]> git.lizzy.rs Git - rust.git/commitdiff
Auto merge of #91275 - camelid:deny-test-warnings, r=jyn514
authorbors <bors@rust-lang.org>
Wed, 1 Dec 2021 16:41:52 +0000 (16:41 +0000)
committerbors <bors@rust-lang.org>
Wed, 1 Dec 2021 16:41:52 +0000 (16:41 +0000)
Deny warnings in rustdoc non-UI tests

These warnings were silently ignored since they did not appear in a
`.stderr` file and did not fail the test. With this change, warnings in
tests are denied, causing the tests to fail if they have warnings.

This change has already led me to find a bug in rustdoc (#91274) and a
useless test (`src/test/rustdoc/primitive/primitive-generic-impl.rs`,
though its uselessness is unrelated to its warnings).

r? `@jyn514`

315 files changed:
Cargo.lock
RELEASES.md
compiler/rustc_ast_passes/src/ast_validation.rs
compiler/rustc_ast_passes/src/lib.rs
compiler/rustc_borrowck/src/diagnostics/mod.rs
compiler/rustc_borrowck/src/renumber.rs
compiler/rustc_borrowck/src/type_check/free_region_relations.rs
compiler/rustc_builtin_macros/src/cfg_eval.rs
compiler/rustc_builtin_macros/src/format.rs
compiler/rustc_codegen_llvm/src/back/write.rs
compiler/rustc_codegen_llvm/src/coverageinfo/mapgen.rs
compiler/rustc_codegen_llvm/src/llvm/ffi.rs
compiler/rustc_codegen_ssa/src/coverageinfo/ffi.rs
compiler/rustc_const_eval/src/interpret/intrinsics.rs
compiler/rustc_const_eval/src/interpret/step.rs
compiler/rustc_const_eval/src/lib.rs
compiler/rustc_const_eval/src/transform/check_consts/check.rs
compiler/rustc_const_eval/src/transform/mod.rs
compiler/rustc_const_eval/src/transform/promote_consts.rs
compiler/rustc_const_eval/src/transform/validate.rs
compiler/rustc_data_structures/src/functor.rs
compiler/rustc_data_structures/src/lib.rs
compiler/rustc_errors/src/emitter.rs
compiler/rustc_infer/src/infer/canonical/canonicalizer.rs
compiler/rustc_infer/src/infer/freshen.rs
compiler/rustc_infer/src/infer/fudge.rs
compiler/rustc_infer/src/infer/mod.rs
compiler/rustc_infer/src/infer/opaque_types.rs
compiler/rustc_infer/src/infer/resolve.rs
compiler/rustc_infer/src/lib.rs
compiler/rustc_infer/src/traits/structural_impls.rs
compiler/rustc_lint/src/builtin.rs
compiler/rustc_lint/src/enum_intrinsics_non_enums.rs
compiler/rustc_lint/src/lib.rs
compiler/rustc_lint/src/non_fmt_panic.rs
compiler/rustc_lint/src/noop_method_call.rs
compiler/rustc_lint/src/types.rs
compiler/rustc_llvm/llvm-wrapper/CoverageMappingWrapper.cpp
compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp
compiler/rustc_macros/src/type_foldable.rs
compiler/rustc_metadata/src/rmeta/encoder.rs
compiler/rustc_middle/src/hir/map/mod.rs
compiler/rustc_middle/src/lib.rs
compiler/rustc_middle/src/macros.rs
compiler/rustc_middle/src/middle/region.rs
compiler/rustc_middle/src/mir/coverage.rs
compiler/rustc_middle/src/mir/interpret/error.rs
compiler/rustc_middle/src/mir/mod.rs
compiler/rustc_middle/src/mir/type_foldable.rs
compiler/rustc_middle/src/mir/visit.rs
compiler/rustc_middle/src/query/mod.rs
compiler/rustc_middle/src/ty/context.rs
compiler/rustc_middle/src/ty/erase_regions.rs
compiler/rustc_middle/src/ty/error.rs
compiler/rustc_middle/src/ty/fold.rs
compiler/rustc_middle/src/ty/instance.rs
compiler/rustc_middle/src/ty/layout.rs
compiler/rustc_middle/src/ty/mod.rs
compiler/rustc_middle/src/ty/normalize_erasing_regions.rs
compiler/rustc_middle/src/ty/print/pretty.rs
compiler/rustc_middle/src/ty/structural_impls.rs
compiler/rustc_middle/src/ty/sty.rs
compiler/rustc_middle/src/ty/subst.rs
compiler/rustc_middle/src/ty/util.rs
compiler/rustc_mir_transform/src/dest_prop.rs
compiler/rustc_mir_transform/src/lib.rs
compiler/rustc_mir_transform/src/reveal_all.rs
compiler/rustc_parse/src/parser/diagnostics.rs
compiler/rustc_parse/src/parser/pat.rs
compiler/rustc_passes/src/check_attr.rs
compiler/rustc_passes/src/lib_features.rs
compiler/rustc_passes/src/reachable.rs
compiler/rustc_passes/src/region.rs
compiler/rustc_passes/src/stability.rs
compiler/rustc_privacy/src/lib.rs
compiler/rustc_resolve/src/diagnostics.rs
compiler/rustc_resolve/src/late/lifetimes.rs
compiler/rustc_resolve/src/lib.rs
compiler/rustc_session/src/config.rs
compiler/rustc_session/src/options.rs
compiler/rustc_span/src/hygiene.rs
compiler/rustc_trait_selection/src/lib.rs
compiler/rustc_trait_selection/src/opaque_types.rs
compiler/rustc_trait_selection/src/traits/auto_trait.rs
compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs
compiler/rustc_trait_selection/src/traits/project.rs
compiler/rustc_trait_selection/src/traits/query/normalize.rs
compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs
compiler/rustc_trait_selection/src/traits/select/mod.rs
compiler/rustc_traits/src/chalk/db.rs
compiler/rustc_traits/src/chalk/lowering.rs
compiler/rustc_traits/src/chalk/mod.rs
compiler/rustc_traits/src/lib.rs
compiler/rustc_traits/src/normalize_erasing_regions.rs
compiler/rustc_ty_utils/src/ty.rs
compiler/rustc_typeck/src/check/check.rs
compiler/rustc_typeck/src/check/coercion.rs
compiler/rustc_typeck/src/check/compare_method.rs
compiler/rustc_typeck/src/check/fn_ctxt/_impl.rs
compiler/rustc_typeck/src/check/method/prelude2021.rs
compiler/rustc_typeck/src/check/mod.rs
compiler/rustc_typeck/src/check/op.rs
compiler/rustc_typeck/src/check/wfcheck.rs
compiler/rustc_typeck/src/check/writeback.rs
compiler/rustc_typeck/src/check_unused.rs
compiler/rustc_typeck/src/coherence/builtin.rs
compiler/rustc_typeck/src/collect.rs
compiler/rustc_typeck/src/collect/type_of.rs
compiler/rustc_typeck/src/hir_wf_check.rs
compiler/rustc_typeck/src/lib.rs
library/alloc/src/raw_vec.rs
library/alloc/src/raw_vec/tests.rs
library/alloc/src/string.rs
library/alloc/src/vec/mod.rs
library/alloc/tests/vec.rs
library/core/src/alloc/layout.rs
library/core/src/fmt/mod.rs
library/core/src/hash/mod.rs
library/core/src/intrinsics.rs
library/core/src/iter/adapters/skip.rs
library/core/src/iter/adapters/take.rs
library/core/src/iter/traits/double_ended.rs
library/core/src/iter/traits/iterator.rs
library/core/src/lib.rs
library/core/src/mem/maybe_uninit.rs
library/core/src/num/nonzero.rs
library/core/src/option.rs
library/core/src/result.rs
library/core/src/str/lossy.rs
library/core/src/str/validations.rs
library/core/tests/iter/adapters/chain.rs
library/core/tests/iter/adapters/flatten.rs
library/core/tests/iter/adapters/skip.rs
library/core/tests/iter/adapters/take.rs
library/core/tests/iter/range.rs
library/core/tests/lib.rs
library/core/tests/mem.rs
library/core/tests/slice.rs
library/std/Cargo.toml
library/std/src/os/windows/fs.rs
library/std/src/sys/unix/android.rs
library/std/src/sys/unix/fd.rs
library/std/src/sys/unix/fs.rs
library/std/src/sys/unix/kernel_copy.rs
library/std/src/sys/unix/net.rs
library/std/src/sys/unix/os.rs
library/std/src/sys/unix/os/tests.rs
library/std/src/sys/unix/process/process_unix.rs
library/std/src/sys/unix/thread.rs
library/std/src/sys/unix/weak.rs
library/std/src/thread/mod.rs
src/bootstrap/lib.rs
src/doc/rustdoc/src/documentation-tests.md
src/doc/rustdoc/src/unstable-features.md
src/doc/unstable-book/src/compiler-flags/instrument-coverage.md
src/librustdoc/clean/auto_trait.rs
src/librustdoc/clean/inline.rs
src/librustdoc/clean/mod.rs
src/librustdoc/clean/types.rs
src/librustdoc/clean/utils.rs
src/librustdoc/config.rs
src/librustdoc/doctest.rs
src/librustdoc/doctest/tests.rs
src/librustdoc/error.rs
src/librustdoc/formats/cache.rs
src/librustdoc/html/format.rs
src/librustdoc/html/layout.rs
src/librustdoc/html/render/cache.rs
src/librustdoc/html/render/context.rs
src/librustdoc/html/render/mod.rs
src/librustdoc/html/render/print_item.rs
src/librustdoc/html/render/write_shared.rs
src/librustdoc/html/static/css/rustdoc.css
src/librustdoc/html/static/js/main.js
src/librustdoc/html/static/js/storage.js
src/librustdoc/html/templates/page.html
src/librustdoc/json/conversions.rs
src/librustdoc/lib.rs
src/librustdoc/markdown.rs
src/librustdoc/scrape_examples.rs
src/librustdoc/visit_ast.rs
src/test/debuginfo/rc_arc.rs
src/test/run-make-fulldeps/coverage-llvmir/Makefile
src/test/run-make-fulldeps/coverage-reports/Makefile
src/test/rustdoc-gui/anchors.goml
src/test/rustdoc-gui/src/test_docs/lib.rs
src/test/rustdoc-ui/display-output.rs
src/test/rustdoc-ui/display-output.stdout
src/test/rustdoc-ui/scrape-examples-ice.rs [new file with mode: 0644]
src/test/rustdoc/doc-notable_trait-slice.rs [new file with mode: 0644]
src/test/rustdoc/static-root-path.rs
src/test/ui-fulldeps/auxiliary/issue-40001-plugin.rs
src/test/ui/associated-types/issue-59324.rs [new file with mode: 0644]
src/test/ui/associated-types/issue-59324.stderr [new file with mode: 0644]
src/test/ui/associated-types/issue-67684.rs [new file with mode: 0644]
src/test/ui/associated-types/issue-69398.rs [new file with mode: 0644]
src/test/ui/associated-types/issue-71113.rs [new file with mode: 0644]
src/test/ui/associated-types/issue-82079.rs [new file with mode: 0644]
src/test/ui/associated-types/issue-85103.rs [new file with mode: 0644]
src/test/ui/associated-types/issue-85103.stderr [new file with mode: 0644]
src/test/ui/associated-types/issue-88856.rs [new file with mode: 0644]
src/test/ui/associated-types/issue-91231.rs [new file with mode: 0644]
src/test/ui/associated-types/issue-91234.rs [new file with mode: 0644]
src/test/ui/borrowck/borrowck-and-init.stderr
src/test/ui/borrowck/borrowck-break-uninit-2.stderr
src/test/ui/borrowck/borrowck-break-uninit.stderr
src/test/ui/borrowck/borrowck-or-init.stderr
src/test/ui/borrowck/borrowck-while-break.stderr
src/test/ui/borrowck/issue-24267-flow-exit.stderr
src/test/ui/borrowck/issue-55492-borrowck-migrate-scans-parents.migrate.stderr
src/test/ui/borrowck/issue-55492-borrowck-migrate-scans-parents.nll.stderr
src/test/ui/borrowck/issue-55492-borrowck-migrate-scans-parents.rs
src/test/ui/borrowck/issue-58776-borrowck-scans-children.migrate.stderr [deleted file]
src/test/ui/closures/2229_closure_analysis/diagnostics/arrays.stderr
src/test/ui/closures/2229_closure_analysis/diagnostics/box.stderr
src/test/ui/closures/2229_closure_analysis/diagnostics/repr_packed.stderr
src/test/ui/closures/2229_closure_analysis/diagnostics/simple-struct-min-capture.stderr
src/test/ui/codemap_tests/tab_3.stderr
src/test/ui/const-generics/generic_const_exprs/issue-72787.min.stderr
src/test/ui/const-generics/generic_const_exprs/issue-72787.rs
src/test/ui/consts/assert-type-intrinsics.rs [new file with mode: 0644]
src/test/ui/consts/assert-type-intrinsics.stderr [new file with mode: 0644]
src/test/ui/consts/assume-type-intrinsics.rs [deleted file]
src/test/ui/consts/assume-type-intrinsics.stderr [deleted file]
src/test/ui/consts/const-cast-different-types.rs
src/test/ui/consts/const-cast-different-types.stderr
src/test/ui/consts/const-cast-wrong-type.rs
src/test/ui/consts/const-cast-wrong-type.stderr
src/test/ui/consts/const-eval/conditional_array_execution.stderr
src/test/ui/consts/const-eval/issue-43197.stderr
src/test/ui/error-codes/E0161.edition.stderr
src/test/ui/error-codes/E0161.migrate.stderr
src/test/ui/error-codes/E0161.nll.stderr
src/test/ui/error-codes/E0161.rs
src/test/ui/error-codes/E0161.zflags.stderr
src/test/ui/fn/implied-bounds-unnorm-associated-type.nll.stderr [new file with mode: 0644]
src/test/ui/fn/implied-bounds-unnorm-associated-type.rs [new file with mode: 0644]
src/test/ui/fn/implied-bounds-unnorm-associated-type.stderr [new file with mode: 0644]
src/test/ui/generator/yield-while-ref-reborrowed.stderr
src/test/ui/generic-associated-types/equality-bound.rs [new file with mode: 0644]
src/test/ui/generic-associated-types/equality-bound.stderr [new file with mode: 0644]
src/test/ui/generic-associated-types/issue-87748.rs [deleted file]
src/test/ui/generic-associated-types/missing-bounds.fixed
src/test/ui/generic-associated-types/missing-bounds.rs
src/test/ui/generic-associated-types/missing-bounds.stderr
src/test/ui/higher-rank-trait-bounds/issue-88586-hr-self-outlives-in-trait-def.rs [new file with mode: 0644]
src/test/ui/higher-rank-trait-bounds/issue-88586-hr-self-outlives-in-trait-def.stderr [new file with mode: 0644]
src/test/ui/higher-rank-trait-bounds/normalize-under-binder/issue-71955.migrate.stderr
src/test/ui/higher-rank-trait-bounds/normalize-under-binder/issue-71955.nll.stderr
src/test/ui/higher-rank-trait-bounds/normalize-under-binder/issue-71955.rs
src/test/ui/hrtb/issue-30786.migrate.stderr
src/test/ui/hrtb/issue-30786.nll.stderr
src/test/ui/hrtb/issue-30786.rs
src/test/ui/impl-trait/issues/issue-86201.rs
src/test/ui/issues/issue-16538.mir.stderr
src/test/ui/issues/issue-16538.rs
src/test/ui/issues/issue-16538.thir.stderr
src/test/ui/issues/issue-17718-static-sync.stderr
src/test/ui/issues/issue-24446.rs
src/test/ui/issues/issue-24446.stderr
src/test/ui/issues/issue-42796.stderr
src/test/ui/issues/issue-47646.stderr
src/test/ui/issues/issue-5216.rs
src/test/ui/issues/issue-5216.stderr
src/test/ui/issues/issue-7364.rs
src/test/ui/issues/issue-7364.stderr
src/test/ui/issues/issue-77919.rs
src/test/ui/issues/issue-77919.stderr
src/test/ui/limits/issue-55878.stderr
src/test/ui/lint/unused/unused-doc-comments-edge-cases.rs
src/test/ui/lint/unused/unused-doc-comments-edge-cases.stderr
src/test/ui/liveness/liveness-move-in-while.stderr
src/test/ui/liveness/liveness-use-after-move.stderr
src/test/ui/liveness/liveness-use-after-send.stderr
src/test/ui/loops/loop-proper-liveness.stderr
src/test/ui/moves/moves-based-on-type-capture-clause-bad.stderr
src/test/ui/optimization-remark.rs [new file with mode: 0644]
src/test/ui/parser/issues/issue-87086-colon-path-sep.rs
src/test/ui/parser/issues/issue-87086-colon-path-sep.stderr
src/test/ui/regions/regions-assoc-type-in-supertrait-outlives-container.migrate.nll.stderr [deleted file]
src/test/ui/regions/regions-assoc-type-in-supertrait-outlives-container.migrate.stderr
src/test/ui/regions/regions-assoc-type-in-supertrait-outlives-container.nll.stderr
src/test/ui/regions/regions-assoc-type-in-supertrait-outlives-container.rs
src/test/ui/regions/regions-free-region-ordering-caller.migrate.nll.stderr [deleted file]
src/test/ui/regions/regions-free-region-ordering-caller.migrate.stderr
src/test/ui/regions/regions-free-region-ordering-caller.nll.stderr
src/test/ui/regions/regions-free-region-ordering-caller.rs
src/test/ui/regions/regions-outlives-projection-container-hrtb.migrate.nll.stderr [deleted file]
src/test/ui/regions/regions-outlives-projection-container-hrtb.migrate.stderr
src/test/ui/regions/regions-outlives-projection-container-hrtb.nll.stderr
src/test/ui/regions/regions-outlives-projection-container-hrtb.rs
src/test/ui/regions/regions-outlives-projection-container-wc.migrate.nll.stderr [deleted file]
src/test/ui/regions/regions-outlives-projection-container-wc.migrate.stderr
src/test/ui/regions/regions-outlives-projection-container-wc.nll.stderr
src/test/ui/regions/regions-outlives-projection-container-wc.rs
src/test/ui/rfc-2008-non-exhaustive/auxiliary/enums.rs
src/test/ui/rfc-2008-non-exhaustive/enum-as-cast.rs [new file with mode: 0644]
src/test/ui/rfc1623.nll.stderr
src/test/ui/rfc1623.rs
src/test/ui/rfc1623.stderr
src/test/ui/try-block/try-block-maybe-bad-lifetime.stderr
src/test/ui/type-alias-impl-trait/static-const-types.rs
src/test/ui/type-alias-impl-trait/static-const-types.stderr
src/test/ui/use/use-after-move-based-on-type.stderr
src/test/ui/walk-struct-literal-with.stderr
src/tools/cargo
src/tools/clippy/clippy_lints/src/derive.rs
src/tools/clippy/clippy_lints/src/methods/mod.rs
src/tools/clippy/clippy_lints/src/non_copy_const.rs
src/tools/clippy/clippy_lints/src/self_named_constructors.rs
src/tools/clippy/clippy_lints/src/unused_self.rs
src/tools/clippy/tests/ui/crashes/ice-6252.stderr
src/tools/miri
src/tools/rust-analyzer
src/version

index edc227d9db7baee9b5cd3dc306efc73915ea90be..2233162be3b6b464749f9d474f7d189064dbcd10 100644 (file)
@@ -678,9 +678,9 @@ dependencies = [
 
 [[package]]
 name = "compiler_builtins"
-version = "0.1.52"
+version = "0.1.55"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b6591c2442ee984e2b264638a8b5e7ae44fd47b32d28e3a08e2e9c3cdb0c2fb0"
+checksum = "c9ac60765140c97aaf531dae151a287646b0805ec725805da9e2a3ee31cd501c"
 dependencies = [
  "cc",
  "rustc-std-workspace-core",
@@ -1900,9 +1900,9 @@ checksum = "830d08ce1d1d941e6b30645f1a0eb5643013d835ce3779a5fc208261dbe10f55"
 
 [[package]]
 name = "libc"
-version = "0.2.106"
+version = "0.2.108"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a60553f9a9e039a333b4e9b20573b9e9b9c0bb3a11e201ccc48ef4283456d673"
+checksum = "8521a1b57e76b1ec69af7599e75e38e7b7fad6610f037db8c79b127201b5d119"
 dependencies = [
  "rustc-std-workspace-core",
 ]
index a38ab7cabf468c39aace386fb49321579be2dc22..4b9b20f4cba606cd75ecb00ceab7ca2ba7894f6a 100644 (file)
@@ -1,3 +1,117 @@
+Version 1.57.0 (2021-12-02)
+==========================
+
+Language
+--------
+
+- [Macro attributes may follow `#[derive]` and will see the original (pre-`cfg`) input.][87220]
+- [Accept curly-brace macros in expressions, like `m!{ .. }.method()` and `m!{ .. }?`.][88690]
+- [Allow panicking in constant evaluation.][89508]
+
+Compiler
+--------
+
+- [Create more accurate debuginfo for vtables.][89597]
+- [Add `armv6k-nintendo-3ds` at Tier 3\*.][88529]
+- [Add `armv7-unknown-linux-uclibceabihf` at Tier 3\*.][88952]
+- [Add `m68k-unknown-linux-gnu` at Tier 3\*.][88321]
+- [Add SOLID targets at Tier 3\*:][86191] `aarch64-kmc-solid_asp3`, `armv7a-kmc-solid_asp3-eabi`, `armv7a-kmc-solid_asp3-eabihf`
+
+\* Refer to Rust's [platform support page][platform-support-doc] for more
+   information on Rust's tiered platform support.
+
+Libraries
+---------
+
+- [Avoid allocations and copying in `Vec::leak`][89337]
+- [Add `#[repr(i8)]` to `Ordering`][89507]
+- [Optimize `File::read_to_end` and `read_to_string`][89582]
+- [Update to Unicode 14.0][89614]
+- [Many more functions are marked `#[must_use]`][89692], producing a warning
+  when ignoring their return value. This helps catch mistakes such as expecting
+  a function to mutate a value in place rather than return a new value.
+
+Stabilised APIs
+---------------
+
+- [`[T; N]::as_mut_slice`][`array::as_mut_slice`]
+- [`[T; N]::as_slice`][`array::as_slice`]
+- [`collections::TryReserveError`]
+- [`HashMap::try_reserve`]
+- [`HashSet::try_reserve`]
+- [`String::try_reserve`]
+- [`String::try_reserve_exact`]
+- [`Vec::try_reserve`]
+- [`Vec::try_reserve_exact`]
+- [`VecDeque::try_reserve`]
+- [`VecDeque::try_reserve_exact`]
+- [`Iterator::map_while`]
+- [`iter::MapWhile`]
+- [`proc_macro::is_available`]
+- [`Command::get_program`]
+- [`Command::get_args`]
+- [`Command::get_envs`]
+- [`Command::get_current_dir`]
+- [`CommandArgs`]
+- [`CommandEnvs`]
+
+These APIs are now usable in const contexts:
+
+- [`hint::unreachable_unchecked`]
+
+Cargo
+-----
+
+- [Stabilize custom profiles][cargo/9943]
+
+Compatibility notes
+-------------------
+
+Internal changes
+----------------
+These changes provide no direct user facing benefits, but represent significant
+improvements to the internals and overall performance of rustc
+and related tools.
+
+- [Added an experimental backend for codegen with `libgccjit`.][87260]
+
+[86191]: https://github.com/rust-lang/rust/pull/86191/
+[87220]: https://github.com/rust-lang/rust/pull/87220/
+[87260]: https://github.com/rust-lang/rust/pull/87260/
+[88243]: https://github.com/rust-lang/rust/pull/88243/
+[88321]: https://github.com/rust-lang/rust/pull/88321/
+[88529]: https://github.com/rust-lang/rust/pull/88529/
+[88690]: https://github.com/rust-lang/rust/pull/88690/
+[88952]: https://github.com/rust-lang/rust/pull/88952/
+[89337]: https://github.com/rust-lang/rust/pull/89337/
+[89507]: https://github.com/rust-lang/rust/pull/89507/
+[89508]: https://github.com/rust-lang/rust/pull/89508/
+[89582]: https://github.com/rust-lang/rust/pull/89582/
+[89597]: https://github.com/rust-lang/rust/pull/89597/
+[89614]: https://github.com/rust-lang/rust/pull/89614/
+[89692]: https://github.com/rust-lang/rust/issues/89692/
+[cargo/9943]: https://github.com/rust-lang/cargo/pull/9943/
+[`array::as_mut_slice`]: https://doc.rust-lang.org/std/primitive.array.html#method.as_mut_slice
+[`array::as_slice`]: https://doc.rust-lang.org/std/primitive.array.html#method.as_slice
+[`collections::TryReserveError`]: https://doc.rust-lang.org/std/collections/struct.TryReserveError.html
+[`HashMap::try_reserve`]: https://doc.rust-lang.org/std/collections/hash_map/struct.HashMap.html#method.try_reserve
+[`HashSet::try_reserve`]: https://doc.rust-lang.org/std/collections/hash_set/struct.HashSet.html#method.try_reserve
+[`String::try_reserve`]: https://doc.rust-lang.org/alloc/string/struct.String.html#method.try_reserve
+[`String::try_reserve_exact`]: https://doc.rust-lang.org/alloc/string/struct.String.html#method.try_reserve_exact
+[`Vec::try_reserve`]: https://doc.rust-lang.org/std/vec/struct.Vec.html#method.try_reserve
+[`Vec::try_reserve_exact`]: https://doc.rust-lang.org/std/vec/struct.Vec.html#method.try_reserve_exact
+[`VecDeque::try_reserve`]: https://doc.rust-lang.org/std/collections/struct.VecDeque.html#method.try_reserve
+[`VecDeque::try_reserve_exact`]: https://doc.rust-lang.org/std/collections/struct.VecDeque.html#method.try_reserve_exact
+[`Iterator::map_while`]: https://doc.rust-lang.org/std/iter/trait.Iterator.html#method.map_while
+[`iter::MapWhile`]: https://doc.rust-lang.org/std/iter/struct.MapWhile.html
+[`proc_macro::is_available`]: https://doc.rust-lang.org/proc_macro/fn.is_available.html
+[`Command::get_program`]: https://doc.rust-lang.org/std/process/struct.Command.html#method.get_program
+[`Command::get_args`]: https://doc.rust-lang.org/std/process/struct.Command.html#method.get_args
+[`Command::get_envs`]: https://doc.rust-lang.org/std/process/struct.Command.html#method.get_envs
+[`Command::get_current_dir`]: https://doc.rust-lang.org/std/process/struct.Command.html#method.get_current_dir
+[`CommandArgs`]: https://doc.rust-lang.org/std/process/struct.CommandArgs.html
+[`CommandEnvs`]: https://doc.rust-lang.org/std/process/struct.CommandEnvs.html
+
 Version 1.56.1 (2021-11-01)
 ===========================
 
index 1822ba6ec996493d952d217a25fa39253c5c383a..efc30121987e289389fb54525bf191035a814efb 100644 (file)
@@ -23,7 +23,7 @@
 use rustc_span::Span;
 use rustc_target::spec::abi;
 use std::mem;
-use std::ops::DerefMut;
+use std::ops::{Deref, DerefMut};
 
 const MORE_EXTERN: &str =
     "for more information, visit https://doc.rust-lang.org/std/keyword.extern.html";
@@ -1714,6 +1714,53 @@ fn deny_equality_constraints(
             }
         }
     }
+    // Given `A: Foo, A::Bar = RhsTy`, suggest `A: Foo<Bar = RhsTy>`.
+    if let TyKind::Path(None, full_path) = &predicate.lhs_ty.kind {
+        if let [potential_param, potential_assoc] = &full_path.segments[..] {
+            for param in &generics.params {
+                if param.ident == potential_param.ident {
+                    for bound in &param.bounds {
+                        if let ast::GenericBound::Trait(trait_ref, TraitBoundModifier::None) = bound
+                        {
+                            if let [trait_segment] = &trait_ref.trait_ref.path.segments[..] {
+                                let assoc = pprust::path_to_string(&ast::Path::from_ident(
+                                    potential_assoc.ident,
+                                ));
+                                let ty = pprust::ty_to_string(&predicate.rhs_ty);
+                                let (args, span) = match &trait_segment.args {
+                                    Some(args) => match args.deref() {
+                                        ast::GenericArgs::AngleBracketed(args) => {
+                                            let Some(arg) = args.args.last() else {
+                                                continue;
+                                            };
+                                            (
+                                                format!(", {} = {}", assoc, ty),
+                                                arg.span().shrink_to_hi(),
+                                            )
+                                        }
+                                        _ => continue,
+                                    },
+                                    None => (
+                                        format!("<{} = {}>", assoc, ty),
+                                        trait_segment.span().shrink_to_hi(),
+                                    ),
+                                };
+                                err.multipart_suggestion(
+                                    &format!(
+                                        "if `{}::{}` is an associated type you're trying to set, \
+                                        use the associated type binding syntax",
+                                        trait_segment.ident, potential_assoc.ident,
+                                    ),
+                                    vec![(span, args), (predicate.span, String::new())],
+                                    Applicability::MaybeIncorrect,
+                                );
+                            }
+                        }
+                    }
+                }
+            }
+        }
+    }
     err.note(
         "see issue #20041 <https://github.com/rust-lang/rust/issues/20041> for more information",
     );
index 47666670b2b63dbb2f2fbbe714e278011e1da4d7..adc4d117b805f587e349d4f8294fefe0731d4a00 100644 (file)
@@ -6,6 +6,7 @@
 
 #![feature(iter_is_partitioned)]
 #![feature(box_patterns)]
+#![feature(let_else)]
 #![recursion_limit = "256"]
 
 pub mod ast_validation;
index 79623e26eb710d304d4556ad30a335aa42a07fbe..42f5d557542088a10d3da5cb673a85f494cd66e7 100644 (file)
@@ -738,15 +738,13 @@ pub(super) fn describe_for_unnamed_place(&self, tcx: TyCtxt<'_>) -> String {
             BorrowedContentSource::DerefRawPointer => "a raw pointer".to_string(),
             BorrowedContentSource::DerefSharedRef => "a shared reference".to_string(),
             BorrowedContentSource::DerefMutableRef => "a mutable reference".to_string(),
-            BorrowedContentSource::OverloadedDeref(ty) => match ty.kind() {
-                ty::Adt(def, _) if tcx.is_diagnostic_item(sym::Rc, def.did) => {
-                    "an `Rc`".to_string()
-                }
-                ty::Adt(def, _) if tcx.is_diagnostic_item(sym::Arc, def.did) => {
-                    "an `Arc`".to_string()
-                }
-                _ => format!("dereference of `{}`", ty),
-            },
+            BorrowedContentSource::OverloadedDeref(ty) => ty
+                .ty_adt_def()
+                .and_then(|adt| match tcx.get_diagnostic_name(adt.did)? {
+                    name @ (sym::Rc | sym::Arc) => Some(format!("an `{}`", name)),
+                    _ => None,
+                })
+                .unwrap_or_else(|| format!("dereference of `{}`", ty)),
             BorrowedContentSource::OverloadedIndex(ty) => format!("index of `{}`", ty),
         }
     }
@@ -770,15 +768,13 @@ pub(super) fn describe_for_immutable_place(&self, tcx: TyCtxt<'_>) -> String {
             BorrowedContentSource::DerefMutableRef => {
                 bug!("describe_for_immutable_place: DerefMutableRef isn't immutable")
             }
-            BorrowedContentSource::OverloadedDeref(ty) => match ty.kind() {
-                ty::Adt(def, _) if tcx.is_diagnostic_item(sym::Rc, def.did) => {
-                    "an `Rc`".to_string()
-                }
-                ty::Adt(def, _) if tcx.is_diagnostic_item(sym::Arc, def.did) => {
-                    "an `Arc`".to_string()
-                }
-                _ => format!("a dereference of `{}`", ty),
-            },
+            BorrowedContentSource::OverloadedDeref(ty) => ty
+                .ty_adt_def()
+                .and_then(|adt| match tcx.get_diagnostic_name(adt.did)? {
+                    name @ (sym::Rc | sym::Arc) => Some(format!("an `{}`", name)),
+                    _ => None,
+                })
+                .unwrap_or_else(|| format!("dereference of `{}`", ty)),
             BorrowedContentSource::OverloadedIndex(ty) => format!("an index of `{}`", ty),
         }
     }
@@ -960,8 +956,7 @@ pub(super) fn move_spans(
                         _ => None,
                     });
                 let is_option_or_result = parent_self_ty.map_or(false, |def_id| {
-                    tcx.is_diagnostic_item(sym::Option, def_id)
-                        || tcx.is_diagnostic_item(sym::Result, def_id)
+                    matches!(tcx.get_diagnostic_name(def_id), Some(sym::Option | sym::Result))
                 });
                 FnSelfUseKind::Normal { self_arg, implicit_into_iter, is_option_or_result }
             });
index 20567610f6557895076e7a79ef877d3259df641b..4b6cab24cdb70457537d01f21608a3cacea06e68 100644 (file)
@@ -1,7 +1,7 @@
 use rustc_index::vec::IndexVec;
 use rustc_infer::infer::{InferCtxt, NllRegionVariableOrigin};
 use rustc_middle::mir::visit::{MutVisitor, TyContext};
-use rustc_middle::mir::{Body, Location, PlaceElem, Promoted};
+use rustc_middle::mir::{Body, Location, Promoted};
 use rustc_middle::ty::subst::SubstsRef;
 use rustc_middle::ty::{self, Ty, TyCtxt, TypeFoldable};
 
@@ -62,22 +62,6 @@ fn visit_ty(&mut self, ty: &mut Ty<'tcx>, ty_context: TyContext) {
         debug!(?ty);
     }
 
-    fn process_projection_elem(
-        &mut self,
-        elem: PlaceElem<'tcx>,
-        _: Location,
-    ) -> Option<PlaceElem<'tcx>> {
-        if let PlaceElem::Field(field, ty) = elem {
-            let new_ty = self.renumber_regions(ty);
-
-            if new_ty != ty {
-                return Some(PlaceElem::Field(field, new_ty));
-            }
-        }
-
-        None
-    }
-
     #[instrument(skip(self), level = "debug")]
     fn visit_substs(&mut self, substs: &mut SubstsRef<'tcx>, location: Location) {
         *substs = self.renumber_regions(*substs);
index f71cf09ecf6304941c6fb6d2a04497185ed0ad58..8d97c3cbb0b0ebd406fa9301d91827a36c08617d 100644 (file)
@@ -256,7 +256,6 @@ impl UniversalRegionRelationsBuilder<'cx, 'tcx> {
                 debug!("build: input_or_output={:?}", ty);
                 // We add implied bounds from both the unnormalized and normalized ty
                 // See issue #87748
-                let constraints_implied_1 = self.add_implied_bounds(ty);
                 let TypeOpOutput { output: norm_ty, constraints: constraints1, .. } = self
                     .param_env
                     .and(type_op::normalize::Normalize::new(ty))
@@ -284,10 +283,9 @@ impl UniversalRegionRelationsBuilder<'cx, 'tcx> {
                 // }
                 // ```
                 // Both &Self::Bar and &() are WF
-                let constraints_implied_2 =
-                    if ty != norm_ty { self.add_implied_bounds(norm_ty) } else { None };
+                let constraints_implied = self.add_implied_bounds(norm_ty);
                 normalized_inputs_and_output.push(norm_ty);
-                constraints1.into_iter().chain(constraints_implied_1).chain(constraints_implied_2)
+                constraints1.into_iter().chain(constraints_implied)
             })
             .collect();
 
index 307730f7f5f14a9f88f4f627fe2a3b03f84fc3e8..8cc761dfd513aa73da18d9136d4c6ff64233e495 100644 (file)
@@ -11,7 +11,7 @@
 use rustc_expand::config::StripUnconfigured;
 use rustc_expand::configure;
 use rustc_feature::Features;
-use rustc_parse::parser::ForceCollect;
+use rustc_parse::parser::{ForceCollect, Parser};
 use rustc_session::utils::FlattenNonterminals;
 use rustc_session::Session;
 use rustc_span::symbol::sym;
@@ -138,8 +138,34 @@ fn configure_annotatable(&mut self, mut annotatable: Annotatable) -> Option<Anno
         // the location of `#[cfg]` and `#[cfg_attr]` in the token stream. The tokenization
         // process is lossless, so this process is invisible to proc-macros.
 
-        // FIXME - get rid of this clone
-        let nt = annotatable.clone().into_nonterminal();
+        let parse_annotatable_with: fn(&mut Parser<'_>) -> _ = match annotatable {
+            Annotatable::Item(_) => {
+                |parser| Annotatable::Item(parser.parse_item(ForceCollect::Yes).unwrap().unwrap())
+            }
+            Annotatable::TraitItem(_) => |parser| {
+                Annotatable::TraitItem(
+                    parser.parse_trait_item(ForceCollect::Yes).unwrap().unwrap().unwrap(),
+                )
+            },
+            Annotatable::ImplItem(_) => |parser| {
+                Annotatable::ImplItem(
+                    parser.parse_impl_item(ForceCollect::Yes).unwrap().unwrap().unwrap(),
+                )
+            },
+            Annotatable::ForeignItem(_) => |parser| {
+                Annotatable::ForeignItem(
+                    parser.parse_foreign_item(ForceCollect::Yes).unwrap().unwrap().unwrap(),
+                )
+            },
+            Annotatable::Stmt(_) => |parser| {
+                Annotatable::Stmt(P(parser.parse_stmt(ForceCollect::Yes).unwrap().unwrap()))
+            },
+            Annotatable::Expr(_) => {
+                |parser| Annotatable::Expr(parser.parse_expr_force_collect().unwrap())
+            }
+            _ => unreachable!(),
+        };
+        let nt = annotatable.into_nonterminal();
 
         let mut orig_tokens = rustc_parse::nt_to_tokenstream(
             &nt,
@@ -173,25 +199,7 @@ fn configure_annotatable(&mut self, mut annotatable: Annotatable) -> Option<Anno
         let mut parser =
             rustc_parse::stream_to_parser(&self.cfg.sess.parse_sess, orig_tokens, None);
         parser.capture_cfg = true;
-        annotatable = match annotatable {
-            Annotatable::Item(_) => {
-                Annotatable::Item(parser.parse_item(ForceCollect::Yes).unwrap().unwrap())
-            }
-            Annotatable::TraitItem(_) => Annotatable::TraitItem(
-                parser.parse_trait_item(ForceCollect::Yes).unwrap().unwrap().unwrap(),
-            ),
-            Annotatable::ImplItem(_) => Annotatable::ImplItem(
-                parser.parse_impl_item(ForceCollect::Yes).unwrap().unwrap().unwrap(),
-            ),
-            Annotatable::ForeignItem(_) => Annotatable::ForeignItem(
-                parser.parse_foreign_item(ForceCollect::Yes).unwrap().unwrap().unwrap(),
-            ),
-            Annotatable::Stmt(_) => {
-                Annotatable::Stmt(P(parser.parse_stmt(ForceCollect::Yes).unwrap().unwrap()))
-            }
-            Annotatable::Expr(_) => Annotatable::Expr(parser.parse_expr_force_collect().unwrap()),
-            _ => unreachable!(),
-        };
+        annotatable = parse_annotatable_with(&mut parser);
 
         // Now that we have our re-parsed `AttrAnnotatedTokenStream`, recursively configuring
         // our attribute target will correctly the tokens as well.
index 097eaddb874083ec2895f553eaf16fecfff555ef..62a55c0e49ed08ed94a0263688f01e6ceedba9ba 100644 (file)
@@ -88,8 +88,8 @@ struct Context<'a, 'b> {
     /// * Implicit argument resolution: `"{1:.0$} {2:.foo$} {1:.3$} {4:.0$}"`
     /// * Name resolution: `"{1:.0$} {2:.5$} {1:.3$} {4:.0$}"`
     /// * `count_positions` (in JSON): `{0: 0, 5: 1, 3: 2}`
-    /// * `count_args`: `vec![Exact(0), Exact(5), Exact(3)]`
-    count_args: Vec<Position>,
+    /// * `count_args`: `vec![0, 5, 3]`
+    count_args: Vec<usize>,
     /// Relative slot numbers for count arguments.
     count_positions: FxHashMap<usize, usize>,
     /// Number of count slots assigned.
@@ -513,7 +513,7 @@ fn verify_arg_type(&mut self, arg: Position, ty: ArgumentType) {
                         if let Entry::Vacant(e) = self.count_positions.entry(arg) {
                             let i = self.count_positions_count;
                             e.insert(i);
-                            self.count_args.push(Exact(arg));
+                            self.count_args.push(arg);
                             self.count_positions_count += 1;
                         }
                     }
@@ -769,13 +769,12 @@ fn into_expr(self) -> P<ast::Expr> {
             for arg_ty in self.arg_unique_types[i].iter() {
                 args.push(Context::format_arg(self.ecx, self.macsp, e.span, arg_ty, i));
             }
-            heads.push(self.ecx.expr_addr_of(e.span, e));
+            // use the arg span for `&arg` so that borrowck errors
+            // point to the specific expression passed to the macro
+            // (the span is otherwise unavailable in MIR)
+            heads.push(self.ecx.expr_addr_of(e.span.with_ctxt(self.macsp.ctxt()), e));
         }
-        for pos in self.count_args {
-            let index = match pos {
-                Exact(i) => i,
-                _ => panic!("should never happen"),
-            };
+        for index in self.count_args {
             let span = spans_pos[index];
             args.push(Context::format_arg(self.ecx, self.macsp, span, &Count, index));
         }
index 3d05fc15b38f4121c22f737cccc040d78f734db2..460a8cc69128e9f72c2b64f9977b8e185a4712f0 100644 (file)
@@ -259,6 +259,7 @@ pub(crate) fn save_temp_bitcode(
 pub struct DiagnosticHandlers<'a> {
     data: *mut (&'a CodegenContext<LlvmCodegenBackend>, &'a Handler),
     llcx: &'a llvm::Context,
+    old_handler: Option<&'a llvm::DiagnosticHandler>,
 }
 
 impl<'a> DiagnosticHandlers<'a> {
@@ -267,12 +268,35 @@ pub fn new(
         handler: &'a Handler,
         llcx: &'a llvm::Context,
     ) -> Self {
+        let remark_passes_all: bool;
+        let remark_passes: Vec<CString>;
+        match &cgcx.remark {
+            Passes::All => {
+                remark_passes_all = true;
+                remark_passes = Vec::new();
+            }
+            Passes::Some(passes) => {
+                remark_passes_all = false;
+                remark_passes =
+                    passes.iter().map(|name| CString::new(name.as_str()).unwrap()).collect();
+            }
+        };
+        let remark_passes: Vec<*const c_char> =
+            remark_passes.iter().map(|name: &CString| name.as_ptr()).collect();
         let data = Box::into_raw(Box::new((cgcx, handler)));
         unsafe {
+            let old_handler = llvm::LLVMRustContextGetDiagnosticHandler(llcx);
+            llvm::LLVMRustContextConfigureDiagnosticHandler(
+                llcx,
+                diagnostic_handler,
+                data.cast(),
+                remark_passes_all,
+                remark_passes.as_ptr(),
+                remark_passes.len(),
+            );
             llvm::LLVMRustSetInlineAsmDiagnosticHandler(llcx, inline_asm_handler, data.cast());
-            llvm::LLVMContextSetDiagnosticHandler(llcx, diagnostic_handler, data.cast());
+            DiagnosticHandlers { data, llcx, old_handler }
         }
-        DiagnosticHandlers { data, llcx }
     }
 }
 
@@ -281,7 +305,7 @@ fn drop(&mut self) {
         use std::ptr::null_mut;
         unsafe {
             llvm::LLVMRustSetInlineAsmDiagnosticHandler(self.llcx, inline_asm_handler, null_mut());
-            llvm::LLVMContextSetDiagnosticHandler(self.llcx, diagnostic_handler, null_mut());
+            llvm::LLVMRustContextSetDiagnosticHandler(self.llcx, self.old_handler);
             drop(Box::from_raw(self.data));
         }
     }
@@ -337,13 +361,8 @@ fn report_inline_asm(
 
             if enabled {
                 diag_handler.note_without_error(&format!(
-                    "optimization {} for {} at {}:{}:{}: {}",
-                    opt.kind.describe(),
-                    opt.pass_name,
-                    opt.filename,
-                    opt.line,
-                    opt.column,
-                    opt.message
+                    "{}:{}:{}: {}: {}",
+                    opt.filename, opt.line, opt.column, opt.pass_name, opt.message,
                 ));
             }
         }
index 6830864ba04b4e9271a630df3f1f09af993dd66d..0390caaec33e55ef40f8710c521cd56134837e88 100644 (file)
@@ -9,6 +9,7 @@
 use rustc_hir::def_id::{DefId, DefIdSet};
 use rustc_llvm::RustString;
 use rustc_middle::mir::coverage::CodeRegion;
+use rustc_middle::ty::TyCtxt;
 use rustc_span::Symbol;
 
 use std::ffi::CString;
 
 /// Generates and exports the Coverage Map.
 ///
-/// This Coverage Map complies with Coverage Mapping Format version 4 (zero-based encoded as 3),
-/// as defined at [LLVM Code Coverage Mapping Format](https://github.com/rust-lang/llvm-project/blob/rustc/11.0-2020-10-12/llvm/docs/CoverageMappingFormat.rst#llvm-code-coverage-mapping-format)
-/// and published in Rust's November 2020 fork of LLVM. This version is supported by the LLVM
-/// coverage tools (`llvm-profdata` and `llvm-cov`) bundled with Rust's fork of LLVM.
+/// Rust Coverage Map generation supports LLVM Coverage Mapping Format versions
+/// 5 (LLVM 12, only) and 6 (zero-based encoded as 4 and 5, respectively), as defined at
+/// [LLVM Code Coverage Mapping Format](https://github.com/rust-lang/llvm-project/blob/rustc/13.0-2021-09-30/llvm/docs/CoverageMappingFormat.rst#llvm-code-coverage-mapping-format).
+/// These versions are supported by the LLVM coverage tools (`llvm-profdata` and `llvm-cov`)
+/// bundled with Rust's fork of LLVM.
 ///
 /// Consequently, Rust's bundled version of Clang also generates Coverage Maps compliant with
 /// the same version. Clang's implementation of Coverage Map generation was referenced when
 pub fn finalize<'ll, 'tcx>(cx: &CodegenCx<'ll, 'tcx>) {
     let tcx = cx.tcx;
 
-    // Ensure LLVM supports Coverage Map Version 4 (encoded as a zero-based value: 3).
-    // If not, the LLVM Version must be less than 11.
+    // Ensure the installed version of LLVM supports at least Coverage Map
+    // Version 5 (encoded as a zero-based value: 4), which was introduced with
+    // LLVM 12.
     let version = coverageinfo::mapping_version();
-    if version != 3 {
-        tcx.sess.fatal("rustc option `-Z instrument-coverage` requires LLVM 11 or higher.");
+    if version < 4 {
+        tcx.sess.fatal("rustc option `-Z instrument-coverage` requires LLVM 12 or higher.");
     }
 
     debug!("Generating coverage map for CodegenUnit: `{}`", cx.codegen_unit.name());
@@ -57,7 +60,7 @@ pub fn finalize<'ll, 'tcx>(cx: &CodegenCx<'ll, 'tcx>) {
         return;
     }
 
-    let mut mapgen = CoverageMapGenerator::new();
+    let mut mapgen = CoverageMapGenerator::new(tcx, version);
 
     // Encode coverage mappings and generate function records
     let mut function_data = Vec::new();
@@ -112,8 +115,26 @@ struct CoverageMapGenerator {
 }
 
 impl CoverageMapGenerator {
-    fn new() -> Self {
-        Self { filenames: FxIndexSet::default() }
+    fn new(tcx: TyCtxt<'_>, version: u32) -> Self {
+        let mut filenames = FxIndexSet::default();
+        if version >= 5 {
+            // LLVM Coverage Mapping Format version 6 (zero-based encoded as 5)
+            // requires setting the first filename to the compilation directory.
+            // Since rustc generates coverage maps with relative paths, the
+            // compilation directory can be combined with the the relative paths
+            // to get absolute paths, if needed.
+            let working_dir = tcx
+                .sess
+                .opts
+                .working_dir
+                .remapped_path_if_available()
+                .to_string_lossy()
+                .to_string();
+            let c_filename =
+                CString::new(working_dir).expect("null error converting filename to C string");
+            filenames.insert(c_filename);
+        }
+        Self { filenames }
     }
 
     /// Using the `expressions` and `counter_regions` collected for the current function, generate
index 1d255c075598078f616ef704c1470bcb4d064a33..2ef4c871825cbdc6f28881a01aac9abe43677033 100644 (file)
@@ -675,13 +675,17 @@ struct 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);
+extern "C" {
+    pub type DiagnosticHandler;
+}
+
+pub type DiagnosticHandlerTy = unsafe extern "C" fn(&DiagnosticInfo, *mut c_void);
+pub type InlineAsmDiagHandlerTy = unsafe extern "C" fn(&SMDiagnostic, *const c_void, c_uint);
 
 pub mod coverageinfo {
     use super::coverage_map;
 
-    /// Aligns with [llvm::coverage::CounterMappingRegion::RegionKind](https://github.com/rust-lang/llvm-project/blob/rustc/11.0-2020-10-12/llvm/include/llvm/ProfileData/Coverage/CoverageMapping.h#L206-L222)
+    /// Aligns with [llvm::coverage::CounterMappingRegion::RegionKind](https://github.com/rust-lang/llvm-project/blob/rustc/13.0-2021-09-30/llvm/include/llvm/ProfileData/Coverage/CoverageMapping.h#L209-L230)
     #[derive(Copy, Clone, Debug)]
     #[repr(C)]
     pub enum RegionKind {
@@ -700,11 +704,16 @@ pub enum RegionKind {
         /// A GapRegion is like a CodeRegion, but its count is only set as the
         /// line execution count when its the only region in the line.
         GapRegion = 3,
+
+        /// A BranchRegion represents leaf-level boolean expressions and is
+        /// associated with two counters, each representing the number of times the
+        /// expression evaluates to true or false.
+        BranchRegion = 4,
     }
 
     /// This struct provides LLVM's representation of a "CoverageMappingRegion", encoded into the
     /// coverage map, in accordance with the
-    /// [LLVM Code Coverage Mapping Format](https://github.com/rust-lang/llvm-project/blob/rustc/11.0-2020-10-12/llvm/docs/CoverageMappingFormat.rst#llvm-code-coverage-mapping-format).
+    /// [LLVM Code Coverage Mapping Format](https://github.com/rust-lang/llvm-project/blob/rustc/13.0-2021-09-30/llvm/docs/CoverageMappingFormat.rst#llvm-code-coverage-mapping-format).
     /// The struct composes fields representing the `Counter` type and value(s) (injected counter
     /// ID, or expression type and operands), the source file (an indirect index into a "filenames
     /// array", encoded separately), and source location (start and end positions of the represented
@@ -717,6 +726,10 @@ pub struct CounterMappingRegion {
         /// The counter type and type-dependent counter data, if any.
         counter: coverage_map::Counter,
 
+        /// If the `RegionKind` is a `BranchRegion`, this represents the counter
+        /// for the false branch of the region.
+        false_counter: coverage_map::Counter,
+
         /// An indirect reference to the source filename. In the LLVM Coverage Mapping Format, the
         /// file_id is an index into a function-specific `virtual_file_mapping` array of indexes
         /// that, in turn, are used to look up the filename for this region.
@@ -754,6 +767,7 @@ impl CounterMappingRegion {
         ) -> Self {
             Self {
                 counter,
+                false_counter: coverage_map::Counter::zero(),
                 file_id,
                 expanded_file_id: 0,
                 start_line,
@@ -764,6 +778,31 @@ impl CounterMappingRegion {
             }
         }
 
+        // This function might be used in the future; the LLVM API is still evolving, as is coverage
+        // support.
+        #[allow(dead_code)]
+        crate fn branch_region(
+            counter: coverage_map::Counter,
+            false_counter: coverage_map::Counter,
+            file_id: u32,
+            start_line: u32,
+            start_col: u32,
+            end_line: u32,
+            end_col: u32,
+        ) -> Self {
+            Self {
+                counter,
+                false_counter,
+                file_id,
+                expanded_file_id: 0,
+                start_line,
+                start_col,
+                end_line,
+                end_col,
+                kind: RegionKind::BranchRegion,
+            }
+        }
+
         // This function might be used in the future; the LLVM API is still evolving, as is coverage
         // support.
         #[allow(dead_code)]
@@ -777,6 +816,7 @@ impl CounterMappingRegion {
         ) -> Self {
             Self {
                 counter: coverage_map::Counter::zero(),
+                false_counter: coverage_map::Counter::zero(),
                 file_id,
                 expanded_file_id,
                 start_line,
@@ -799,6 +839,7 @@ impl CounterMappingRegion {
         ) -> Self {
             Self {
                 counter: coverage_map::Counter::zero(),
+                false_counter: coverage_map::Counter::zero(),
                 file_id,
                 expanded_file_id: 0,
                 start_line,
@@ -822,6 +863,7 @@ impl CounterMappingRegion {
         ) -> Self {
             Self {
                 counter,
+                false_counter: coverage_map::Counter::zero(),
                 file_id,
                 expanded_file_id: 0,
                 start_line,
@@ -2289,12 +2331,6 @@ pub fn LLVMRustArchiveIteratorNext(
     #[allow(improper_ctypes)]
     pub fn LLVMRustWriteTwineToString(T: &Twine, s: &RustString);
 
-    pub fn LLVMContextSetDiagnosticHandler(
-        C: &Context,
-        Handler: DiagnosticHandler,
-        DiagnosticContext: *mut c_void,
-    );
-
     #[allow(improper_ctypes)]
     pub fn LLVMRustUnpackOptimizationDiagnostic(
         DI: &'a DiagnosticInfo,
@@ -2324,7 +2360,7 @@ pub fn LLVMRustGetSMDiagnostic(
 
     pub fn LLVMRustSetInlineAsmDiagnosticHandler(
         C: &Context,
-        H: InlineAsmDiagHandler,
+        H: InlineAsmDiagHandlerTy,
         CX: *mut c_void,
     );
 
@@ -2439,4 +2475,19 @@ pub fn LLVMRustComputeLTOCacheKey(
         mod_id: *const c_char,
         data: &ThinLTOData,
     );
+
+    pub fn LLVMRustContextGetDiagnosticHandler(Context: &Context) -> Option<&DiagnosticHandler>;
+    pub fn LLVMRustContextSetDiagnosticHandler(
+        context: &Context,
+        diagnostic_handler: Option<&DiagnosticHandler>,
+    );
+    pub fn LLVMRustContextConfigureDiagnosticHandler(
+        context: &Context,
+        diagnostic_handler_callback: DiagnosticHandlerTy,
+        diagnostic_handler_context: *mut c_void,
+        remark_all_passes: bool,
+        remark_passes: *const *const c_char,
+        remark_passes_len: usize,
+    );
+
 }
index 962c01c2ee7a6fd25cb9633523056319f21643ac..e288760a02b186612249db0225f4ec2a42a57ee4 100644 (file)
@@ -1,6 +1,6 @@
 use rustc_middle::mir::coverage::{CounterValueReference, MappedExpressionIndex};
 
-/// Aligns with [llvm::coverage::Counter::CounterKind](https://github.com/rust-lang/llvm-project/blob/rustc/11.0-2020-10-12/llvm/include/llvm/ProfileData/Coverage/CoverageMapping.h#L206-L222)
+/// Aligns with [llvm::coverage::Counter::CounterKind](https://github.com/rust-lang/llvm-project/blob/rustc/13.0-2021-09-30/llvm/include/llvm/ProfileData/Coverage/CoverageMapping.h#L95)
 #[derive(Copy, Clone, Debug)]
 #[repr(C)]
 pub enum CounterKind {
@@ -17,7 +17,7 @@ pub enum CounterKind {
 ///     `instrprof.increment()`)
 ///   * For `CounterKind::Expression`, `id` is the index into the coverage map's array of
 ///     counter expressions.
-/// Aligns with [llvm::coverage::Counter](https://github.com/rust-lang/llvm-project/blob/rustc/11.0-2020-10-12/llvm/include/llvm/ProfileData/Coverage/CoverageMapping.h#L99-L100)
+/// Aligns with [llvm::coverage::Counter](https://github.com/rust-lang/llvm-project/blob/rustc/13.0-2021-09-30/llvm/include/llvm/ProfileData/Coverage/CoverageMapping.h#L102-L103)
 /// Important: The Rust struct layout (order and types of fields) must match its C++ counterpart.
 #[derive(Copy, Clone, Debug)]
 #[repr(C)]
@@ -59,7 +59,7 @@ pub fn zero_based_id(&self) -> u32 {
     }
 }
 
-/// Aligns with [llvm::coverage::CounterExpression::ExprKind](https://github.com/rust-lang/llvm-project/blob/rustc/11.0-2020-10-12/llvm/include/llvm/ProfileData/Coverage/CoverageMapping.h#L147)
+/// Aligns with [llvm::coverage::CounterExpression::ExprKind](https://github.com/rust-lang/llvm-project/blob/rustc/13.0-2021-09-30/llvm/include/llvm/ProfileData/Coverage/CoverageMapping.h#L150)
 #[derive(Copy, Clone, Debug)]
 #[repr(C)]
 pub enum ExprKind {
@@ -67,7 +67,7 @@ pub enum ExprKind {
     Add = 1,
 }
 
-/// Aligns with [llvm::coverage::CounterExpression](https://github.com/rust-lang/llvm-project/blob/rustc/11.0-2020-10-12/llvm/include/llvm/ProfileData/Coverage/CoverageMapping.h#L148-L149)
+/// Aligns with [llvm::coverage::CounterExpression](https://github.com/rust-lang/llvm-project/blob/rustc/13.0-2021-09-30/llvm/include/llvm/ProfileData/Coverage/CoverageMapping.h#L151-L152)
 /// Important: The Rust struct layout (order and types of fields) must match its C++
 /// counterpart.
 #[derive(Copy, Clone, Debug)]
index 44da27a43db0a01e08d9c46db4ef4fc8be2c4e70..025d2998b00525e4ee1a1e99ea8143ee365393d7 100644 (file)
@@ -394,10 +394,12 @@ pub fn emulate_intrinsic(
             sym::transmute => {
                 self.copy_op_transmute(&args[0], dest)?;
             }
-            sym::assert_inhabited => {
+            sym::assert_inhabited | sym::assert_zero_valid | sym::assert_uninit_valid => {
                 let ty = instance.substs.type_at(0);
                 let layout = self.layout_of(ty)?;
 
+                // For *all* intrinsics we first check `is_uninhabited` to give a more specific
+                // error message.
                 if layout.abi.is_uninhabited() {
                     // The run-time intrinsic panics just to get a good backtrace; here we abort
                     // since there is no problem showing a backtrace even for aborts.
@@ -409,6 +411,28 @@ pub fn emulate_intrinsic(
                         ),
                     )?;
                 }
+                if intrinsic_name == sym::assert_zero_valid
+                    && !layout.might_permit_raw_init(self, /*zero:*/ true)
+                {
+                    M::abort(
+                        self,
+                        format!(
+                            "aborted execution: attempted to zero-initialize type `{}`, which is invalid",
+                            ty
+                        ),
+                    )?;
+                }
+                if intrinsic_name == sym::assert_uninit_valid
+                    && !layout.might_permit_raw_init(self, /*zero:*/ false)
+                {
+                    M::abort(
+                        self,
+                        format!(
+                            "aborted execution: attempted to leave type `{}` uninitialized, which is invalid",
+                            ty
+                        ),
+                    )?;
+                }
             }
             sym::simd_insert => {
                 let index = u64::from(self.read_scalar(&args[1])?.to_u32()?);
index e6037d561dedcb5228ed84e93e524df136f17551..9299ae2b2b9f8f6708f9a1a1646e23818a96f260 100644 (file)
@@ -242,11 +242,15 @@ pub fn eval_rvalue_into_place(
                     let elem_size = first.layout.size;
                     let first_ptr = first.ptr;
                     let rest_ptr = first_ptr.offset(elem_size, self)?;
+                    // For the alignment of `rest_ptr`, we crucially do *not* use `first.align` as
+                    // that place might be more aligned than its type mandates (a `u8` array could
+                    // be 4-aligned if it sits at the right spot in a struct). Instead we use
+                    // `first.layout.align`, i.e., the alignment given by the type.
                     self.memory.copy_repeatedly(
                         first_ptr,
                         first.align,
                         rest_ptr,
-                        first.align,
+                        first.layout.align.abi,
                         elem_size,
                         length - 1,
                         /*nonoverlapping:*/ true,
index f308e764e861d0422e76464c39014aea20b59d09..0d36466f6e3e73153e2498e393c608614cc367da 100644 (file)
@@ -23,6 +23,7 @@
 #![feature(trusted_len)]
 #![feature(trusted_step)]
 #![feature(try_blocks)]
+#![feature(unwrap_infallible)]
 #![recursion_limit = "256"]
 
 #[macro_use]
index 4e3a8b64094af7c20c7982833c39e30521a6cb45..274665ccd98364f7f4f90d060247840e6f4ca46e 100644 (file)
@@ -1,8 +1,8 @@
 //! The `Visitor` responsible for actually checking a `mir::Body` for invalid operations.
 
 use rustc_errors::{Applicability, Diagnostic, ErrorReported};
+use rustc_hir as hir;
 use rustc_hir::def_id::DefId;
-use rustc_hir::{self as hir, HirId, LangItem};
 use rustc_index::bit_set::BitSet;
 use rustc_infer::infer::TyCtxtInferExt;
 use rustc_infer::traits::{ImplSource, Obligation, ObligationCause};
@@ -14,8 +14,7 @@
 use rustc_middle::ty::{Binder, TraitPredicate, TraitRef};
 use rustc_mir_dataflow::{self, Analysis};
 use rustc_span::{sym, Span, Symbol};
-use rustc_trait_selection::traits::error_reporting::InferCtxtExt;
-use rustc_trait_selection::traits::{self, SelectionContext, TraitEngine};
+use rustc_trait_selection::traits::SelectionContext;
 
 use std::mem;
 use std::ops::Deref;
@@ -255,16 +254,6 @@ pub fn check_body(&mut self) {
             self.visit_body(&body);
         }
 
-        // Ensure that the end result is `Sync` in a non-thread local `static`.
-        let should_check_for_sync = self.const_kind()
-            == hir::ConstContext::Static(hir::Mutability::Not)
-            && !tcx.is_thread_local_static(def_id.to_def_id());
-
-        if should_check_for_sync {
-            let hir_id = tcx.hir().local_def_id_to_hir_id(def_id);
-            check_return_ty_is_sync(tcx, &body, hir_id);
-        }
-
         // If we got through const-checking without emitting any "primary" errors, emit any
         // "secondary" errors if they occurred.
         let secondary_errors = mem::take(&mut self.secondary_errors);
@@ -1054,20 +1043,6 @@ fn visit_terminator(&mut self, terminator: &Terminator<'tcx>, location: Location
     }
 }
 
-fn check_return_ty_is_sync(tcx: TyCtxt<'tcx>, body: &Body<'tcx>, hir_id: HirId) {
-    let ty = body.return_ty();
-    tcx.infer_ctxt().enter(|infcx| {
-        let cause = traits::ObligationCause::new(body.span, hir_id, traits::SharedStatic);
-        let mut fulfillment_cx = traits::FulfillmentContext::new();
-        let sync_def_id = tcx.require_lang_item(LangItem::Sync, Some(body.span));
-        fulfillment_cx.register_bound(&infcx, ty::ParamEnv::empty(), ty, sync_def_id, cause);
-        let errors = fulfillment_cx.select_all_or_error(&infcx);
-        if !errors.is_empty() {
-            infcx.report_fulfillment_errors(&errors, None, false);
-        }
-    });
-}
-
 fn place_as_reborrow(
     tcx: TyCtxt<'tcx>,
     body: &Body<'tcx>,
index 38c28f34934a4d01da25fecaec30fe22becf6bbe..a2928bdf51b83195e9f553e6ce249cdf33b42965 100644 (file)
@@ -1,5 +1,3 @@
 pub mod check_consts;
 pub mod promote_consts;
 pub mod validate;
-
-pub use rustc_middle::mir::MirPass;
index a92b20f5cb520ae147c0ddfd3be48fc532738870..464155db89f488f6d2c8492243966998c1ed8e6f 100644 (file)
@@ -27,7 +27,6 @@
 use std::{cmp, iter, mem};
 
 use crate::transform::check_consts::{qualifs, ConstCx};
-use crate::transform::MirPass;
 
 /// A `MirPass` for promotion.
 ///
index b09b2227f3e88b63e860cef4a90da2d6ea0759dc..c86c8f81dbd96e206946fc384053d342d3bef6e6 100644 (file)
@@ -1,14 +1,13 @@
 //! Validates the MIR to ensure that invariants are upheld.
 
-use super::MirPass;
 use rustc_index::bit_set::BitSet;
 use rustc_infer::infer::TyCtxtInferExt;
 use rustc_middle::mir::interpret::Scalar;
 use rustc_middle::mir::traversal;
 use rustc_middle::mir::visit::{PlaceContext, Visitor};
 use rustc_middle::mir::{
-    AggregateKind, BasicBlock, Body, BorrowKind, Local, Location, MirPhase, Operand, PlaceElem,
-    PlaceRef, ProjectionElem, Rvalue, SourceScope, Statement, StatementKind, Terminator,
+    AggregateKind, BasicBlock, Body, BorrowKind, Local, Location, MirPass, MirPhase, Operand,
+    PlaceElem, PlaceRef, ProjectionElem, Rvalue, SourceScope, Statement, StatementKind, Terminator,
     TerminatorKind, START_BLOCK,
 };
 use rustc_middle::ty::fold::BottomUpFolder;
@@ -95,7 +94,8 @@ pub fn equal_up_to_regions(
                 // Leave consts and types unchanged.
                 ct_op: |ct| ct,
                 ty_op: |ty| ty,
-            }),
+            })
+            .into_ok(),
         )
     };
     tcx.infer_ctxt().enter(|infcx| infcx.can_eq(param_env, normalize(src), normalize(dest)).is_ok())
index 5b83ae31247661e7ecf7969b124d909499f568ed..920f7b1ed0a543c15dac3c272f59edad8243464e 100644 (file)
@@ -1,35 +1,42 @@
 use rustc_index::vec::{Idx, IndexVec};
 use std::mem;
-use std::ptr;
 
-pub trait IdFunctor {
+pub trait IdFunctor: Sized {
     type Inner;
 
-    fn map_id<F>(self, f: F) -> Self
+    #[inline]
+    fn map_id<F>(self, mut f: F) -> Self
+    where
+        F: FnMut(Self::Inner) -> Self::Inner,
+    {
+        self.try_map_id::<_, !>(|value| Ok(f(value))).into_ok()
+    }
+
+    fn try_map_id<F, E>(self, f: F) -> Result<Self, E>
     where
-        F: FnMut(Self::Inner) -> Self::Inner;
+        F: FnMut(Self::Inner) -> Result<Self::Inner, E>;
 }
 
 impl<T> IdFunctor for Box<T> {
     type Inner = T;
 
     #[inline]
-    fn map_id<F>(self, mut f: F) -> Self
+    fn try_map_id<F, E>(self, mut f: F) -> Result<Self, E>
     where
-        F: FnMut(Self::Inner) -> Self::Inner,
+        F: FnMut(Self::Inner) -> Result<Self::Inner, E>,
     {
         let raw = Box::into_raw(self);
-        unsafe {
+        Ok(unsafe {
             // SAFETY: The raw pointer points to a valid value of type `T`.
-            let value = ptr::read(raw);
+            let value = raw.read();
             // SAFETY: Converts `Box<T>` to `Box<MaybeUninit<T>>` which is the
             // inverse of `Box::assume_init()` and should be safe.
             let mut raw: Box<mem::MaybeUninit<T>> = Box::from_raw(raw.cast());
             // SAFETY: Write the mapped value back into the `Box`.
-            raw.write(f(value));
+            raw.write(f(value)?);
             // SAFETY: We just initialized `raw`.
             raw.assume_init()
-        }
+        })
     }
 }
 
@@ -37,9 +44,9 @@ impl<T> IdFunctor for Vec<T> {
     type Inner = T;
 
     #[inline]
-    fn map_id<F>(mut self, mut f: F) -> Self
+    fn try_map_id<F, E>(mut self, mut f: F) -> Result<Self, E>
     where
-        F: FnMut(Self::Inner) -> Self::Inner,
+        F: FnMut(Self::Inner) -> Result<Self::Inner, E>,
     {
         // FIXME: We don't really care about panics here and leak
         // far more than we should, but that should be fine for now.
@@ -49,11 +56,26 @@ fn map_id<F>(mut self, mut f: F) -> Self
             let start = self.as_mut_ptr();
             for i in 0..len {
                 let p = start.add(i);
-                ptr::write(p, f(ptr::read(p)));
+                match f(p.read()) {
+                    Ok(val) => p.write(val),
+                    Err(err) => {
+                        // drop all other elements in self
+                        // (current element was "moved" into the call to f)
+                        for j in (0..i).chain(i + 1..len) {
+                            start.add(j).drop_in_place();
+                        }
+
+                        // returning will drop self, releasing the allocation
+                        // (len is 0 so elements will not be re-dropped)
+                        return Err(err);
+                    }
+                }
             }
+            // Even if we encountered an error, set the len back
+            // so we don't leak memory.
             self.set_len(len);
         }
-        self
+        Ok(self)
     }
 }
 
@@ -61,11 +83,11 @@ impl<T> IdFunctor for Box<[T]> {
     type Inner = T;
 
     #[inline]
-    fn map_id<F>(self, f: F) -> Self
+    fn try_map_id<F, E>(self, f: F) -> Result<Self, E>
     where
-        F: FnMut(Self::Inner) -> Self::Inner,
+        F: FnMut(Self::Inner) -> Result<Self::Inner, E>,
     {
-        Vec::from(self).map_id(f).into()
+        Vec::from(self).try_map_id(f).map(Into::into)
     }
 }
 
@@ -73,10 +95,10 @@ impl<I: Idx, T> IdFunctor for IndexVec<I, T> {
     type Inner = T;
 
     #[inline]
-    fn map_id<F>(self, f: F) -> Self
+    fn try_map_id<F, E>(self, f: F) -> Result<Self, E>
     where
-        F: FnMut(Self::Inner) -> Self::Inner,
+        F: FnMut(Self::Inner) -> Result<Self::Inner, E>,
     {
-        IndexVec::from_raw(self.raw.map_id(f))
+        self.raw.try_map_id(f).map(IndexVec::from_raw)
     }
 }
index 77784bf1705234d0018ef5aca044267902dd6735..d4eb622e780ce1857af21276d6d4fcb5df8f9a7d 100644 (file)
@@ -25,6 +25,7 @@
 #![feature(once_cell)]
 #![feature(test)]
 #![feature(thread_id_value)]
+#![feature(unwrap_infallible)]
 #![allow(rustc::default_hash_types)]
 #![deny(unaligned_references)]
 
index d64a589bd9b2a37b1db629e6e10d7112c206ea36..3104bc185e7568966c72de3c40e8a3346fc3ac60 100644 (file)
@@ -214,7 +214,7 @@ fn supports_color(&self) -> bool {
 
     /// Formats the substitutions of the primary_span
     ///
-    /// The are a lot of conditions to this method, but in short:
+    /// There are a lot of conditions to this method, but in short:
     ///
     /// * If the current `Diagnostic` has only one visible `CodeSuggestion`,
     ///   we format the `help` suggestion depending on the content of the
@@ -736,7 +736,9 @@ fn render_source_line(
 
         let line_offset = buffer.num_lines();
 
-        let left = margin.left(source_string.len()); // Left trim
+        // Left trim
+        let left = margin.left(source_string.len());
+
         // Account for unicode characters of width !=0 that were removed.
         let left = source_string
             .chars()
@@ -1623,18 +1625,27 @@ fn emit_suggestion_default(
             suggestions.iter().take(MAX_SUGGESTIONS)
         {
             notice_capitalization |= only_capitalization;
-            // Only show underline if the suggestion spans a single line and doesn't cover the
-            // entirety of the code output. If you have multiple replacements in the same line
-            // of code, show the underline.
-            let show_underline = !(parts.len() == 1 && parts[0].snippet.trim() == complete.trim())
-                && complete.lines().count() == 1;
 
             let has_deletion = parts.iter().any(|p| p.is_deletion());
             let is_multiline = complete.lines().count() > 1;
 
-            let show_diff = has_deletion && !is_multiline;
+            enum DisplaySuggestion {
+                Underline,
+                Diff,
+                None,
+            }
+
+            let show_code_change = if has_deletion && !is_multiline {
+                DisplaySuggestion::Diff
+            } else if (parts.len() != 1 || parts[0].snippet.trim() != complete.trim())
+                && !is_multiline
+            {
+                DisplaySuggestion::Underline
+            } else {
+                DisplaySuggestion::None
+            };
 
-            if show_diff {
+            if let DisplaySuggestion::Diff = show_code_change {
                 row_num += 1;
             }
 
@@ -1657,7 +1668,7 @@ fn emit_suggestion_default(
                     &self.maybe_anonymized(line_start + line_pos),
                     Style::LineNumber,
                 );
-                if show_diff {
+                if let DisplaySuggestion::Diff = show_code_change {
                     // Add the line number for both addition and removal to drive the point home.
                     //
                     // N - fn foo<A: T>(bar: A) {
@@ -1727,7 +1738,7 @@ fn emit_suggestion_default(
             let mut offsets: Vec<(usize, isize)> = Vec::new();
             // Only show an underline in the suggestions if the suggestion is not the
             // entirety of the code being shown and the displayed code is not multiline.
-            if show_underline {
+            if let DisplaySuggestion::Diff | DisplaySuggestion::Underline = show_code_change {
                 draw_col_separator(&mut buffer, row_num, max_line_num_len + 1);
                 for part in parts {
                     let span_start_pos = sm.lookup_char_pos(part.span.lo()).col_display;
@@ -1755,7 +1766,7 @@ fn emit_suggestion_default(
                     assert!(underline_start >= 0 && underline_end >= 0);
                     let padding: usize = max_line_num_len + 3;
                     for p in underline_start..underline_end {
-                        if !show_diff {
+                        if let DisplaySuggestion::Underline = show_code_change {
                             // If this is a replacement, underline with `^`, if this is an addition
                             // underline with `+`.
                             buffer.putc(
@@ -1766,7 +1777,7 @@ fn emit_suggestion_default(
                             );
                         }
                     }
-                    if show_diff {
+                    if let DisplaySuggestion::Diff = show_code_change {
                         // Colorize removal with red in diff format.
                         buffer.set_style_range(
                             row_num - 2,
@@ -1797,7 +1808,7 @@ fn emit_suggestion_default(
             // if we elided some lines, add an ellipsis
             if lines.next().is_some() {
                 buffer.puts(row_num, max_line_num_len - 1, "...", Style::LineNumber);
-            } else if !show_underline {
+            } else if let DisplaySuggestion::None = show_code_change {
                 draw_col_separator_no_space(&mut buffer, row_num, max_line_num_len + 1);
                 row_num += 1;
             }
@@ -2083,7 +2094,7 @@ fn num_decimal_digits(num: usize) -> usize {
     ('\t', "    "),   // We do our own tab replacement
     ('\u{200D}', ""), // Replace ZWJ with nothing for consistent terminal output of grapheme clusters.
     ('\u{202A}', ""), // The following unicode text flow control characters are inconsistently
-    ('\u{202B}', ""), // supported accross CLIs and can cause confusion due to the bytes on disk
+    ('\u{202B}', ""), // supported across CLIs and can cause confusion due to the bytes on disk
     ('\u{202D}', ""), // not corresponding to the visible source code, so we replace them always.
     ('\u{202E}', ""),
     ('\u{2066}', ""),
index 934ada9932e71ad91d9b737b0ed38ff145696d17..27e73738b7f351bf07bd4bd56298cd90477ecaee 100644 (file)
@@ -278,7 +278,7 @@ fn tcx<'b>(&'b self) -> TyCtxt<'tcx> {
         self.tcx
     }
 
-    fn fold_binder<T>(&mut self, t: ty::Binder<'tcx, T>) -> ty::Binder<'tcx, T>
+    fn fold_binder<T>(&mut self, t: ty::Binder<'tcx, T>) -> Result<ty::Binder<'tcx, T>, Self::Error>
     where
         T: TypeFoldable<'tcx>,
     {
@@ -288,13 +288,13 @@ fn fold_binder<T>(&mut self, t: ty::Binder<'tcx, T>) -> ty::Binder<'tcx, T>
         t
     }
 
-    fn fold_region(&mut self, r: ty::Region<'tcx>) -> ty::Region<'tcx> {
+    fn fold_region(&mut self, r: ty::Region<'tcx>) -> Result<ty::Region<'tcx>, Self::Error> {
         match *r {
             ty::ReLateBound(index, ..) => {
                 if index >= self.binder_index {
                     bug!("escaping late-bound region during canonicalization");
                 } else {
-                    r
+                    Ok(r)
                 }
             }
 
@@ -311,7 +311,7 @@ fn fold_region(&mut self, r: ty::Region<'tcx>) -> ty::Region<'tcx> {
                     vid, r
                 );
                 let r = self.tcx.reuse_or_mk_region(r, ty::ReVar(resolved_vid));
-                self.canonicalize_region_mode.canonicalize_free_region(self, r)
+                Ok(self.canonicalize_region_mode.canonicalize_free_region(self, r))
             }
 
             ty::ReStatic
@@ -319,11 +319,11 @@ fn fold_region(&mut self, r: ty::Region<'tcx>) -> ty::Region<'tcx> {
             | ty::ReFree(_)
             | ty::ReEmpty(_)
             | ty::RePlaceholder(..)
-            | ty::ReErased => self.canonicalize_region_mode.canonicalize_free_region(self, r),
+            | ty::ReErased => Ok(self.canonicalize_region_mode.canonicalize_free_region(self, r)),
         }
     }
 
-    fn fold_ty(&mut self, t: Ty<'tcx>) -> Ty<'tcx> {
+    fn fold_ty(&mut self, t: Ty<'tcx>) -> Result<Ty<'tcx>, Self::Error> {
         match *t.kind() {
             ty::Infer(ty::TyVar(vid)) => {
                 debug!("canonical: type var found with vid {:?}", vid);
@@ -339,40 +339,40 @@ fn fold_ty(&mut self, t: Ty<'tcx>) -> Ty<'tcx> {
                     Err(mut ui) => {
                         // FIXME: perf problem described in #55921.
                         ui = ty::UniverseIndex::ROOT;
-                        self.canonicalize_ty_var(
+                        Ok(self.canonicalize_ty_var(
                             CanonicalVarInfo {
                                 kind: CanonicalVarKind::Ty(CanonicalTyVarKind::General(ui)),
                             },
                             t,
-                        )
+                        ))
                     }
                 }
             }
 
-            ty::Infer(ty::IntVar(_)) => self.canonicalize_ty_var(
+            ty::Infer(ty::IntVar(_)) => Ok(self.canonicalize_ty_var(
                 CanonicalVarInfo { kind: CanonicalVarKind::Ty(CanonicalTyVarKind::Int) },
                 t,
-            ),
+            )),
 
-            ty::Infer(ty::FloatVar(_)) => self.canonicalize_ty_var(
+            ty::Infer(ty::FloatVar(_)) => Ok(self.canonicalize_ty_var(
                 CanonicalVarInfo { kind: CanonicalVarKind::Ty(CanonicalTyVarKind::Float) },
                 t,
-            ),
+            )),
 
             ty::Infer(ty::FreshTy(_) | ty::FreshIntTy(_) | ty::FreshFloatTy(_)) => {
                 bug!("encountered a fresh type during canonicalization")
             }
 
-            ty::Placeholder(placeholder) => self.canonicalize_ty_var(
+            ty::Placeholder(placeholder) => Ok(self.canonicalize_ty_var(
                 CanonicalVarInfo { kind: CanonicalVarKind::PlaceholderTy(placeholder) },
                 t,
-            ),
+            )),
 
             ty::Bound(debruijn, _) => {
                 if debruijn >= self.binder_index {
                     bug!("escaping bound type during canonicalization")
                 } else {
-                    t
+                    Ok(t)
                 }
             }
 
@@ -403,13 +403,16 @@ fn fold_ty(&mut self, t: Ty<'tcx>) -> Ty<'tcx> {
                 if t.flags().intersects(self.needs_canonical_flags) {
                     t.super_fold_with(self)
                 } else {
-                    t
+                    Ok(t)
                 }
             }
         }
     }
 
-    fn fold_const(&mut self, ct: &'tcx ty::Const<'tcx>) -> &'tcx ty::Const<'tcx> {
+    fn fold_const(
+        &mut self,
+        ct: &'tcx ty::Const<'tcx>,
+    ) -> Result<&'tcx ty::Const<'tcx>, Self::Error> {
         match ct.val {
             ty::ConstKind::Infer(InferConst::Var(vid)) => {
                 debug!("canonical: const var found with vid {:?}", vid);
@@ -424,10 +427,10 @@ fn fold_const(&mut self, ct: &'tcx ty::Const<'tcx>) -> &'tcx ty::Const<'tcx> {
                     Err(mut ui) => {
                         // FIXME: perf problem described in #55921.
                         ui = ty::UniverseIndex::ROOT;
-                        return self.canonicalize_const_var(
+                        return Ok(self.canonicalize_const_var(
                             CanonicalVarInfo { kind: CanonicalVarKind::Const(ui) },
                             ct,
-                        );
+                        ));
                     }
                 }
             }
@@ -438,20 +441,20 @@ fn fold_const(&mut self, ct: &'tcx ty::Const<'tcx>) -> &'tcx ty::Const<'tcx> {
                 if debruijn >= self.binder_index {
                     bug!("escaping bound type during canonicalization")
                 } else {
-                    return ct;
+                    return Ok(ct);
                 }
             }
             ty::ConstKind::Placeholder(placeholder) => {
-                return self.canonicalize_const_var(
+                return Ok(self.canonicalize_const_var(
                     CanonicalVarInfo { kind: CanonicalVarKind::PlaceholderConst(placeholder) },
                     ct,
-                );
+                ));
             }
             _ => {}
         }
 
         let flags = FlagComputation::for_const(ct);
-        if flags.intersects(self.needs_canonical_flags) { ct.super_fold_with(self) } else { ct }
+        if flags.intersects(self.needs_canonical_flags) { ct.super_fold_with(self) } else { Ok(ct) }
     }
 }
 
@@ -500,7 +503,7 @@ fn canonicalize<V>(
             indices: FxHashMap::default(),
             binder_index: ty::INNERMOST,
         };
-        let out_value = value.fold_with(&mut canonicalizer);
+        let out_value = value.fold_with(&mut canonicalizer).into_ok();
 
         // Once we have canonicalized `out_value`, it should not
         // contain anything that ties it to this inference context
@@ -618,7 +621,7 @@ fn canonicalize_ty_var(&mut self, info: CanonicalVarInfo<'tcx>, ty_var: Ty<'tcx>
         let infcx = self.infcx;
         let bound_to = infcx.shallow_resolve(ty_var);
         if bound_to != ty_var {
-            self.fold_ty(bound_to)
+            self.fold_ty(bound_to).into_ok()
         } else {
             let var = self.canonical_var(info, ty_var.into());
             self.tcx().mk_ty(ty::Bound(self.binder_index, var.into()))
@@ -637,12 +640,12 @@ fn canonicalize_const_var(
         let infcx = self.infcx;
         let bound_to = infcx.shallow_resolve(const_var);
         if bound_to != const_var {
-            self.fold_const(bound_to)
+            self.fold_const(bound_to).into_ok()
         } else {
             let var = self.canonical_var(info, const_var.into());
             self.tcx().mk_const(ty::Const {
                 val: ty::ConstKind::Bound(self.binder_index, var),
-                ty: self.fold_ty(const_var.ty),
+                ty: self.fold_ty(const_var.ty).into_ok(),
             })
         }
     }
index c40e409891bc25cb76a7612fbab231493c67de98..7599e98167fb5c04e6c8e2839ae394a4f3761c68 100644 (file)
@@ -72,7 +72,7 @@ fn freshen_ty<F>(
         F: FnOnce(u32) -> ty::InferTy,
     {
         if let Some(ty) = opt_ty {
-            return ty.fold_with(self);
+            return ty.fold_with(self).into_ok();
         }
 
         match self.ty_freshen_map.entry(key) {
@@ -98,7 +98,7 @@ fn freshen_const<F>(
         F: FnOnce(u32) -> ty::InferConst<'tcx>,
     {
         if let Some(ct) = opt_ct {
-            return ct.fold_with(self);
+            return ct.fold_with(self).into_ok();
         }
 
         match self.const_freshen_map.entry(key) {
@@ -119,11 +119,11 @@ fn tcx<'b>(&'b self) -> TyCtxt<'tcx> {
         self.infcx.tcx
     }
 
-    fn fold_region(&mut self, r: ty::Region<'tcx>) -> ty::Region<'tcx> {
+    fn fold_region(&mut self, r: ty::Region<'tcx>) -> Result<ty::Region<'tcx>, Self::Error> {
         match *r {
             ty::ReLateBound(..) => {
                 // leave bound regions alone
-                r
+                Ok(r)
             }
 
             ty::ReEarlyBound(..)
@@ -133,21 +133,21 @@ fn fold_region(&mut self, r: ty::Region<'tcx>) -> ty::Region<'tcx> {
             | ty::ReEmpty(_)
             | ty::ReErased => {
                 // replace all free regions with 'erased
-                self.tcx().lifetimes.re_erased
+                Ok(self.tcx().lifetimes.re_erased)
             }
             ty::ReStatic => {
                 if self.keep_static {
-                    r
+                    Ok(r)
                 } else {
-                    self.tcx().lifetimes.re_erased
+                    Ok(self.tcx().lifetimes.re_erased)
                 }
             }
         }
     }
 
-    fn fold_ty(&mut self, t: Ty<'tcx>) -> Ty<'tcx> {
+    fn fold_ty(&mut self, t: Ty<'tcx>) -> Result<Ty<'tcx>, Self::Error> {
         if !t.needs_infer() && !t.has_erasable_regions(self.tcx()) {
-            return t;
+            return Ok(t);
         }
 
         let tcx = self.infcx.tcx;
@@ -155,10 +155,10 @@ fn fold_ty(&mut self, t: Ty<'tcx>) -> Ty<'tcx> {
         match *t.kind() {
             ty::Infer(ty::TyVar(v)) => {
                 let opt_ty = self.infcx.inner.borrow_mut().type_variables().probe(v).known();
-                self.freshen_ty(opt_ty, ty::TyVar(v), ty::FreshTy)
+                Ok(self.freshen_ty(opt_ty, ty::TyVar(v), ty::FreshTy))
             }
 
-            ty::Infer(ty::IntVar(v)) => self.freshen_ty(
+            ty::Infer(ty::IntVar(v)) => Ok(self.freshen_ty(
                 self.infcx
                     .inner
                     .borrow_mut()
@@ -167,9 +167,9 @@ fn fold_ty(&mut self, t: Ty<'tcx>) -> Ty<'tcx> {
                     .map(|v| v.to_type(tcx)),
                 ty::IntVar(v),
                 ty::FreshIntTy,
-            ),
+            )),
 
-            ty::Infer(ty::FloatVar(v)) => self.freshen_ty(
+            ty::Infer(ty::FloatVar(v)) => Ok(self.freshen_ty(
                 self.infcx
                     .inner
                     .borrow_mut()
@@ -178,7 +178,7 @@ fn fold_ty(&mut self, t: Ty<'tcx>) -> Ty<'tcx> {
                     .map(|v| v.to_type(tcx)),
                 ty::FloatVar(v),
                 ty::FreshFloatTy,
-            ),
+            )),
 
             ty::Infer(ty::FreshTy(ct) | ty::FreshIntTy(ct) | ty::FreshFloatTy(ct)) => {
                 if ct >= self.ty_freshen_count {
@@ -189,7 +189,7 @@ fn fold_ty(&mut self, t: Ty<'tcx>) -> Ty<'tcx> {
                         self.ty_freshen_count
                     );
                 }
-                t
+                Ok(t)
             }
 
             ty::Generator(..)
@@ -221,7 +221,10 @@ fn fold_ty(&mut self, t: Ty<'tcx>) -> Ty<'tcx> {
         }
     }
 
-    fn fold_const(&mut self, ct: &'tcx ty::Const<'tcx>) -> &'tcx ty::Const<'tcx> {
+    fn fold_const(
+        &mut self,
+        ct: &'tcx ty::Const<'tcx>,
+    ) -> Result<&'tcx ty::Const<'tcx>, Self::Error> {
         match ct.val {
             ty::ConstKind::Infer(ty::InferConst::Var(v)) => {
                 let opt_ct = self
@@ -232,12 +235,12 @@ fn fold_const(&mut self, ct: &'tcx ty::Const<'tcx>) -> &'tcx ty::Const<'tcx> {
                     .probe_value(v)
                     .val
                     .known();
-                return self.freshen_const(
+                return Ok(self.freshen_const(
                     opt_ct,
                     ty::InferConst::Var(v),
                     ty::InferConst::Fresh,
                     ct.ty,
-                );
+                ));
             }
             ty::ConstKind::Infer(ty::InferConst::Fresh(i)) => {
                 if i >= self.const_freshen_count {
@@ -248,7 +251,7 @@ fn fold_const(&mut self, ct: &'tcx ty::Const<'tcx>) -> &'tcx ty::Const<'tcx> {
                         self.const_freshen_count,
                     );
                 }
-                return ct;
+                return Ok(ct);
             }
 
             ty::ConstKind::Bound(..) | ty::ConstKind::Placeholder(_) => {
index 773753a0363264400be63ce562bae19850ffa3e8..4e6f1315d102437ecf565992403cf0548181c6a4 100644 (file)
@@ -161,7 +161,7 @@ pub fn fudge_inference_if_ok<T, E, F>(&self, f: F) -> Result<T, E>
         {
             Ok(value)
         } else {
-            Ok(value.fold_with(&mut fudger))
+            Ok(value.fold_with(&mut fudger).into_ok())
         }
     }
 }
@@ -180,7 +180,7 @@ fn tcx<'b>(&'b self) -> TyCtxt<'tcx> {
         self.infcx.tcx
     }
 
-    fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> {
+    fn fold_ty(&mut self, ty: Ty<'tcx>) -> Result<Ty<'tcx>, Self::Error> {
         match *ty.kind() {
             ty::Infer(ty::InferTy::TyVar(vid)) => {
                 if self.type_vars.0.contains(&vid) {
@@ -188,7 +188,7 @@ fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> {
                     // Recreate it with a fresh variable here.
                     let idx = (vid.as_usize() - self.type_vars.0.start.as_usize()) as usize;
                     let origin = self.type_vars.1[idx];
-                    self.infcx.next_ty_var(origin)
+                    Ok(self.infcx.next_ty_var(origin))
                 } else {
                     // This variable was created before the
                     // "fudging". Since we refresh all type
@@ -198,48 +198,43 @@ fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> {
                     debug_assert!(
                         self.infcx.inner.borrow_mut().type_variables().probe(vid).is_unknown()
                     );
-                    ty
+                    Ok(ty)
                 }
             }
             ty::Infer(ty::InferTy::IntVar(vid)) => {
-                if self.int_vars.contains(&vid) {
-                    self.infcx.next_int_var()
-                } else {
-                    ty
-                }
+                Ok(if self.int_vars.contains(&vid) { self.infcx.next_int_var() } else { ty })
             }
             ty::Infer(ty::InferTy::FloatVar(vid)) => {
-                if self.float_vars.contains(&vid) {
-                    self.infcx.next_float_var()
-                } else {
-                    ty
-                }
+                Ok(if self.float_vars.contains(&vid) { self.infcx.next_float_var() } else { ty })
             }
             _ => ty.super_fold_with(self),
         }
     }
 
-    fn fold_region(&mut self, r: ty::Region<'tcx>) -> ty::Region<'tcx> {
+    fn fold_region(&mut self, r: ty::Region<'tcx>) -> Result<ty::Region<'tcx>, Self::Error> {
         if let ty::ReVar(vid) = *r {
             if self.region_vars.0.contains(&vid) {
                 let idx = vid.index() - self.region_vars.0.start.index();
                 let origin = self.region_vars.1[idx];
-                return self.infcx.next_region_var(origin);
+                return Ok(self.infcx.next_region_var(origin));
             }
         }
-        r
+        Ok(r)
     }
 
-    fn fold_const(&mut self, ct: &'tcx ty::Const<'tcx>) -> &'tcx ty::Const<'tcx> {
+    fn fold_const(
+        &mut self,
+        ct: &'tcx ty::Const<'tcx>,
+    ) -> Result<&'tcx ty::Const<'tcx>, Self::Error> {
         if let ty::Const { val: ty::ConstKind::Infer(ty::InferConst::Var(vid)), ty } = ct {
             if self.const_vars.0.contains(&vid) {
                 // This variable was created during the fudging.
                 // Recreate it with a fresh variable here.
                 let idx = (vid.index - self.const_vars.0.start.index) as usize;
                 let origin = self.const_vars.1[idx];
-                self.infcx.next_const_var(ty, origin)
+                Ok(self.infcx.next_const_var(ty, origin))
             } else {
-                ct
+                Ok(ct)
             }
         } else {
             ct.super_fold_with(self)
index 2fd01c2d595fabe187d8019f1ad04f757b093976..4a9a63e1c76029357a4f14f033ff386c4560c6f6 100644 (file)
@@ -681,7 +681,7 @@ pub fn is_in_snapshot(&self) -> bool {
     }
 
     pub fn freshen<T: TypeFoldable<'tcx>>(&self, t: T) -> T {
-        t.fold_with(&mut self.freshener())
+        t.fold_with(&mut self.freshener()).into_ok()
     }
 
     /// Returns the origin of the type variable identified by `vid`, or `None`
@@ -1381,7 +1381,7 @@ pub fn shallow_resolve<T>(&self, value: T) -> T
     where
         T: TypeFoldable<'tcx>,
     {
-        value.fold_with(&mut ShallowResolver { infcx: self })
+        value.fold_with(&mut ShallowResolver { infcx: self }).into_ok()
     }
 
     pub fn root_var(&self, var: ty::TyVid) -> ty::TyVid {
@@ -1402,7 +1402,7 @@ pub fn resolve_vars_if_possible<T>(&self, value: T) -> T
             return value; // Avoid duplicated subst-folding.
         }
         let mut r = resolve::OpportunisticVarResolver::new(self);
-        value.fold_with(&mut r)
+        value.fold_with(&mut r).into_ok()
     }
 
     /// Returns the first unresolved variable contained in `T`. In the
@@ -1745,12 +1745,15 @@ fn tcx<'b>(&'b self) -> TyCtxt<'tcx> {
         self.infcx.tcx
     }
 
-    fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> {
-        self.infcx.shallow_resolve_ty(ty)
+    fn fold_ty(&mut self, ty: Ty<'tcx>) -> Result<Ty<'tcx>, Self::Error> {
+        Ok(self.infcx.shallow_resolve_ty(ty))
     }
 
-    fn fold_const(&mut self, ct: &'tcx ty::Const<'tcx>) -> &'tcx ty::Const<'tcx> {
-        if let ty::Const { val: ty::ConstKind::Infer(InferConst::Var(vid)), .. } = ct {
+    fn fold_const(
+        &mut self,
+        ct: &'tcx ty::Const<'tcx>,
+    ) -> Result<&'tcx ty::Const<'tcx>, Self::Error> {
+        Ok(if let ty::Const { val: ty::ConstKind::Infer(InferConst::Var(vid)), .. } = ct {
             self.infcx
                 .inner
                 .borrow_mut()
@@ -1761,7 +1764,7 @@ fn fold_const(&mut self, ct: &'tcx ty::Const<'tcx>) -> &'tcx ty::Const<'tcx> {
                 .unwrap_or(ct)
         } else {
             ct
-        }
+        })
     }
 }
 
index e2e07f2072e498ea907e7fb176ed0ff9e9d811f2..7893abbfc9bf7640030484161ddfa80b1634c225 100644 (file)
@@ -418,92 +418,94 @@ struct Instantiator<'a, 'tcx> {
 impl<'a, 'tcx> Instantiator<'a, 'tcx> {
     fn instantiate_opaque_types_in_map<T: TypeFoldable<'tcx>>(&mut self, value: T) -> T {
         let tcx = self.infcx.tcx;
-        value.fold_with(&mut BottomUpFolder {
-            tcx,
-            ty_op: |ty| {
-                if ty.references_error() {
-                    return tcx.ty_error();
-                } else if let ty::Opaque(def_id, substs) = ty.kind() {
-                    // Check that this is `impl Trait` type is
-                    // declared by `parent_def_id` -- i.e., one whose
-                    // value we are inferring.  At present, this is
-                    // always true during the first phase of
-                    // type-check, but not always true later on during
-                    // NLL. Once we support named opaque types more fully,
-                    // this same scenario will be able to arise during all phases.
-                    //
-                    // Here is an example using type alias `impl Trait`
-                    // that indicates the distinction we are checking for:
-                    //
-                    // ```rust
-                    // mod a {
-                    //   pub type Foo = impl Iterator;
-                    //   pub fn make_foo() -> Foo { .. }
-                    // }
-                    //
-                    // mod b {
-                    //   fn foo() -> a::Foo { a::make_foo() }
-                    // }
-                    // ```
-                    //
-                    // Here, the return type of `foo` references an
-                    // `Opaque` indeed, but not one whose value is
-                    // presently being inferred. You can get into a
-                    // similar situation with closure return types
-                    // today:
-                    //
-                    // ```rust
-                    // fn foo() -> impl Iterator { .. }
-                    // fn bar() {
-                    //     let x = || foo(); // returns the Opaque assoc with `foo`
-                    // }
-                    // ```
-                    if let Some(def_id) = def_id.as_local() {
-                        let opaque_hir_id = tcx.hir().local_def_id_to_hir_id(def_id);
-                        let parent_def_id = self.infcx.defining_use_anchor;
-                        let def_scope_default = || {
-                            let opaque_parent_hir_id = tcx.hir().get_parent_item(opaque_hir_id);
-                            parent_def_id == tcx.hir().local_def_id(opaque_parent_hir_id)
-                        };
-                        let (in_definition_scope, origin) =
-                            match tcx.hir().expect_item(opaque_hir_id).kind {
-                                // Anonymous `impl Trait`
-                                hir::ItemKind::OpaqueTy(hir::OpaqueTy {
-                                    impl_trait_fn: Some(parent),
-                                    origin,
-                                    ..
-                                }) => (parent == parent_def_id.to_def_id(), origin),
-                                // Named `type Foo = impl Bar;`
-                                hir::ItemKind::OpaqueTy(hir::OpaqueTy {
-                                    impl_trait_fn: None,
-                                    origin,
-                                    ..
-                                }) => (
-                                    may_define_opaque_type(tcx, parent_def_id, opaque_hir_id),
-                                    origin,
-                                ),
-                                _ => (def_scope_default(), hir::OpaqueTyOrigin::TyAlias),
+        value
+            .fold_with(&mut BottomUpFolder {
+                tcx,
+                ty_op: |ty| {
+                    if ty.references_error() {
+                        return tcx.ty_error();
+                    } else if let ty::Opaque(def_id, substs) = ty.kind() {
+                        // Check that this is `impl Trait` type is
+                        // declared by `parent_def_id` -- i.e., one whose
+                        // value we are inferring.  At present, this is
+                        // always true during the first phase of
+                        // type-check, but not always true later on during
+                        // NLL. Once we support named opaque types more fully,
+                        // this same scenario will be able to arise during all phases.
+                        //
+                        // Here is an example using type alias `impl Trait`
+                        // that indicates the distinction we are checking for:
+                        //
+                        // ```rust
+                        // mod a {
+                        //   pub type Foo = impl Iterator;
+                        //   pub fn make_foo() -> Foo { .. }
+                        // }
+                        //
+                        // mod b {
+                        //   fn foo() -> a::Foo { a::make_foo() }
+                        // }
+                        // ```
+                        //
+                        // Here, the return type of `foo` references an
+                        // `Opaque` indeed, but not one whose value is
+                        // presently being inferred. You can get into a
+                        // similar situation with closure return types
+                        // today:
+                        //
+                        // ```rust
+                        // fn foo() -> impl Iterator { .. }
+                        // fn bar() {
+                        //     let x = || foo(); // returns the Opaque assoc with `foo`
+                        // }
+                        // ```
+                        if let Some(def_id) = def_id.as_local() {
+                            let opaque_hir_id = tcx.hir().local_def_id_to_hir_id(def_id);
+                            let parent_def_id = self.infcx.defining_use_anchor;
+                            let def_scope_default = || {
+                                let opaque_parent_hir_id = tcx.hir().get_parent_item(opaque_hir_id);
+                                parent_def_id == tcx.hir().local_def_id(opaque_parent_hir_id)
                             };
-                        if in_definition_scope {
-                            let opaque_type_key =
-                                OpaqueTypeKey { def_id: def_id.to_def_id(), substs };
-                            return self.fold_opaque_ty(ty, opaque_type_key, origin);
-                        }
-
-                        debug!(
-                            "instantiate_opaque_types_in_map: \
+                            let (in_definition_scope, origin) =
+                                match tcx.hir().expect_item(def_id).kind {
+                                    // Anonymous `impl Trait`
+                                    hir::ItemKind::OpaqueTy(hir::OpaqueTy {
+                                        impl_trait_fn: Some(parent),
+                                        origin,
+                                        ..
+                                    }) => (parent == parent_def_id.to_def_id(), origin),
+                                    // Named `type Foo = impl Bar;`
+                                    hir::ItemKind::OpaqueTy(hir::OpaqueTy {
+                                        impl_trait_fn: None,
+                                        origin,
+                                        ..
+                                    }) => (
+                                        may_define_opaque_type(tcx, parent_def_id, opaque_hir_id),
+                                        origin,
+                                    ),
+                                    _ => (def_scope_default(), hir::OpaqueTyOrigin::TyAlias),
+                                };
+                            if in_definition_scope {
+                                let opaque_type_key =
+                                    OpaqueTypeKey { def_id: def_id.to_def_id(), substs };
+                                return self.fold_opaque_ty(ty, opaque_type_key, origin);
+                            }
+
+                            debug!(
+                                "instantiate_opaque_types_in_map: \
                              encountered opaque outside its definition scope \
                              def_id={:?}",
-                            def_id,
-                        );
+                                def_id,
+                            );
+                        }
                     }
-                }
 
-                ty
-            },
-            lt_op: |lt| lt,
-            ct_op: |ct| ct,
-        })
+                    ty
+                },
+                lt_op: |lt| lt,
+                ct_op: |ct| ct,
+            })
+            .into_ok()
     }
 
     #[instrument(skip(self), level = "debug")]
@@ -556,21 +558,23 @@ fn fold_opaque_ty(
             debug!(?predicate);
 
             // We can't normalize associated types from `rustc_infer`, but we can eagerly register inference variables for them.
-            let predicate = predicate.fold_with(&mut BottomUpFolder {
-                tcx,
-                ty_op: |ty| match ty.kind() {
-                    ty::Projection(projection_ty) => infcx.infer_projection(
-                        self.param_env,
-                        *projection_ty,
-                        traits::ObligationCause::misc(self.value_span, self.body_id),
-                        0,
-                        &mut self.obligations,
-                    ),
-                    _ => ty,
-                },
-                lt_op: |lt| lt,
-                ct_op: |ct| ct,
-            });
+            let predicate = predicate
+                .fold_with(&mut BottomUpFolder {
+                    tcx,
+                    ty_op: |ty| match ty.kind() {
+                        ty::Projection(projection_ty) => infcx.infer_projection(
+                            self.param_env,
+                            *projection_ty,
+                            traits::ObligationCause::misc(self.value_span, self.body_id),
+                            0,
+                            &mut self.obligations,
+                        ),
+                        _ => ty,
+                    },
+                    lt_op: |lt| lt,
+                    ct_op: |ct| ct,
+                })
+                .into_ok();
             debug!(?predicate);
 
             if let ty::PredicateKind::Projection(projection) = predicate.kind().skip_binder() {
index 4b08c2eb9c19eee7d3bf9cc9327553a17d82518c..cccdfb7452a77fd7db25cda5f59171172640f610 100644 (file)
@@ -30,25 +30,28 @@ fn tcx<'b>(&'b self) -> TyCtxt<'tcx> {
         self.infcx.tcx
     }
 
-    fn fold_ty(&mut self, t: Ty<'tcx>) -> Ty<'tcx> {
+    fn fold_ty(&mut self, t: Ty<'tcx>) -> Result<Ty<'tcx>, Self::Error> {
         if !t.has_infer_types_or_consts() {
-            t // micro-optimize -- if there is nothing in this type that this fold affects...
+            Ok(t) // micro-optimize -- if there is nothing in this type that this fold affects...
         } else {
             let t = self.infcx.shallow_resolve(t);
             t.super_fold_with(self)
         }
     }
 
-    fn fold_const(&mut self, ct: &'tcx Const<'tcx>) -> &'tcx Const<'tcx> {
+    fn fold_const(&mut self, ct: &'tcx Const<'tcx>) -> Result<&'tcx Const<'tcx>, Self::Error> {
         if !ct.has_infer_types_or_consts() {
-            ct // micro-optimize -- if there is nothing in this const that this fold affects...
+            Ok(ct) // micro-optimize -- if there is nothing in this const that this fold affects...
         } else {
             let ct = self.infcx.shallow_resolve(ct);
             ct.super_fold_with(self)
         }
     }
 
-    fn fold_mir_const(&mut self, constant: mir::ConstantKind<'tcx>) -> mir::ConstantKind<'tcx> {
+    fn fold_mir_const(
+        &mut self,
+        constant: mir::ConstantKind<'tcx>,
+    ) -> Result<mir::ConstantKind<'tcx>, Self::Error> {
         constant.super_fold_with(self)
     }
 }
@@ -75,16 +78,16 @@ fn tcx<'b>(&'b self) -> TyCtxt<'tcx> {
         self.infcx.tcx
     }
 
-    fn fold_ty(&mut self, t: Ty<'tcx>) -> Ty<'tcx> {
+    fn fold_ty(&mut self, t: Ty<'tcx>) -> Result<Ty<'tcx>, Self::Error> {
         if !t.has_infer_regions() {
-            t // micro-optimize -- if there is nothing in this type that this fold affects...
+            Ok(t) // micro-optimize -- if there is nothing in this type that this fold affects...
         } else {
             t.super_fold_with(self)
         }
     }
 
-    fn fold_region(&mut self, r: ty::Region<'tcx>) -> ty::Region<'tcx> {
-        match *r {
+    fn fold_region(&mut self, r: ty::Region<'tcx>) -> Result<ty::Region<'tcx>, Self::Error> {
+        Ok(match *r {
             ty::ReVar(rid) => {
                 let resolved = self
                     .infcx
@@ -95,12 +98,15 @@ fn fold_region(&mut self, r: ty::Region<'tcx>) -> ty::Region<'tcx> {
                 self.tcx().reuse_or_mk_region(r, ty::ReVar(resolved))
             }
             _ => r,
-        }
+        })
     }
 
-    fn fold_const(&mut self, ct: &'tcx ty::Const<'tcx>) -> &'tcx ty::Const<'tcx> {
+    fn fold_const(
+        &mut self,
+        ct: &'tcx ty::Const<'tcx>,
+    ) -> Result<&'tcx ty::Const<'tcx>, Self::Error> {
         if !ct.has_infer_regions() {
-            ct // micro-optimize -- if there is nothing in this const that this fold affects...
+            Ok(ct) // micro-optimize -- if there is nothing in this const that this fold affects...
         } else {
             ct.super_fold_with(self)
         }
@@ -175,44 +181,31 @@ pub fn fully_resolve<'a, 'tcx, T>(infcx: &InferCtxt<'a, 'tcx>, value: T) -> Fixu
 where
     T: TypeFoldable<'tcx>,
 {
-    let mut full_resolver = FullTypeResolver { infcx, err: None };
-    let result = value.fold_with(&mut full_resolver);
-    match full_resolver.err {
-        None => Ok(result),
-        Some(e) => Err(e),
-    }
+    value.fold_with(&mut FullTypeResolver { infcx })
 }
 
 // N.B. This type is not public because the protocol around checking the
 // `err` field is not enforceable otherwise.
 struct FullTypeResolver<'a, 'tcx> {
     infcx: &'a InferCtxt<'a, 'tcx>,
-    err: Option<FixupError<'tcx>>,
 }
 
 impl<'a, 'tcx> TypeFolder<'tcx> for FullTypeResolver<'a, 'tcx> {
+    type Error = FixupError<'tcx>;
+
     fn tcx<'b>(&'b self) -> TyCtxt<'tcx> {
         self.infcx.tcx
     }
 
-    fn fold_ty(&mut self, t: Ty<'tcx>) -> Ty<'tcx> {
+    fn fold_ty(&mut self, t: Ty<'tcx>) -> Result<Ty<'tcx>, Self::Error> {
         if !t.needs_infer() {
-            t // micro-optimize -- if there is nothing in this type that this fold affects...
+            Ok(t) // micro-optimize -- if there is nothing in this type that this fold affects...
         } else {
             let t = self.infcx.shallow_resolve(t);
             match *t.kind() {
-                ty::Infer(ty::TyVar(vid)) => {
-                    self.err = Some(FixupError::UnresolvedTy(vid));
-                    self.tcx().ty_error()
-                }
-                ty::Infer(ty::IntVar(vid)) => {
-                    self.err = Some(FixupError::UnresolvedIntTy(vid));
-                    self.tcx().ty_error()
-                }
-                ty::Infer(ty::FloatVar(vid)) => {
-                    self.err = Some(FixupError::UnresolvedFloatTy(vid));
-                    self.tcx().ty_error()
-                }
+                ty::Infer(ty::TyVar(vid)) => Err(FixupError::UnresolvedTy(vid)),
+                ty::Infer(ty::IntVar(vid)) => Err(FixupError::UnresolvedIntTy(vid)),
+                ty::Infer(ty::FloatVar(vid)) => Err(FixupError::UnresolvedFloatTy(vid)),
                 ty::Infer(_) => {
                     bug!("Unexpected type in full type resolver: {:?}", t);
                 }
@@ -221,28 +214,30 @@ fn fold_ty(&mut self, t: Ty<'tcx>) -> Ty<'tcx> {
         }
     }
 
-    fn fold_region(&mut self, r: ty::Region<'tcx>) -> ty::Region<'tcx> {
+    fn fold_region(&mut self, r: ty::Region<'tcx>) -> Result<ty::Region<'tcx>, Self::Error> {
         match *r {
-            ty::ReVar(rid) => self
+            ty::ReVar(rid) => Ok(self
                 .infcx
                 .lexical_region_resolutions
                 .borrow()
                 .as_ref()
                 .expect("region resolution not performed")
-                .resolve_var(rid),
-            _ => r,
+                .resolve_var(rid)),
+            _ => Ok(r),
         }
     }
 
-    fn fold_const(&mut self, c: &'tcx ty::Const<'tcx>) -> &'tcx ty::Const<'tcx> {
+    fn fold_const(
+        &mut self,
+        c: &'tcx ty::Const<'tcx>,
+    ) -> Result<&'tcx ty::Const<'tcx>, Self::Error> {
         if !c.needs_infer() {
-            c // micro-optimize -- if there is nothing in this const that this fold affects...
+            Ok(c) // micro-optimize -- if there is nothing in this const that this fold affects...
         } else {
             let c = self.infcx.shallow_resolve(c);
             match c.val {
                 ty::ConstKind::Infer(InferConst::Var(vid)) => {
-                    self.err = Some(FixupError::UnresolvedConst(vid));
-                    return self.tcx().const_error(c.ty);
+                    return Err(FixupError::UnresolvedConst(vid));
                 }
                 ty::ConstKind::Infer(InferConst::Fresh(_)) => {
                     bug!("Unexpected const in full const resolver: {:?}", c);
index e4b407e7c112d838057df364b0d4de3c1f13e5d3..5153427954ccc723f761dbf1f79ab274146b8f1f 100644 (file)
@@ -24,6 +24,7 @@
 #![feature(control_flow_enum)]
 #![feature(min_specialization)]
 #![feature(label_break_value)]
+#![feature(unwrap_infallible)]
 #![recursion_limit = "512"] // For rustdoc
 
 #[macro_use]
index b48ca3bd0c0d355d9cd8d3ed2aa311b590873eab..544b89397790a0f6b321228f346771ec6e95e49a 100644 (file)
@@ -60,13 +60,13 @@ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
 // TypeFoldable implementations.
 
 impl<'tcx, O: TypeFoldable<'tcx>> TypeFoldable<'tcx> for traits::Obligation<'tcx, O> {
-    fn super_fold_with<F: TypeFolder<'tcx>>(self, folder: &mut F) -> Self {
-        traits::Obligation {
+    fn super_fold_with<F: TypeFolder<'tcx>>(self, folder: &mut F) -> Result<Self, F::Error> {
+        Ok(traits::Obligation {
             cause: self.cause,
             recursion_depth: self.recursion_depth,
-            predicate: self.predicate.fold_with(folder),
-            param_env: self.param_env.fold_with(folder),
-        }
+            predicate: self.predicate.fold_with(folder)?,
+            param_env: self.param_env.fold_with(folder)?,
+        })
     }
 
     fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> {
index f2e4e70a197796923fb8eae72e799cb39d829d74..077d3e1c82058bd055d33ed0b673571ab001c134 100644 (file)
@@ -1079,6 +1079,10 @@ fn check_arm(&mut self, cx: &EarlyContext<'_>, arm: &ast::Arm) {
     fn check_expr(&mut self, cx: &EarlyContext<'_>, expr: &ast::Expr) {
         warn_if_doc(cx, expr.span, "expressions", &expr.attrs);
     }
+
+    fn check_generic_param(&mut self, cx: &EarlyContext<'_>, param: &ast::GenericParam) {
+        warn_if_doc(cx, param.ident.span, "generic parameters", &param.attrs);
+    }
 }
 
 declare_lint! {
@@ -3011,7 +3015,7 @@ fn check_foreign_item(&mut self, cx: &LateContext<'tcx>, this_fi: &hir::ForeignI
                     this_decl_ty,
                     CItemKind::Declaration,
                 ) {
-                    let orig_fi = tcx.hir().expect_foreign_item(existing_hid);
+                    let orig_fi = tcx.hir().expect_foreign_item(existing_hid.expect_owner());
                     let orig = Self::name_of_extern_decl(tcx, orig_fi);
 
                     // We want to ensure that we use spans for both decls that include where the
index 876245747f64a50acf8a94f702fd3bfc176a9978..65772d02376d43ae082a6e4b11933604c5649fb3 100644 (file)
@@ -91,16 +91,14 @@ fn enforce_mem_variant_count(cx: &LateContext<'_>, func_expr: &hir::Expr<'_>, sp
 
 impl<'tcx> LateLintPass<'tcx> for EnumIntrinsicsNonEnums {
     fn check_expr(&mut self, cx: &LateContext<'_>, expr: &hir::Expr<'_>) {
-        if let hir::ExprKind::Call(ref func, ref args) = expr.kind {
-            if let hir::ExprKind::Path(ref qpath) = func.kind {
-                if let Some(def_id) = cx.qpath_res(qpath, func.hir_id).opt_def_id() {
-                    if cx.tcx.is_diagnostic_item(sym::mem_discriminant, def_id) {
-                        enforce_mem_discriminant(cx, func, expr.span, args[0].span);
-                    } else if cx.tcx.is_diagnostic_item(sym::mem_variant_count, def_id) {
-                        enforce_mem_variant_count(cx, func, expr.span);
-                    }
-                }
-            }
+        let hir::ExprKind::Call(func, args) = &expr.kind else { return };
+        let hir::ExprKind::Path(qpath) = &func.kind else { return };
+        let Some(def_id) = cx.qpath_res(qpath, func.hir_id).opt_def_id() else { return };
+        let Some(name) = cx.tcx.get_diagnostic_name(def_id) else { return };
+        match name {
+            sym::mem_discriminant => enforce_mem_discriminant(cx, func, expr.span, args[0].span),
+            sym::mem_variant_count => enforce_mem_variant_count(cx, func, expr.span),
+            _ => {}
         }
     }
 }
index 507b4421fa160266c860d468c0e5ec1f5eaed56f..7cc40cc60d9cdf7fab5cba1bf0922441a37ef2c6 100644 (file)
@@ -33,6 +33,7 @@
 #![cfg_attr(bootstrap, feature(format_args_capture))]
 #![feature(iter_order_by)]
 #![feature(iter_zip)]
+#![feature(let_else)]
 #![feature(never_type)]
 #![feature(nll)]
 #![feature(control_flow_enum)]
index f2ad72f97eca77a9a22937a6b4f2e6602ef33106..4a9b27e89b19927464ef8bdf71849252261c0e70 100644 (file)
@@ -309,14 +309,21 @@ fn panic_call<'tcx>(cx: &LateContext<'tcx>, f: &'tcx hir::Expr<'tcx>) -> (Span,
     // Unwrap more levels of macro expansion, as panic_2015!()
     // was likely expanded from panic!() and possibly from
     // [debug_]assert!().
-    for &i in
-        &[sym::std_panic_macro, sym::core_panic_macro, sym::assert_macro, sym::debug_assert_macro]
-    {
+    loop {
         let parent = expn.call_site.ctxt().outer_expn_data();
-        if parent.macro_def_id.map_or(false, |id| cx.tcx.is_diagnostic_item(i, id)) {
-            expn = parent;
-            panic_macro = i;
+        let Some(id) = parent.macro_def_id else { break };
+        let Some(name) = cx.tcx.get_diagnostic_name(id) else { break };
+        if !matches!(
+            name,
+            sym::core_panic_macro
+                | sym::std_panic_macro
+                | sym::assert_macro
+                | sym::debug_assert_macro
+        ) {
+            break;
         }
+        expn = parent;
+        panic_macro = name;
     }
 
     let macro_symbol =
index d2c970468abc7d8de5800e76aa684710defaad18..a3a3cd0077dbefd70c80018aaf5550d93ca9b8e6 100644 (file)
@@ -75,38 +75,36 @@ fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) {
             _ => return,
         };
         // (Re)check that it implements the noop diagnostic.
-        for s in [sym::noop_method_clone, sym::noop_method_deref, sym::noop_method_borrow].iter() {
-            if cx.tcx.is_diagnostic_item(*s, i.def_id()) {
-                let method = &call.ident.name;
-                let receiver = &elements[0];
-                let receiver_ty = cx.typeck_results().expr_ty(receiver);
-                let expr_ty = cx.typeck_results().expr_ty_adjusted(expr);
-                if receiver_ty != expr_ty {
-                    // This lint will only trigger if the receiver type and resulting expression \
-                    // type are the same, implying that the method call is unnecessary.
-                    return;
-                }
-                let expr_span = expr.span;
-                let note = format!(
-                    "the type `{:?}` which `{}` is being called on is the same as \
-                     the type returned from `{}`, so the method call does not do \
-                     anything and can be removed",
-                    receiver_ty, method, method,
-                );
-
-                let span = expr_span.with_lo(receiver.span.hi());
-                cx.struct_span_lint(NOOP_METHOD_CALL, span, |lint| {
-                    let method = &call.ident.name;
-                    let message = format!(
-                        "call to `.{}()` on a reference in this situation does nothing",
-                        &method,
-                    );
-                    lint.build(&message)
-                        .span_label(span, "unnecessary method call")
-                        .note(&note)
-                        .emit()
-                });
-            }
+        let Some(name) = cx.tcx.get_diagnostic_name(i.def_id()) else { return };
+        if !matches!(
+            name,
+            sym::noop_method_borrow | sym::noop_method_clone | sym::noop_method_deref
+        ) {
+            return;
         }
+        let method = &call.ident.name;
+        let receiver = &elements[0];
+        let receiver_ty = cx.typeck_results().expr_ty(receiver);
+        let expr_ty = cx.typeck_results().expr_ty_adjusted(expr);
+        if receiver_ty != expr_ty {
+            // This lint will only trigger if the receiver type and resulting expression \
+            // type are the same, implying that the method call is unnecessary.
+            return;
+        }
+        let expr_span = expr.span;
+        let note = format!(
+            "the type `{:?}` which `{}` is being called on is the same as \
+             the type returned from `{}`, so the method call does not do \
+             anything and can be removed",
+            receiver_ty, method, method,
+        );
+
+        let span = expr_span.with_lo(receiver.span.hi());
+        cx.struct_span_lint(NOOP_METHOD_CALL, span, |lint| {
+            let method = &call.ident.name;
+            let message =
+                format!("call to `.{}()` on a reference in this situation does nothing", &method,);
+            lint.build(&message).span_label(span, "unnecessary method call").note(&note).emit()
+        });
     }
 }
index 708cd56e068b537c40be4088eb3d961194443b2f..b20f7357b35b898ac537887318b59999575b6bcf 100644 (file)
@@ -1337,7 +1337,9 @@ fn check_item(&mut self, cx: &LateContext<'_>, it: &hir::Item<'_>) {
             let layout = match cx.layout_of(ty) {
                 Ok(layout) => layout,
                 Err(
-                    ty::layout::LayoutError::Unknown(_) | ty::layout::LayoutError::SizeOverflow(_),
+                    ty::layout::LayoutError::Unknown(_)
+                    | ty::layout::LayoutError::SizeOverflow(_)
+                    | ty::layout::LayoutError::NormalizationFailure(_, _),
                 ) => return,
             };
             let (variants, tag) = match layout.variants {
index 8cd2bd12450e3d55a1c548cc4475d1f598754225..154f554d607dfb60af9afaa03d54952f96d4a178 100644 (file)
@@ -10,6 +10,7 @@ using namespace llvm;
 
 struct LLVMRustCounterMappingRegion {
   coverage::Counter Count;
+  coverage::Counter FalseCount;
   uint32_t FileID;
   uint32_t ExpandedFileID;
   uint32_t LineStart;
@@ -53,7 +54,7 @@ extern "C" void LLVMRustCoverageWriteMappingToBuffer(
   MappingRegions.reserve(NumMappingRegions);
   for (const auto &Region : makeArrayRef(RustMappingRegions, NumMappingRegions)) {
     MappingRegions.emplace_back(
-        Region.Count, Region.FileID, Region.ExpandedFileID,
+        Region.Count, Region.FalseCount, Region.FileID, Region.ExpandedFileID,
         Region.LineStart, Region.ColumnStart, Region.LineEnd, Region.ColumnEnd,
         Region.Kind);
   }
@@ -108,5 +109,9 @@ extern "C" void LLVMRustCoverageWriteMappingVarNameToString(RustStringRef Str) {
 }
 
 extern "C" uint32_t LLVMRustCoverageMappingVersion() {
-  return coverage::CovMapVersion::Version4;
+#if LLVM_VERSION_GE(13, 0)
+  return coverage::CovMapVersion::Version6;
+#else
+  return coverage::CovMapVersion::Version5;
+#endif
 }
index bb6d42c1a9cbb0c3d42b644863808511802d3854..94d2a4b8e4c9be23d2b505b48e576fbc6c1c79d7 100644 (file)
@@ -1,5 +1,6 @@
 #include "LLVMWrapper.h"
 #include "llvm/IR/DebugInfoMetadata.h"
+#include "llvm/IR/DiagnosticHandler.h"
 #include "llvm/IR/DiagnosticInfo.h"
 #include "llvm/IR/DiagnosticPrinter.h"
 #include "llvm/IR/GlobalVariable.h"
@@ -1177,10 +1178,13 @@ static LLVMRustDiagnosticKind toRust(DiagnosticKind Kind) {
   case DK_SampleProfile:
     return LLVMRustDiagnosticKind::SampleProfile;
   case DK_OptimizationRemark:
+  case DK_MachineOptimizationRemark:
     return LLVMRustDiagnosticKind::OptimizationRemark;
   case DK_OptimizationRemarkMissed:
+  case DK_MachineOptimizationRemarkMissed:
     return LLVMRustDiagnosticKind::OptimizationRemarkMissed;
   case DK_OptimizationRemarkAnalysis:
+  case DK_MachineOptimizationRemarkAnalysis:
     return LLVMRustDiagnosticKind::OptimizationRemarkAnalysis;
   case DK_OptimizationRemarkAnalysisFPCommute:
     return LLVMRustDiagnosticKind::OptimizationRemarkAnalysisFPCommute;
@@ -1783,3 +1787,92 @@ extern "C" LLVMRustResult LLVMRustWriteImportLibrary(
     return LLVMRustResult::Success;
   }
 }
+
+// Transfers ownership of DiagnosticHandler unique_ptr to the caller.
+extern "C" DiagnosticHandler *
+LLVMRustContextGetDiagnosticHandler(LLVMContextRef C) {
+  std::unique_ptr<DiagnosticHandler> DH = unwrap(C)->getDiagnosticHandler();
+  return DH.release();
+}
+
+// Sets unique_ptr to object of DiagnosticHandler to provide custom diagnostic
+// handling. Ownership of the handler is moved to the LLVMContext.
+extern "C" void LLVMRustContextSetDiagnosticHandler(LLVMContextRef C,
+                                                    DiagnosticHandler *DH) {
+  unwrap(C)->setDiagnosticHandler(std::unique_ptr<DiagnosticHandler>(DH));
+}
+
+using LLVMDiagnosticHandlerTy = DiagnosticHandler::DiagnosticHandlerTy;
+
+// Configures a diagnostic handler that invokes provided callback when a
+// backend needs to emit a diagnostic.
+//
+// When RemarkAllPasses is true, remarks are enabled for all passes. Otherwise
+// the RemarkPasses array specifies individual passes for which remarks will be
+// enabled.
+extern "C" void LLVMRustContextConfigureDiagnosticHandler(
+    LLVMContextRef C, LLVMDiagnosticHandlerTy DiagnosticHandlerCallback,
+    void *DiagnosticHandlerContext, bool RemarkAllPasses,
+    const char * const * RemarkPasses, size_t RemarkPassesLen) {
+
+  class RustDiagnosticHandler final : public DiagnosticHandler {
+  public:
+    RustDiagnosticHandler(LLVMDiagnosticHandlerTy DiagnosticHandlerCallback,
+                          void *DiagnosticHandlerContext,
+                          bool RemarkAllPasses,
+                          std::vector<std::string> RemarkPasses)
+        : DiagnosticHandlerCallback(DiagnosticHandlerCallback),
+          DiagnosticHandlerContext(DiagnosticHandlerContext),
+          RemarkAllPasses(RemarkAllPasses),
+          RemarkPasses(RemarkPasses) {}
+
+    virtual bool handleDiagnostics(const DiagnosticInfo &DI) override {
+      if (DiagnosticHandlerCallback) {
+        DiagnosticHandlerCallback(DI, DiagnosticHandlerContext);
+        return true;
+      }
+      return false;
+    }
+
+    bool isAnalysisRemarkEnabled(StringRef PassName) const override {
+      return isRemarkEnabled(PassName);
+    }
+
+    bool isMissedOptRemarkEnabled(StringRef PassName) const override {
+      return isRemarkEnabled(PassName);
+    }
+
+    bool isPassedOptRemarkEnabled(StringRef PassName) const override {
+      return isRemarkEnabled(PassName);
+    }
+
+    bool isAnyRemarkEnabled() const override {
+      return RemarkAllPasses || !RemarkPasses.empty();
+    }
+
+  private:
+    bool isRemarkEnabled(StringRef PassName) const {
+      if (RemarkAllPasses)
+        return true;
+
+      for (auto &Pass : RemarkPasses)
+        if (Pass == PassName)
+          return true;
+
+      return false;
+    }
+
+    LLVMDiagnosticHandlerTy DiagnosticHandlerCallback = nullptr;
+    void *DiagnosticHandlerContext = nullptr;
+
+    bool RemarkAllPasses = false;
+    std::vector<std::string> RemarkPasses;
+  };
+
+  std::vector<std::string> Passes;
+  for (size_t I = 0; I != RemarkPassesLen; ++I)
+    Passes.push_back(RemarkPasses[I]);
+
+  unwrap(C)->setDiagnosticHandler(std::make_unique<RustDiagnosticHandler>(
+      DiagnosticHandlerCallback, DiagnosticHandlerContext, RemarkAllPasses, Passes));
+}
index 082af087bf49fd720236862aa438776024495b49..769f009b492067c7141a871334025929f9b912aa 100644 (file)
@@ -17,7 +17,7 @@ pub fn type_foldable_derive(mut s: synstructure::Structure<'_>) -> proc_macro2::
         vi.construct(|_, index| {
             let bind = &bindings[index];
             quote! {
-                ::rustc_middle::ty::fold::TypeFoldable::fold_with(#bind, __folder)
+                ::rustc_middle::ty::fold::TypeFoldable::fold_with(#bind, __folder)?
             }
         })
     });
@@ -28,8 +28,8 @@ pub fn type_foldable_derive(mut s: synstructure::Structure<'_>) -> proc_macro2::
             fn super_fold_with<__F: ::rustc_middle::ty::fold::TypeFolder<'tcx>>(
                 self,
                 __folder: &mut __F
-            ) -> Self {
-                match self { #body_fold }
+            ) -> Result<Self, __F::Error> {
+                Ok(match self { #body_fold })
             }
 
             fn super_visit_with<__F: ::rustc_middle::ty::fold::TypeVisitor<'tcx>>(
index d46829c2ceea693b047305ca5165b8dd0696a9fd..514a49d7e2ce27f25b59706720158ad62b249788 100644 (file)
@@ -1152,8 +1152,7 @@ fn encode_info_for_trait_item(&mut self, def_id: DefId) {
         debug!("EncodeContext::encode_info_for_trait_item({:?})", def_id);
         let tcx = self.tcx;
 
-        let hir_id = tcx.hir().local_def_id_to_hir_id(def_id.expect_local());
-        let ast_item = tcx.hir().expect_trait_item(hir_id);
+        let ast_item = tcx.hir().expect_trait_item(def_id.expect_local());
         let trait_item = tcx.associated_item(def_id);
 
         let container = match trait_item.defaultness {
@@ -1221,8 +1220,7 @@ fn encode_info_for_impl_item(&mut self, def_id: DefId) {
         debug!("EncodeContext::encode_info_for_impl_item({:?})", def_id);
         let tcx = self.tcx;
 
-        let hir_id = self.tcx.hir().local_def_id_to_hir_id(def_id.expect_local());
-        let ast_item = self.tcx.hir().expect_impl_item(hir_id);
+        let ast_item = self.tcx.hir().expect_impl_item(def_id.expect_local());
         let impl_item = self.tcx.associated_item(def_id);
 
         let container = match impl_item.defaultness {
@@ -1751,7 +1749,7 @@ fn encode_crate_deps(&mut self) -> Lazy<[CrateDep]> {
     fn encode_lib_features(&mut self) -> Lazy<[(Symbol, Option<Symbol>)]> {
         empty_proc_macro!(self);
         let tcx = self.tcx;
-        let lib_features = tcx.lib_features();
+        let lib_features = tcx.lib_features(());
         self.lazy(lib_features.to_vec())
     }
 
index d9d0781b37aacefe4afab97366de2b6448907d6e..5c4c2eee21fc1e5c954720987ee08f079a97b44f 100644 (file)
@@ -869,24 +869,24 @@ pub fn get_foreign_abi(&self, hir_id: HirId) -> Abi {
         bug!("expected foreign mod or inlined parent, found {}", self.node_to_string(parent))
     }
 
-    pub fn expect_item(&self, id: HirId) -> &'hir Item<'hir> {
-        match self.tcx.hir_owner(id.expect_owner()) {
+    pub fn expect_item(&self, id: LocalDefId) -> &'hir Item<'hir> {
+        match self.tcx.hir_owner(id) {
             Some(Owner { node: OwnerNode::Item(item), .. }) => item,
-            _ => bug!("expected item, found {}", self.node_to_string(id)),
+            _ => bug!("expected item, found {}", self.node_to_string(HirId::make_owner(id))),
         }
     }
 
-    pub fn expect_impl_item(&self, id: HirId) -> &'hir ImplItem<'hir> {
-        match self.tcx.hir_owner(id.expect_owner()) {
+    pub fn expect_impl_item(&self, id: LocalDefId) -> &'hir ImplItem<'hir> {
+        match self.tcx.hir_owner(id) {
             Some(Owner { node: OwnerNode::ImplItem(item), .. }) => item,
-            _ => bug!("expected impl item, found {}", self.node_to_string(id)),
+            _ => bug!("expected impl item, found {}", self.node_to_string(HirId::make_owner(id))),
         }
     }
 
-    pub fn expect_trait_item(&self, id: HirId) -> &'hir TraitItem<'hir> {
-        match self.tcx.hir_owner(id.expect_owner()) {
+    pub fn expect_trait_item(&self, id: LocalDefId) -> &'hir TraitItem<'hir> {
+        match self.tcx.hir_owner(id) {
             Some(Owner { node: OwnerNode::TraitItem(item), .. }) => item,
-            _ => bug!("expected trait item, found {}", self.node_to_string(id)),
+            _ => bug!("expected trait item, found {}", self.node_to_string(HirId::make_owner(id))),
         }
     }
 
@@ -897,10 +897,12 @@ pub fn expect_variant(&self, id: HirId) -> &'hir Variant<'hir> {
         }
     }
 
-    pub fn expect_foreign_item(&self, id: HirId) -> &'hir ForeignItem<'hir> {
-        match self.tcx.hir_owner(id.expect_owner()) {
+    pub fn expect_foreign_item(&self, id: LocalDefId) -> &'hir ForeignItem<'hir> {
+        match self.tcx.hir_owner(id) {
             Some(Owner { node: OwnerNode::ForeignItem(item), .. }) => item,
-            _ => bug!("expected foreign item, found {}", self.node_to_string(id)),
+            _ => {
+                bug!("expected foreign item, found {}", self.node_to_string(HirId::make_owner(id)))
+            }
         }
     }
 
index 9ce9f65a49066bb88064a3e6786a551a8a52de8a..b67ad8b770ea1537ca2e8264d2a36a5eeb50cb30 100644 (file)
@@ -56,6 +56,7 @@
 #![feature(try_blocks)]
 #![feature(try_reserve_kind)]
 #![feature(nonzero_ops)]
+#![feature(unwrap_infallible)]
 #![recursion_limit = "512"]
 
 #[macro_use]
index c0f2a76c19d6e93021fc68ce50469f1e8bdc743f..c0cf265b2287957f1edd0fb8eb5513d00f2c165d 100644 (file)
@@ -55,8 +55,8 @@ impl<$tcx> $crate::ty::fold::TypeFoldable<$tcx> for $ty {
                 fn super_fold_with<F: $crate::ty::fold::TypeFolder<$tcx>>(
                     self,
                     _: &mut F
-                ) -> $ty {
-                    self
+                ) -> ::std::result::Result<$ty, F::Error> {
+                    Ok(self)
                 }
 
                 fn super_visit_with<F: $crate::ty::fold::TypeVisitor<$tcx>>(
@@ -98,7 +98,7 @@ impl<$($p),*> $crate::ty::fold::TypeFoldable<$tcx> for $s
             fn super_fold_with<V: $crate::ty::fold::TypeFolder<$tcx>>(
                 self,
                 folder: &mut V,
-            ) -> Self {
+            ) -> ::std::result::Result<Self, V::Error> {
                 EnumTypeFoldableImpl!(@FoldVariants(self, folder) input($($variants)*) output())
             }
 
@@ -112,9 +112,9 @@ fn super_visit_with<V: $crate::ty::fold::TypeVisitor<$tcx>>(
     };
 
     (@FoldVariants($this:expr, $folder:expr) input() output($($output:tt)*)) => {
-        match $this {
+        Ok(match $this {
             $($output)*
-        }
+        })
     };
 
     (@FoldVariants($this:expr, $folder:expr)
@@ -126,7 +126,7 @@ fn super_visit_with<V: $crate::ty::fold::TypeVisitor<$tcx>>(
                 output(
                     $variant ( $($variant_arg),* ) => {
                         $variant (
-                            $($crate::ty::fold::TypeFoldable::fold_with($variant_arg, $folder)),*
+                            $($crate::ty::fold::TypeFoldable::fold_with($variant_arg, $folder)?),*
                         )
                     }
                     $($output)*
@@ -145,7 +145,7 @@ fn super_visit_with<V: $crate::ty::fold::TypeVisitor<$tcx>>(
                         $variant {
                             $($variant_arg: $crate::ty::fold::TypeFoldable::fold_with(
                                 $variant_arg, $folder
-                            )),* }
+                            )?),* }
                     }
                     $($output)*
                 )
index 605e0bc2e63ef7d6810989ebafc401bf3822f274..39ca41c92ff7569f749f4371fef9696591020bb3 100644 (file)
@@ -7,13 +7,12 @@
 //! [rustc dev guide]: https://rustc-dev-guide.rust-lang.org/borrow_check.html
 
 use crate::ty::TyCtxt;
-use rustc_hir as hir;
-use rustc_hir::Node;
-use rustc_query_system::ich::{NodeIdHashingMode, StableHashingContext};
-
 use rustc_data_structures::fx::FxHashMap;
 use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
+use rustc_hir as hir;
+use rustc_hir::Node;
 use rustc_macros::HashStable;
+use rustc_query_system::ich::{NodeIdHashingMode, StableHashingContext};
 use rustc_span::{Span, DUMMY_SP};
 
 use std::fmt;
@@ -210,11 +209,6 @@ pub struct ScopeTree {
     /// If not empty, this body is the root of this region hierarchy.
     pub root_body: Option<hir::HirId>,
 
-    /// The parent of the root body owner, if the latter is an
-    /// an associated const or method, as impls/traits can also
-    /// have lifetime parameters free in this body.
-    pub root_parent: Option<hir::HirId>,
-
     /// Maps from a scope ID to the enclosing scope id;
     /// this is usually corresponding to the lexical nesting, though
     /// in the case of closures the parent scope is the innermost
@@ -445,7 +439,6 @@ impl<'a> HashStable<StableHashingContext<'a>> for ScopeTree {
     fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher) {
         let ScopeTree {
             root_body,
-            root_parent,
             ref body_expr_count,
             ref parent_map,
             ref var_map,
@@ -455,8 +448,7 @@ fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHas
         } = *self;
 
         hcx.with_node_id_hashing_mode(NodeIdHashingMode::HashDefPath, |hcx| {
-            root_body.hash_stable(hcx, hasher);
-            root_parent.hash_stable(hcx, hasher);
+            root_body.hash_stable(hcx, hasher)
         });
 
         body_expr_count.hash_stable(hcx, hasher);
index ddb1a84fe7bdffbd368cf8028572c4916a27f704..640d3a5a02b0f0ae7e1efc759a9f13a9997096a5 100644 (file)
@@ -21,9 +21,9 @@ pub struct ExpressionOperandId {
 impl ExpressionOperandId {
     /// An expression operand for a "zero counter", as described in the following references:
     ///
-    /// * <https://github.com/rust-lang/llvm-project/blob/rustc/11.0-2020-10-12/llvm/docs/CoverageMappingFormat.rst#counter>
-    /// * <https://github.com/rust-lang/llvm-project/blob/rustc/11.0-2020-10-12/llvm/docs/CoverageMappingFormat.rst#tag>
-    /// * <https://github.com/rust-lang/llvm-project/blob/rustc/11.0-2020-10-12/llvm/docs/CoverageMappingFormat.rst#counter-expressions>
+    /// * <https://github.com/rust-lang/llvm-project/blob/rustc/13.0-2021-09-30/llvm/docs/CoverageMappingFormat.rst#counter>
+    /// * <https://github.com/rust-lang/llvm-project/blob/rustc/13.0-2021-09-30/llvm/docs/CoverageMappingFormat.rst#tag>
+    /// * <https://github.com/rust-lang/llvm-project/blob/rustc/13.0-2021-09-30/llvm/docs/CoverageMappingFormat.rst#counter-expressions>
     ///
     /// This operand can be used to count two or more separate code regions with a single counter,
     /// if they run sequentially with no branches, by injecting the `Counter` in a `BasicBlock` for
index 7a51bb4a1f32ae828f9de259450a815ba37981c1..8e4a17bfa65cb531c578999f827b596570f9ef6a 100644 (file)
@@ -492,9 +492,6 @@ pub fn downcast_ref<T: Any>(&self) -> Option<&T> {
     }
 }
 
-#[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))]
-static_assert_size!(InterpError<'_>, 64);
-
 pub enum InterpError<'tcx> {
     /// The program caused undefined behavior.
     UndefinedBehavior(UndefinedBehaviorInfo<'tcx>),
index 4210e07d2780b5d490b57aa0f67b8e9d46d4bc4d..a05b8a1da8d7f008a8b9def9e6395eccff64ac93 100644 (file)
@@ -2760,11 +2760,11 @@ pub(crate) fn variant(
 TrivialTypeFoldableAndLiftImpls! { ProjectionKind, }
 
 impl<'tcx> TypeFoldable<'tcx> for UserTypeProjection {
-    fn super_fold_with<F: TypeFolder<'tcx>>(self, folder: &mut F) -> Self {
-        UserTypeProjection {
-            base: self.base.fold_with(folder),
-            projs: self.projs.fold_with(folder),
-        }
+    fn super_fold_with<F: TypeFolder<'tcx>>(self, folder: &mut F) -> Result<Self, F::Error> {
+        Ok(UserTypeProjection {
+            base: self.base.fold_with(folder)?,
+            projs: self.projs.fold_with(folder)?,
+        })
     }
 
     fn super_visit_with<Vs: TypeVisitor<'tcx>>(
index b7201f7acf392dac6567e4d4ba7d6e69298b467c..df7c6d9cf66501a41b67d809f66a4999f259af78 100644 (file)
 }
 
 impl<'tcx> TypeFoldable<'tcx> for Terminator<'tcx> {
-    fn super_fold_with<F: TypeFolder<'tcx>>(self, folder: &mut F) -> Self {
+    fn super_fold_with<F: TypeFolder<'tcx>>(self, folder: &mut F) -> Result<Self, F::Error> {
         use crate::mir::TerminatorKind::*;
 
         let kind = match self.kind {
             Goto { target } => Goto { target },
             SwitchInt { discr, switch_ty, targets } => SwitchInt {
-                discr: discr.fold_with(folder),
-                switch_ty: switch_ty.fold_with(folder),
+                discr: discr.fold_with(folder)?,
+                switch_ty: switch_ty.fold_with(folder)?,
                 targets,
             },
             Drop { place, target, unwind } => {
-                Drop { place: place.fold_with(folder), target, unwind }
+                Drop { place: place.fold_with(folder)?, target, unwind }
             }
             DropAndReplace { place, value, target, unwind } => DropAndReplace {
-                place: place.fold_with(folder),
-                value: value.fold_with(folder),
+                place: place.fold_with(folder)?,
+                value: value.fold_with(folder)?,
                 target,
                 unwind,
             },
             Yield { value, resume, resume_arg, drop } => Yield {
-                value: value.fold_with(folder),
+                value: value.fold_with(folder)?,
                 resume,
-                resume_arg: resume_arg.fold_with(folder),
+                resume_arg: resume_arg.fold_with(folder)?,
                 drop,
             },
             Call { func, args, destination, cleanup, from_hir_call, fn_span } => {
-                let dest = destination.map(|(loc, dest)| (loc.fold_with(folder), dest));
+                let dest = destination
+                    .map(|(loc, dest)| (loc.fold_with(folder).map(|loc| (loc, dest))))
+                    .transpose()?;
 
                 Call {
-                    func: func.fold_with(folder),
-                    args: args.fold_with(folder),
+                    func: func.fold_with(folder)?,
+                    args: args.fold_with(folder)?,
                     destination: dest,
                     cleanup,
                     from_hir_call,
@@ -57,15 +59,15 @@ fn super_fold_with<F: TypeFolder<'tcx>>(self, folder: &mut F) -> Self {
                 use AssertKind::*;
                 let msg = match msg {
                     BoundsCheck { len, index } => {
-                        BoundsCheck { len: len.fold_with(folder), index: index.fold_with(folder) }
+                        BoundsCheck { len: len.fold_with(folder)?, index: index.fold_with(folder)? }
                     }
-                    Overflow(op, l, r) => Overflow(op, l.fold_with(folder), r.fold_with(folder)),
-                    OverflowNeg(op) => OverflowNeg(op.fold_with(folder)),
-                    DivisionByZero(op) => DivisionByZero(op.fold_with(folder)),
-                    RemainderByZero(op) => RemainderByZero(op.fold_with(folder)),
+                    Overflow(op, l, r) => Overflow(op, l.fold_with(folder)?, r.fold_with(folder)?),
+                    OverflowNeg(op) => OverflowNeg(op.fold_with(folder)?),
+                    DivisionByZero(op) => DivisionByZero(op.fold_with(folder)?),
+                    RemainderByZero(op) => RemainderByZero(op.fold_with(folder)?),
                     ResumedAfterReturn(_) | ResumedAfterPanic(_) => msg,
                 };
-                Assert { cond: cond.fold_with(folder), expected, msg, target, cleanup }
+                Assert { cond: cond.fold_with(folder)?, expected, msg, target, cleanup }
             }
             GeneratorDrop => GeneratorDrop,
             Resume => Resume,
@@ -78,13 +80,13 @@ fn super_fold_with<F: TypeFolder<'tcx>>(self, folder: &mut F) -> Self {
             FalseUnwind { real_target, unwind } => FalseUnwind { real_target, unwind },
             InlineAsm { template, operands, options, line_spans, destination } => InlineAsm {
                 template,
-                operands: operands.fold_with(folder),
+                operands: operands.fold_with(folder)?,
                 options,
                 line_spans,
                 destination,
             },
         };
-        Terminator { source_info: self.source_info, kind }
+        Ok(Terminator { source_info: self.source_info, kind })
     }
 
     fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> {
@@ -140,8 +142,8 @@ fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow
 }
 
 impl<'tcx> TypeFoldable<'tcx> for GeneratorKind {
-    fn super_fold_with<F: TypeFolder<'tcx>>(self, _: &mut F) -> Self {
-        self
+    fn super_fold_with<F: TypeFolder<'tcx>>(self, _: &mut F) -> Result<Self, F::Error> {
+        Ok(self)
     }
 
     fn super_visit_with<V: TypeVisitor<'tcx>>(&self, _: &mut V) -> ControlFlow<V::BreakTy> {
@@ -150,8 +152,11 @@ fn super_visit_with<V: TypeVisitor<'tcx>>(&self, _: &mut V) -> ControlFlow<V::Br
 }
 
 impl<'tcx> TypeFoldable<'tcx> for Place<'tcx> {
-    fn super_fold_with<F: TypeFolder<'tcx>>(self, folder: &mut F) -> Self {
-        Place { local: self.local.fold_with(folder), projection: self.projection.fold_with(folder) }
+    fn super_fold_with<F: TypeFolder<'tcx>>(self, folder: &mut F) -> Result<Self, F::Error> {
+        Ok(Place {
+            local: self.local.fold_with(folder)?,
+            projection: self.projection.fold_with(folder)?,
+        })
     }
 
     fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> {
@@ -161,7 +166,7 @@ fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow
 }
 
 impl<'tcx> TypeFoldable<'tcx> for &'tcx ty::List<PlaceElem<'tcx>> {
-    fn super_fold_with<F: TypeFolder<'tcx>>(self, folder: &mut F) -> Self {
+    fn super_fold_with<F: TypeFolder<'tcx>>(self, folder: &mut F) -> Result<Self, F::Error> {
         ty::util::fold_list(self, folder, |tcx, v| tcx.intern_place_elems(v))
     }
 
@@ -171,47 +176,49 @@ fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow
 }
 
 impl<'tcx> TypeFoldable<'tcx> for Rvalue<'tcx> {
-    fn super_fold_with<F: TypeFolder<'tcx>>(self, folder: &mut F) -> Self {
+    fn super_fold_with<F: TypeFolder<'tcx>>(self, folder: &mut F) -> Result<Self, F::Error> {
         use crate::mir::Rvalue::*;
-        match self {
-            Use(op) => Use(op.fold_with(folder)),
-            Repeat(op, len) => Repeat(op.fold_with(folder), len.fold_with(folder)),
-            ThreadLocalRef(did) => ThreadLocalRef(did.fold_with(folder)),
-            Ref(region, bk, place) => Ref(region.fold_with(folder), bk, place.fold_with(folder)),
-            AddressOf(mutability, place) => AddressOf(mutability, place.fold_with(folder)),
-            Len(place) => Len(place.fold_with(folder)),
-            Cast(kind, op, ty) => Cast(kind, op.fold_with(folder), ty.fold_with(folder)),
+        Ok(match self {
+            Use(op) => Use(op.fold_with(folder)?),
+            Repeat(op, len) => Repeat(op.fold_with(folder)?, len.fold_with(folder)?),
+            ThreadLocalRef(did) => ThreadLocalRef(did.fold_with(folder)?),
+            Ref(region, bk, place) => Ref(region.fold_with(folder)?, bk, place.fold_with(folder)?),
+            AddressOf(mutability, place) => AddressOf(mutability, place.fold_with(folder)?),
+            Len(place) => Len(place.fold_with(folder)?),
+            Cast(kind, op, ty) => Cast(kind, op.fold_with(folder)?, ty.fold_with(folder)?),
             BinaryOp(op, box (rhs, lhs)) => {
-                BinaryOp(op, Box::new((rhs.fold_with(folder), lhs.fold_with(folder))))
+                BinaryOp(op, Box::new((rhs.fold_with(folder)?, lhs.fold_with(folder)?)))
             }
             CheckedBinaryOp(op, box (rhs, lhs)) => {
-                CheckedBinaryOp(op, Box::new((rhs.fold_with(folder), lhs.fold_with(folder))))
+                CheckedBinaryOp(op, Box::new((rhs.fold_with(folder)?, lhs.fold_with(folder)?)))
             }
-            UnaryOp(op, val) => UnaryOp(op, val.fold_with(folder)),
-            Discriminant(place) => Discriminant(place.fold_with(folder)),
-            NullaryOp(op, ty) => NullaryOp(op, ty.fold_with(folder)),
+            UnaryOp(op, val) => UnaryOp(op, val.fold_with(folder)?),
+            Discriminant(place) => Discriminant(place.fold_with(folder)?),
+            NullaryOp(op, ty) => NullaryOp(op, ty.fold_with(folder)?),
             Aggregate(kind, fields) => {
-                let kind = kind.map_id(|kind| match kind {
-                    AggregateKind::Array(ty) => AggregateKind::Array(ty.fold_with(folder)),
-                    AggregateKind::Tuple => AggregateKind::Tuple,
-                    AggregateKind::Adt(def, v, substs, user_ty, n) => AggregateKind::Adt(
-                        def,
-                        v,
-                        substs.fold_with(folder),
-                        user_ty.fold_with(folder),
-                        n,
-                    ),
-                    AggregateKind::Closure(id, substs) => {
-                        AggregateKind::Closure(id, substs.fold_with(folder))
-                    }
-                    AggregateKind::Generator(id, substs, movablity) => {
-                        AggregateKind::Generator(id, substs.fold_with(folder), movablity)
-                    }
-                });
-                Aggregate(kind, fields.fold_with(folder))
+                let kind = kind.try_map_id(|kind| {
+                    Ok(match kind {
+                        AggregateKind::Array(ty) => AggregateKind::Array(ty.fold_with(folder)?),
+                        AggregateKind::Tuple => AggregateKind::Tuple,
+                        AggregateKind::Adt(def, v, substs, user_ty, n) => AggregateKind::Adt(
+                            def,
+                            v,
+                            substs.fold_with(folder)?,
+                            user_ty.fold_with(folder)?,
+                            n,
+                        ),
+                        AggregateKind::Closure(id, substs) => {
+                            AggregateKind::Closure(id, substs.fold_with(folder)?)
+                        }
+                        AggregateKind::Generator(id, substs, movablity) => {
+                            AggregateKind::Generator(id, substs.fold_with(folder)?, movablity)
+                        }
+                    })
+                })?;
+                Aggregate(kind, fields.fold_with(folder)?)
             }
-            ShallowInitBox(op, ty) => ShallowInitBox(op.fold_with(folder), ty.fold_with(folder)),
-        }
+            ShallowInitBox(op, ty) => ShallowInitBox(op.fold_with(folder)?, ty.fold_with(folder)?),
+        })
     }
 
     fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> {
@@ -265,12 +272,12 @@ fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow
 }
 
 impl<'tcx> TypeFoldable<'tcx> for Operand<'tcx> {
-    fn super_fold_with<F: TypeFolder<'tcx>>(self, folder: &mut F) -> Self {
-        match self {
-            Operand::Copy(place) => Operand::Copy(place.fold_with(folder)),
-            Operand::Move(place) => Operand::Move(place.fold_with(folder)),
-            Operand::Constant(c) => Operand::Constant(c.fold_with(folder)),
-        }
+    fn super_fold_with<F: TypeFolder<'tcx>>(self, folder: &mut F) -> Result<Self, F::Error> {
+        Ok(match self {
+            Operand::Copy(place) => Operand::Copy(place.fold_with(folder)?),
+            Operand::Move(place) => Operand::Move(place.fold_with(folder)?),
+            Operand::Constant(c) => Operand::Constant(c.fold_with(folder)?),
+        })
     }
 
     fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> {
@@ -282,19 +289,19 @@ fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow
 }
 
 impl<'tcx> TypeFoldable<'tcx> for PlaceElem<'tcx> {
-    fn super_fold_with<F: TypeFolder<'tcx>>(self, folder: &mut F) -> Self {
+    fn super_fold_with<F: TypeFolder<'tcx>>(self, folder: &mut F) -> Result<Self, F::Error> {
         use crate::mir::ProjectionElem::*;
 
-        match self {
+        Ok(match self {
             Deref => Deref,
-            Field(f, ty) => Field(f, ty.fold_with(folder)),
-            Index(v) => Index(v.fold_with(folder)),
+            Field(f, ty) => Field(f, ty.fold_with(folder)?),
+            Index(v) => Index(v.fold_with(folder)?),
             Downcast(symbol, variantidx) => Downcast(symbol, variantidx),
             ConstantIndex { offset, min_length, from_end } => {
                 ConstantIndex { offset, min_length, from_end }
             }
             Subslice { from, to, from_end } => Subslice { from, to, from_end },
-        }
+        })
     }
 
     fn super_visit_with<Vs: TypeVisitor<'tcx>>(
@@ -312,8 +319,8 @@ fn super_visit_with<Vs: TypeVisitor<'tcx>>(
 }
 
 impl<'tcx> TypeFoldable<'tcx> for Field {
-    fn super_fold_with<F: TypeFolder<'tcx>>(self, _: &mut F) -> Self {
-        self
+    fn super_fold_with<F: TypeFolder<'tcx>>(self, _: &mut F) -> Result<Self, F::Error> {
+        Ok(self)
     }
     fn super_visit_with<V: TypeVisitor<'tcx>>(&self, _: &mut V) -> ControlFlow<V::BreakTy> {
         ControlFlow::CONTINUE
@@ -321,8 +328,8 @@ fn super_visit_with<V: TypeVisitor<'tcx>>(&self, _: &mut V) -> ControlFlow<V::Br
 }
 
 impl<'tcx> TypeFoldable<'tcx> for GeneratorSavedLocal {
-    fn super_fold_with<F: TypeFolder<'tcx>>(self, _: &mut F) -> Self {
-        self
+    fn super_fold_with<F: TypeFolder<'tcx>>(self, _: &mut F) -> Result<Self, F::Error> {
+        Ok(self)
     }
     fn super_visit_with<V: TypeVisitor<'tcx>>(&self, _: &mut V) -> ControlFlow<V::BreakTy> {
         ControlFlow::CONTINUE
@@ -330,8 +337,8 @@ fn super_visit_with<V: TypeVisitor<'tcx>>(&self, _: &mut V) -> ControlFlow<V::Br
 }
 
 impl<'tcx, R: Idx, C: Idx> TypeFoldable<'tcx> for BitMatrix<R, C> {
-    fn super_fold_with<F: TypeFolder<'tcx>>(self, _: &mut F) -> Self {
-        self
+    fn super_fold_with<F: TypeFolder<'tcx>>(self, _: &mut F) -> Result<Self, F::Error> {
+        Ok(self)
     }
     fn super_visit_with<V: TypeVisitor<'tcx>>(&self, _: &mut V) -> ControlFlow<V::BreakTy> {
         ControlFlow::CONTINUE
@@ -339,12 +346,12 @@ fn super_visit_with<V: TypeVisitor<'tcx>>(&self, _: &mut V) -> ControlFlow<V::Br
 }
 
 impl<'tcx> TypeFoldable<'tcx> for Constant<'tcx> {
-    fn super_fold_with<F: TypeFolder<'tcx>>(self, folder: &mut F) -> Self {
-        Constant {
+    fn super_fold_with<F: TypeFolder<'tcx>>(self, folder: &mut F) -> Result<Self, F::Error> {
+        Ok(Constant {
             span: self.span,
-            user_ty: self.user_ty.fold_with(folder),
-            literal: self.literal.fold_with(folder),
-        }
+            user_ty: self.user_ty.fold_with(folder)?,
+            literal: self.literal.fold_with(folder)?,
+        })
     }
     fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> {
         self.literal.visit_with(visitor)?;
@@ -354,14 +361,14 @@ fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow
 
 impl<'tcx> TypeFoldable<'tcx> for ConstantKind<'tcx> {
     #[inline(always)]
-    fn fold_with<F: TypeFolder<'tcx>>(self, folder: &mut F) -> Self {
+    fn fold_with<F: TypeFolder<'tcx>>(self, folder: &mut F) -> Result<Self, F::Error> {
         folder.fold_mir_const(self)
     }
 
-    fn super_fold_with<F: TypeFolder<'tcx>>(self, folder: &mut F) -> Self {
+    fn super_fold_with<F: TypeFolder<'tcx>>(self, folder: &mut F) -> Result<Self, F::Error> {
         match self {
-            ConstantKind::Ty(c) => ConstantKind::Ty(c.fold_with(folder)),
-            ConstantKind::Val(v, t) => ConstantKind::Val(v, t.fold_with(folder)),
+            ConstantKind::Ty(c) => Ok(ConstantKind::Ty(c.fold_with(folder)?)),
+            ConstantKind::Val(v, t) => Ok(ConstantKind::Val(v, t.fold_with(folder)?)),
         }
     }
 
index fda7ebe1a49c15c2697ae150b964124af43a019e..4c23ab49fa29f71efd91a9e12c482d41bf0ada32 100644 (file)
@@ -1004,8 +1004,12 @@ fn process_projection_elem(
 
                     if new_local == local { None } else { Some(PlaceElem::Index(new_local)) }
                 }
+                PlaceElem::Field(field, ty) => {
+                    let mut new_ty = ty;
+                    self.visit_ty(&mut new_ty, TyContext::Location(location));
+                    if ty != new_ty { Some(PlaceElem::Field(field, new_ty)) } else { None }
+                }
                 PlaceElem::Deref
-                | PlaceElem::Field(..)
                 | PlaceElem::ConstantIndex { .. }
                 | PlaceElem::Subslice { .. }
                 | PlaceElem::Downcast(..) => None,
index ca93efbf19b7b14a472bae608aa8cd70d163860c..8667a6bea11f664eae6186f0ebb5fc4ca923d84a 100644 (file)
         desc { |tcx| "computing crate imported by `{}`", tcx.def_path_str(def_id.to_def_id()) }
     }
 
-    query get_lib_features(_: ()) -> LibFeatures {
+    query lib_features(_: ()) -> LibFeatures {
         storage(ArenaCacheSelector<'tcx>)
-        eval_always
         desc { "calculating the lib features map" }
     }
     query defined_lib_features(_: CrateNum)
         desc { "normalizing `{:?}`", goal }
     }
 
+    // FIXME: Implement `normalize_generic_arg_after_erasing_regions` and
+    // `normalize_mir_const_after_erasing_regions` in terms of
+    // `try_normalize_generic_arg_after_erasing_regions` and
+    // `try_normalize_mir_const_after_erasing_regions`, respectively.
+
     /// Do not call this query directly: invoke `normalize_erasing_regions` instead.
     query normalize_generic_arg_after_erasing_regions(
         goal: ParamEnvAnd<'tcx, GenericArg<'tcx>>
         desc { "normalizing `{}`", goal.value }
     }
 
+    /// Do not call this query directly: invoke `try_normalize_erasing_regions` instead.
+    query try_normalize_generic_arg_after_erasing_regions(
+        goal: ParamEnvAnd<'tcx, GenericArg<'tcx>>
+    ) -> Result<GenericArg<'tcx>, NoSolution> {
+        desc { "normalizing `{}`", goal.value }
+    }
+
+    /// Do not call this query directly: invoke `try_normalize_erasing_regions` instead.
+    query try_normalize_mir_const_after_erasing_regions(
+        goal: ParamEnvAnd<'tcx, mir::ConstantKind<'tcx>>
+    ) -> Result<mir::ConstantKind<'tcx>, NoSolution> {
+        desc { "normalizing `{}`", goal.value }
+    }
+
     query implied_outlives_bounds(
         goal: CanonicalTyGoal<'tcx>
     ) -> Result<
index 8240273acad4cd89eb1bcabfff4defc8dbf00cf7..822458d312778d609d4e70f14a3eeadc27ea73e1 100644 (file)
@@ -5,7 +5,6 @@
 use crate::hir::place::Place as HirPlace;
 use crate::infer::canonical::{Canonical, CanonicalVarInfo, CanonicalVarInfos};
 use crate::lint::{struct_lint_level, LintDiagnosticBuilder, LintLevelSource};
-use crate::middle;
 use crate::middle::resolve_lifetime::{self, LifetimeScopeForPath, ObjectLifetimeDefault};
 use crate::middle::stability;
 use crate::mir::interpret::{self, Allocation, ConstValue, Scalar};
@@ -1217,10 +1216,6 @@ pub fn consider_optimizing<T: Fn() -> String>(self, msg: T) -> bool {
         self.sess.consider_optimizing(&cname, msg)
     }
 
-    pub fn lib_features(self) -> &'tcx middle::lib_features::LibFeatures {
-        self.get_lib_features(())
-    }
-
     /// Obtain all lang items of this crate and all dependencies (recursively)
     pub fn lang_items(self) -> &'tcx rustc_hir::lang_items::LanguageItems {
         self.get_lang_items(())
index 63eb55ed1a6208121d0e479810ae80209b0bce03..25b460cf16d3c7f5cfddbb7775fc1e566a306ed0 100644 (file)
@@ -9,7 +9,7 @@ pub(super) fn provide(providers: &mut ty::query::Providers) {
 fn erase_regions_ty<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> Ty<'tcx> {
     // N.B., use `super_fold_with` here. If we used `fold_with`, it
     // could invoke the `erase_regions_ty` query recursively.
-    ty.super_fold_with(&mut RegionEraserVisitor { tcx })
+    ty.super_fold_with(&mut RegionEraserVisitor { tcx }).into_ok()
 }
 
 impl<'tcx> TyCtxt<'tcx> {
@@ -27,7 +27,7 @@ pub fn erase_regions<T>(self, value: T) -> T
             return value;
         }
         debug!("erase_regions({:?})", value);
-        let value1 = value.fold_with(&mut RegionEraserVisitor { tcx: self });
+        let value1 = value.fold_with(&mut RegionEraserVisitor { tcx: self }).into_ok();
         debug!("erase_regions = {:?}", value1);
         value1
     }
@@ -42,11 +42,11 @@ fn tcx<'b>(&'b self) -> TyCtxt<'tcx> {
         self.tcx
     }
 
-    fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> {
-        if ty.needs_infer() { ty.super_fold_with(self) } else { self.tcx.erase_regions_ty(ty) }
+    fn fold_ty(&mut self, ty: Ty<'tcx>) -> Result<Ty<'tcx>, Self::Error> {
+        if ty.needs_infer() { ty.super_fold_with(self) } else { Ok(self.tcx.erase_regions_ty(ty)) }
     }
 
-    fn fold_binder<T>(&mut self, t: ty::Binder<'tcx, T>) -> ty::Binder<'tcx, T>
+    fn fold_binder<T>(&mut self, t: ty::Binder<'tcx, T>) -> Result<ty::Binder<'tcx, T>, Self::Error>
     where
         T: TypeFoldable<'tcx>,
     {
@@ -54,7 +54,7 @@ fn fold_binder<T>(&mut self, t: ty::Binder<'tcx, T>) -> ty::Binder<'tcx, T>
         u.super_fold_with(self)
     }
 
-    fn fold_region(&mut self, r: ty::Region<'tcx>) -> ty::Region<'tcx> {
+    fn fold_region(&mut self, r: ty::Region<'tcx>) -> Result<ty::Region<'tcx>, Self::Error> {
         // because late-bound regions affect subtyping, we can't
         // erase the bound/free distinction, but we can replace
         // all free regions with 'erased.
@@ -64,12 +64,15 @@ fn fold_region(&mut self, r: ty::Region<'tcx>) -> ty::Region<'tcx> {
         // away. In codegen, they will always be erased to 'erased
         // whenever a substitution occurs.
         match *r {
-            ty::ReLateBound(..) => r,
-            _ => self.tcx.lifetimes.re_erased,
+            ty::ReLateBound(..) => Ok(r),
+            _ => Ok(self.tcx.lifetimes.re_erased),
         }
     }
 
-    fn fold_mir_const(&mut self, c: mir::ConstantKind<'tcx>) -> mir::ConstantKind<'tcx> {
+    fn fold_mir_const(
+        &mut self,
+        c: mir::ConstantKind<'tcx>,
+    ) -> Result<mir::ConstantKind<'tcx>, Self::Error> {
         c.super_fold_with(self)
     }
 }
index b14a69892657bcb7bce9c32efc9c9314f5df4b73..bda40a9abb097929f2ad485099873fad97b318e4 100644 (file)
@@ -777,9 +777,7 @@ fn suggest_constraining_opaque_associated_type(
         if let ty::Opaque(def_id, _) = *proj_ty.self_ty().kind() {
             let opaque_local_def_id = def_id.as_local();
             let opaque_hir_ty = if let Some(opaque_local_def_id) = opaque_local_def_id {
-                let hir = self.hir();
-                let opaque_hir_id = hir.local_def_id_to_hir_id(opaque_local_def_id);
-                match &hir.expect_item(opaque_hir_id).kind {
+                match &self.hir().expect_item(opaque_local_def_id).kind {
                     hir::ItemKind::OpaqueTy(opaque_hir_ty) => opaque_hir_ty,
                     _ => bug!("The HirId comes from a `ty::Opaque`"),
                 }
index e16491dcc90b25eeb62ff3858833d11fbfb406f2..31055c03a5d36c73e551ddbf76377ef6699f081d 100644 (file)
@@ -46,8 +46,8 @@
 ///
 /// To implement this conveniently, use the derive macro located in `rustc_macros`.
 pub trait TypeFoldable<'tcx>: fmt::Debug + Clone {
-    fn super_fold_with<F: TypeFolder<'tcx>>(self, folder: &mut F) -> Self;
-    fn fold_with<F: TypeFolder<'tcx>>(self, folder: &mut F) -> Self {
+    fn super_fold_with<F: TypeFolder<'tcx>>(self, folder: &mut F) -> Result<Self, F::Error>;
+    fn fold_with<F: TypeFolder<'tcx>>(self, folder: &mut F) -> Result<Self, F::Error> {
         self.super_fold_with(folder)
     }
 
@@ -179,8 +179,8 @@ fn still_further_specializable(&self) -> bool {
 }
 
 impl TypeFoldable<'tcx> for hir::Constness {
-    fn super_fold_with<F: TypeFolder<'tcx>>(self, _: &mut F) -> Self {
-        self
+    fn super_fold_with<F: TypeFolder<'tcx>>(self, _: &mut F) -> Result<Self, F::Error> {
+        Ok(self)
     }
     fn super_visit_with<V: TypeVisitor<'tcx>>(&self, _: &mut V) -> ControlFlow<V::BreakTy> {
         ControlFlow::CONTINUE
@@ -193,32 +193,43 @@ fn super_visit_with<V: TypeVisitor<'tcx>>(&self, _: &mut V) -> ControlFlow<V::Br
 /// identity fold, it should invoke `foo.fold_with(self)` to fold each
 /// sub-item.
 pub trait TypeFolder<'tcx>: Sized {
+    type Error = !;
+
     fn tcx<'a>(&'a self) -> TyCtxt<'tcx>;
 
-    fn fold_binder<T>(&mut self, t: Binder<'tcx, T>) -> Binder<'tcx, T>
+    fn fold_binder<T>(&mut self, t: Binder<'tcx, T>) -> Result<Binder<'tcx, T>, Self::Error>
     where
         T: TypeFoldable<'tcx>,
     {
         t.super_fold_with(self)
     }
 
-    fn fold_ty(&mut self, t: Ty<'tcx>) -> Ty<'tcx> {
+    fn fold_ty(&mut self, t: Ty<'tcx>) -> Result<Ty<'tcx>, Self::Error> {
         t.super_fold_with(self)
     }
 
-    fn fold_region(&mut self, r: ty::Region<'tcx>) -> ty::Region<'tcx> {
+    fn fold_region(&mut self, r: ty::Region<'tcx>) -> Result<ty::Region<'tcx>, Self::Error> {
         r.super_fold_with(self)
     }
 
-    fn fold_const(&mut self, c: &'tcx ty::Const<'tcx>) -> &'tcx ty::Const<'tcx> {
+    fn fold_const(
+        &mut self,
+        c: &'tcx ty::Const<'tcx>,
+    ) -> Result<&'tcx ty::Const<'tcx>, Self::Error> {
         c.super_fold_with(self)
     }
 
-    fn fold_predicate(&mut self, p: ty::Predicate<'tcx>) -> ty::Predicate<'tcx> {
+    fn fold_predicate(
+        &mut self,
+        p: ty::Predicate<'tcx>,
+    ) -> Result<ty::Predicate<'tcx>, Self::Error> {
         p.super_fold_with(self)
     }
 
-    fn fold_mir_const(&mut self, c: mir::ConstantKind<'tcx>) -> mir::ConstantKind<'tcx> {
+    fn fold_mir_const(
+        &mut self,
+        c: mir::ConstantKind<'tcx>,
+    ) -> Result<mir::ConstantKind<'tcx>, Self::Error> {
         bug!("most type folders should not be folding MIR datastructures: {:?}", c)
     }
 }
@@ -290,19 +301,22 @@ fn tcx<'b>(&'b self) -> TyCtxt<'tcx> {
         self.tcx
     }
 
-    fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> {
-        let t = ty.super_fold_with(self);
-        (self.ty_op)(t)
+    fn fold_ty(&mut self, ty: Ty<'tcx>) -> Result<Ty<'tcx>, Self::Error> {
+        let t = ty.super_fold_with(self)?;
+        Ok((self.ty_op)(t))
     }
 
-    fn fold_region(&mut self, r: ty::Region<'tcx>) -> ty::Region<'tcx> {
-        let r = r.super_fold_with(self);
-        (self.lt_op)(r)
+    fn fold_region(&mut self, r: ty::Region<'tcx>) -> Result<ty::Region<'tcx>, Self::Error> {
+        let r = r.super_fold_with(self)?;
+        Ok((self.lt_op)(r))
     }
 
-    fn fold_const(&mut self, ct: &'tcx ty::Const<'tcx>) -> &'tcx ty::Const<'tcx> {
-        let ct = ct.super_fold_with(self);
-        (self.ct_op)(ct)
+    fn fold_const(
+        &mut self,
+        ct: &'tcx ty::Const<'tcx>,
+    ) -> Result<&'tcx ty::Const<'tcx>, Self::Error> {
+        let ct = ct.super_fold_with(self)?;
+        Ok((self.ct_op)(ct))
     }
 }
 
@@ -322,7 +336,7 @@ pub fn fold_regions<T>(
     where
         T: TypeFoldable<'tcx>,
     {
-        value.fold_with(&mut RegionFolder::new(self, skipped_regions, &mut f))
+        value.fold_with(&mut RegionFolder::new(self, skipped_regions, &mut f)).into_ok()
     }
 
     /// Invoke `callback` on every region appearing free in `value`.
@@ -470,7 +484,7 @@ fn tcx<'b>(&'b self) -> TyCtxt<'tcx> {
     fn fold_binder<T: TypeFoldable<'tcx>>(
         &mut self,
         t: ty::Binder<'tcx, T>,
-    ) -> ty::Binder<'tcx, T> {
+    ) -> Result<ty::Binder<'tcx, T>, Self::Error> {
         self.current_index.shift_in(1);
         let t = t.super_fold_with(self);
         self.current_index.shift_out(1);
@@ -478,16 +492,16 @@ fn fold_binder<T: TypeFoldable<'tcx>>(
     }
 
     #[instrument(skip(self), level = "debug")]
-    fn fold_region(&mut self, r: ty::Region<'tcx>) -> ty::Region<'tcx> {
+    fn fold_region(&mut self, r: ty::Region<'tcx>) -> Result<ty::Region<'tcx>, Self::Error> {
         match *r {
             ty::ReLateBound(debruijn, _) if debruijn < self.current_index => {
                 debug!(?self.current_index, "skipped bound region");
                 *self.skipped_regions = true;
-                r
+                Ok(r)
             }
             _ => {
                 debug!(?self.current_index, "folding free region");
-                (self.fold_region_fn)(r, self.current_index)
+                Ok((self.fold_region_fn)(r, self.current_index))
             }
         }
     }
@@ -528,19 +542,19 @@ fn tcx<'b>(&'b self) -> TyCtxt<'tcx> {
     fn fold_binder<T: TypeFoldable<'tcx>>(
         &mut self,
         t: ty::Binder<'tcx, T>,
-    ) -> ty::Binder<'tcx, T> {
+    ) -> Result<ty::Binder<'tcx, T>, Self::Error> {
         self.current_index.shift_in(1);
         let t = t.super_fold_with(self);
         self.current_index.shift_out(1);
         t
     }
 
-    fn fold_ty(&mut self, t: Ty<'tcx>) -> Ty<'tcx> {
+    fn fold_ty(&mut self, t: Ty<'tcx>) -> Result<Ty<'tcx>, Self::Error> {
         match *t.kind() {
             ty::Bound(debruijn, bound_ty) if debruijn == self.current_index => {
                 if let Some(fld_t) = self.fld_t.as_mut() {
                     let ty = fld_t(bound_ty);
-                    return ty::fold::shift_vars(self.tcx, &ty, self.current_index.as_u32());
+                    return Ok(ty::fold::shift_vars(self.tcx, &ty, self.current_index.as_u32()));
                 }
             }
             _ if t.has_vars_bound_at_or_above(self.current_index) => {
@@ -548,10 +562,10 @@ fn fold_ty(&mut self, t: Ty<'tcx>) -> Ty<'tcx> {
             }
             _ => {}
         }
-        t
+        Ok(t)
     }
 
-    fn fold_region(&mut self, r: ty::Region<'tcx>) -> ty::Region<'tcx> {
+    fn fold_region(&mut self, r: ty::Region<'tcx>) -> Result<ty::Region<'tcx>, Self::Error> {
         match *r {
             ty::ReLateBound(debruijn, br) if debruijn == self.current_index => {
                 if let Some(fld_r) = self.fld_r.as_mut() {
@@ -562,25 +576,28 @@ fn fold_region(&mut self, r: ty::Region<'tcx>) -> ty::Region<'tcx> {
                         // debruijn index. Then we adjust it to the
                         // correct depth.
                         assert_eq!(debruijn1, ty::INNERMOST);
-                        self.tcx.mk_region(ty::ReLateBound(debruijn, br))
+                        Ok(self.tcx.mk_region(ty::ReLateBound(debruijn, br)))
                     } else {
-                        region
+                        Ok(region)
                     };
                 }
             }
             _ => {}
         }
-        r
+        Ok(r)
     }
 
-    fn fold_const(&mut self, ct: &'tcx ty::Const<'tcx>) -> &'tcx ty::Const<'tcx> {
+    fn fold_const(
+        &mut self,
+        ct: &'tcx ty::Const<'tcx>,
+    ) -> Result<&'tcx ty::Const<'tcx>, Self::Error> {
         match *ct {
             ty::Const { val: ty::ConstKind::Bound(debruijn, bound_const), ty }
                 if debruijn == self.current_index =>
             {
                 if let Some(fld_c) = self.fld_c.as_mut() {
                     let ct = fld_c(bound_const, ty);
-                    return ty::fold::shift_vars(self.tcx, &ct, self.current_index.as_u32());
+                    return Ok(ty::fold::shift_vars(self.tcx, &ct, self.current_index.as_u32()));
                 }
             }
             _ if ct.has_vars_bound_at_or_above(self.current_index) => {
@@ -588,7 +605,7 @@ fn fold_const(&mut self, ct: &'tcx ty::Const<'tcx>) -> &'tcx ty::Const<'tcx> {
             }
             _ => {}
         }
-        ct
+        Ok(ct)
     }
 }
 
@@ -621,7 +638,7 @@ pub fn replace_late_bound_regions<T, F>(
             value
         } else {
             let mut replacer = BoundVarReplacer::new(self, Some(&mut real_fld_r), None, None);
-            value.fold_with(&mut replacer)
+            value.fold_with(&mut replacer).into_ok()
         };
         (value, region_map)
     }
@@ -647,7 +664,7 @@ pub fn replace_escaping_bound_vars<T, F, G, H>(
         } else {
             let mut replacer =
                 BoundVarReplacer::new(self, Some(&mut fld_r), Some(&mut fld_t), Some(&mut fld_c));
-            value.fold_with(&mut replacer)
+            value.fold_with(&mut replacer).into_ok()
         }
     }
 
@@ -938,36 +955,36 @@ fn tcx<'b>(&'b self) -> TyCtxt<'tcx> {
     fn fold_binder<T: TypeFoldable<'tcx>>(
         &mut self,
         t: ty::Binder<'tcx, T>,
-    ) -> ty::Binder<'tcx, T> {
+    ) -> Result<ty::Binder<'tcx, T>, Self::Error> {
         self.current_index.shift_in(1);
         let t = t.super_fold_with(self);
         self.current_index.shift_out(1);
         t
     }
 
-    fn fold_region(&mut self, r: ty::Region<'tcx>) -> ty::Region<'tcx> {
+    fn fold_region(&mut self, r: ty::Region<'tcx>) -> Result<ty::Region<'tcx>, Self::Error> {
         match *r {
             ty::ReLateBound(debruijn, br) => {
                 if self.amount == 0 || debruijn < self.current_index {
-                    r
+                    Ok(r)
                 } else {
                     let debruijn = debruijn.shifted_in(self.amount);
                     let shifted = ty::ReLateBound(debruijn, br);
-                    self.tcx.mk_region(shifted)
+                    Ok(self.tcx.mk_region(shifted))
                 }
             }
-            _ => r,
+            _ => Ok(r),
         }
     }
 
-    fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> {
+    fn fold_ty(&mut self, ty: Ty<'tcx>) -> Result<Ty<'tcx>, Self::Error> {
         match *ty.kind() {
             ty::Bound(debruijn, bound_ty) => {
                 if self.amount == 0 || debruijn < self.current_index {
-                    ty
+                    Ok(ty)
                 } else {
                     let debruijn = debruijn.shifted_in(self.amount);
-                    self.tcx.mk_ty(ty::Bound(debruijn, bound_ty))
+                    Ok(self.tcx.mk_ty(ty::Bound(debruijn, bound_ty)))
                 }
             }
 
@@ -975,13 +992,18 @@ fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> {
         }
     }
 
-    fn fold_const(&mut self, ct: &'tcx ty::Const<'tcx>) -> &'tcx ty::Const<'tcx> {
+    fn fold_const(
+        &mut self,
+        ct: &'tcx ty::Const<'tcx>,
+    ) -> Result<&'tcx ty::Const<'tcx>, Self::Error> {
         if let ty::Const { val: ty::ConstKind::Bound(debruijn, bound_ct), ty } = *ct {
             if self.amount == 0 || debruijn < self.current_index {
-                ct
+                Ok(ct)
             } else {
                 let debruijn = debruijn.shifted_in(self.amount);
-                self.tcx.mk_const(ty::Const { val: ty::ConstKind::Bound(debruijn, bound_ct), ty })
+                Ok(self
+                    .tcx
+                    .mk_const(ty::Const { val: ty::ConstKind::Bound(debruijn, bound_ct), ty }))
             }
         } else {
             ct.super_fold_with(self)
@@ -1008,7 +1030,7 @@ pub fn shift_vars<'tcx, T>(tcx: TyCtxt<'tcx>, value: T, amount: u32) -> T
 {
     debug!("shift_vars(value={:?}, amount={})", value, amount);
 
-    value.fold_with(&mut Shifter::new(tcx, amount))
+    value.fold_with(&mut Shifter::new(tcx, amount)).into_ok()
 }
 
 #[derive(Debug, PartialEq, Eq, Copy, Clone)]
@@ -1271,7 +1293,7 @@ impl<'tcx> TyCtxt<'tcx> {
     ///
     /// FIXME(@lcnr): explain this function a bit more
     pub fn expose_default_const_substs<T: TypeFoldable<'tcx>>(self, v: T) -> T {
-        v.fold_with(&mut ExposeDefaultConstSubstsFolder { tcx: self })
+        v.fold_with(&mut ExposeDefaultConstSubstsFolder { tcx: self }).into_ok()
     }
 }
 
@@ -1284,19 +1306,22 @@ fn tcx(&self) -> TyCtxt<'tcx> {
         self.tcx
     }
 
-    fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> {
+    fn fold_ty(&mut self, ty: Ty<'tcx>) -> Result<Ty<'tcx>, Self::Error> {
         if ty.flags().intersects(TypeFlags::HAS_UNKNOWN_DEFAULT_CONST_SUBSTS) {
             ty.super_fold_with(self)
         } else {
-            ty
+            Ok(ty)
         }
     }
 
-    fn fold_predicate(&mut self, pred: ty::Predicate<'tcx>) -> ty::Predicate<'tcx> {
+    fn fold_predicate(
+        &mut self,
+        pred: ty::Predicate<'tcx>,
+    ) -> Result<ty::Predicate<'tcx>, Self::Error> {
         if pred.inner.flags.intersects(TypeFlags::HAS_UNKNOWN_DEFAULT_CONST_SUBSTS) {
             pred.super_fold_with(self)
         } else {
-            pred
+            Ok(pred)
         }
     }
 }
index 4b38105e44717e52300e5b6f9e789e58f8093d12..15931b8d2c86a85d0129437e207e9255cf26b0e9 100644 (file)
@@ -622,7 +622,7 @@ fn tcx<'a>(&'a self) -> TyCtxt<'tcx> {
             self.tcx
         }
 
-        fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> {
+        fn fold_ty(&mut self, ty: Ty<'tcx>) -> Result<Ty<'tcx>, Self::Error> {
             debug!("fold_ty: ty={:?}", ty);
             match ty.kind {
                 ty::Closure(def_id, substs) => {
@@ -631,11 +631,11 @@ fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> {
                         ty::InstanceDef::Item(ty::WithOptConstParam::unknown(def_id)),
                         substs,
                     );
-                    if substs == polymorphized_substs {
+                    Ok(if substs == polymorphized_substs {
                         ty
                     } else {
                         self.tcx.mk_closure(def_id, polymorphized_substs)
-                    }
+                    })
                 }
                 ty::Generator(def_id, substs, movability) => {
                     let polymorphized_substs = polymorphize(
@@ -643,11 +643,11 @@ fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> {
                         ty::InstanceDef::Item(ty::WithOptConstParam::unknown(def_id)),
                         substs,
                     );
-                    if substs == polymorphized_substs {
+                    Ok(if substs == polymorphized_substs {
                         ty
                     } else {
                         self.tcx.mk_generator(def_id, polymorphized_substs, movability)
-                    }
+                    })
                 }
                 _ => ty.super_fold_with(self),
             }
@@ -669,7 +669,7 @@ fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> {
                     // ..and polymorphize any closures/generators captured as upvars.
                     let upvars_ty = upvars_ty.unwrap();
                     let polymorphized_upvars_ty = upvars_ty.fold_with(
-                        &mut PolymorphizationFolder { tcx });
+                        &mut PolymorphizationFolder { tcx }).into_ok();
                     debug!("polymorphize: polymorphized_upvars_ty={:?}", polymorphized_upvars_ty);
                     ty::GenericArg::from(polymorphized_upvars_ty)
                 },
index b87e23af72b702076ea2ea84f8d5b48bf87b6f43..57506bc68345b7c688f02c93daa8c28530085b0b 100644 (file)
@@ -1,5 +1,6 @@
 use crate::middle::codegen_fn_attrs::CodegenFnAttrFlags;
 use crate::mir::{GeneratorLayout, GeneratorSavedLocal};
+use crate::ty::normalize_erasing_regions::NormalizationError;
 use crate::ty::subst::Subst;
 use crate::ty::{self, subst::SubstsRef, ReprOptions, Ty, TyCtxt, TypeFoldable};
 use rustc_ast as ast;
@@ -199,6 +200,7 @@ fn to_int_ty(&self, tcx: TyCtxt<'tcx>) -> Ty<'tcx> {
 pub enum LayoutError<'tcx> {
     Unknown(Ty<'tcx>),
     SizeOverflow(Ty<'tcx>),
+    NormalizationFailure(Ty<'tcx>, NormalizationError<'tcx>),
 }
 
 impl<'tcx> fmt::Display for LayoutError<'tcx> {
@@ -208,16 +210,24 @@ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
             LayoutError::SizeOverflow(ty) => {
                 write!(f, "values of the type `{}` are too big for the current architecture", ty)
             }
+            LayoutError::NormalizationFailure(t, e) => write!(
+                f,
+                "unable to determine layout for `{}` because `{}` cannot be normalized",
+                t,
+                e.get_type_for_failure()
+            ),
         }
     }
 }
 
+#[instrument(skip(tcx, query), level = "debug")]
 fn layout_of<'tcx>(
     tcx: TyCtxt<'tcx>,
     query: ty::ParamEnvAnd<'tcx, Ty<'tcx>>,
 ) -> Result<TyAndLayout<'tcx>, LayoutError<'tcx>> {
     ty::tls::with_related_context(tcx, move |icx| {
         let (param_env, ty) = query.into_parts();
+        debug!(?ty);
 
         if !tcx.recursion_limit().value_within_limit(icx.layout_depth) {
             tcx.sess.fatal(&format!("overflow representing the type `{}`", ty));
@@ -229,7 +239,18 @@ fn layout_of<'tcx>(
         ty::tls::enter_context(&icx, |_| {
             let param_env = param_env.with_reveal_all_normalized(tcx);
             let unnormalized_ty = ty;
-            let ty = tcx.normalize_erasing_regions(param_env, ty);
+
+            // FIXME: We might want to have two different versions of `layout_of`:
+            // One that can be called after typecheck has completed and can use
+            // `normalize_erasing_regions` here and another one that can be called
+            // before typecheck has completed and uses `try_normalize_erasing_regions`.
+            let ty = match tcx.try_normalize_erasing_regions(param_env, ty) {
+                Ok(t) => t,
+                Err(normalization_error) => {
+                    return Err(LayoutError::NormalizationFailure(ty, normalization_error));
+                }
+            };
+
             if ty != unnormalized_ty {
                 // Ensure this layout is also cached for the normalized type.
                 return tcx.layout_of(param_env.and(ty));
index 673733faa766ff5846c02075833be4fba79c0cf7..2d6926703726c63e146b1d93f3555cdbe35ffd55 100644 (file)
@@ -1260,8 +1260,11 @@ fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHas
 }
 
 impl<'tcx> TypeFoldable<'tcx> for ParamEnv<'tcx> {
-    fn super_fold_with<F: ty::fold::TypeFolder<'tcx>>(self, folder: &mut F) -> Self {
-        ParamEnv::new(self.caller_bounds().fold_with(folder), self.reveal().fold_with(folder))
+    fn super_fold_with<F: ty::fold::TypeFolder<'tcx>>(
+        self,
+        folder: &mut F,
+    ) -> Result<Self, F::Error> {
+        Ok(ParamEnv::new(self.caller_bounds().fold_with(folder)?, self.reveal().fold_with(folder)?))
     }
 
     fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> {
index 11399506b96e427373baa68ef7b1b9c53598f240..fce7cbfbb3d1e58f3e8d6e254eb64b1287cc3d58 100644 (file)
@@ -8,10 +8,28 @@
 //! or constant found within. (This underlying query is what is cached.)
 
 use crate::mir;
+use crate::traits::query::NoSolution;
 use crate::ty::fold::{TypeFoldable, TypeFolder};
 use crate::ty::subst::{Subst, SubstsRef};
 use crate::ty::{self, Ty, TyCtxt};
 
+#[derive(Debug, Copy, Clone, HashStable, TyEncodable, TyDecodable)]
+pub enum NormalizationError<'tcx> {
+    Type(Ty<'tcx>),
+    Const(ty::Const<'tcx>),
+    ConstantKind(mir::ConstantKind<'tcx>),
+}
+
+impl<'tcx> NormalizationError<'tcx> {
+    pub fn get_type_for_failure(&self) -> String {
+        match self {
+            NormalizationError::Type(t) => format!("{}", t),
+            NormalizationError::Const(c) => format!("{}", c),
+            NormalizationError::ConstantKind(ck) => format!("{}", ck),
+        }
+    }
+}
+
 impl<'tcx> TyCtxt<'tcx> {
     /// Erase the regions in `value` and then fully normalize all the
     /// types found within. The result will also have regions erased.
@@ -32,10 +50,47 @@ pub fn normalize_erasing_regions<T>(self, param_env: ty::ParamEnv<'tcx>, value:
         // Erase first before we do the real query -- this keeps the
         // cache from being too polluted.
         let value = self.erase_regions(value);
+        debug!(?value);
+
         if !value.has_projections() {
             value
         } else {
-            value.fold_with(&mut NormalizeAfterErasingRegionsFolder { tcx: self, param_env })
+            value
+                .fold_with(&mut NormalizeAfterErasingRegionsFolder { tcx: self, param_env })
+                .into_ok()
+        }
+    }
+
+    /// Tries to erase the regions in `value` and then fully normalize all the
+    /// types found within. The result will also have regions erased.
+    ///
+    /// Contrary to `normalize_erasing_regions` this function does not assume that normalization
+    /// succeeds.
+    pub fn try_normalize_erasing_regions<T>(
+        self,
+        param_env: ty::ParamEnv<'tcx>,
+        value: T,
+    ) -> Result<T, NormalizationError<'tcx>>
+    where
+        T: TypeFoldable<'tcx>,
+    {
+        debug!(
+            "try_normalize_erasing_regions::<{}>(value={:?}, param_env={:?})",
+            std::any::type_name::<T>(),
+            value,
+            param_env,
+        );
+
+        // Erase first before we do the real query -- this keeps the
+        // cache from being too polluted.
+        let value = self.erase_regions(value);
+        debug!(?value);
+
+        if !value.has_projections() {
+            Ok(value)
+        } else {
+            let mut folder = TryNormalizeAfterErasingRegionsFolder::new(self, param_env);
+            value.fold_with(&mut folder)
         }
     }
 
@@ -89,11 +144,14 @@ struct NormalizeAfterErasingRegionsFolder<'tcx> {
 }
 
 impl<'tcx> NormalizeAfterErasingRegionsFolder<'tcx> {
+    #[instrument(skip(self), level = "debug")]
     fn normalize_generic_arg_after_erasing_regions(
         &self,
         arg: ty::GenericArg<'tcx>,
     ) -> ty::GenericArg<'tcx> {
         let arg = self.param_env.and(arg);
+        debug!(?arg);
+
         self.tcx.normalize_generic_arg_after_erasing_regions(arg)
     }
 }
@@ -103,18 +161,83 @@ fn tcx(&self) -> TyCtxt<'tcx> {
         self.tcx
     }
 
-    fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> {
-        self.normalize_generic_arg_after_erasing_regions(ty.into()).expect_ty()
+    fn fold_ty(&mut self, ty: Ty<'tcx>) -> Result<Ty<'tcx>, Self::Error> {
+        Ok(self.normalize_generic_arg_after_erasing_regions(ty.into()).expect_ty())
     }
 
-    fn fold_const(&mut self, c: &'tcx ty::Const<'tcx>) -> &'tcx ty::Const<'tcx> {
-        self.normalize_generic_arg_after_erasing_regions(c.into()).expect_const()
+    fn fold_const(
+        &mut self,
+        c: &'tcx ty::Const<'tcx>,
+    ) -> Result<&'tcx ty::Const<'tcx>, Self::Error> {
+        Ok(self.normalize_generic_arg_after_erasing_regions(c.into()).expect_const())
     }
 
     #[inline]
-    fn fold_mir_const(&mut self, c: mir::ConstantKind<'tcx>) -> mir::ConstantKind<'tcx> {
+    fn fold_mir_const(
+        &mut self,
+        c: mir::ConstantKind<'tcx>,
+    ) -> Result<mir::ConstantKind<'tcx>, Self::Error> {
         // FIXME: This *probably* needs canonicalization too!
         let arg = self.param_env.and(c);
-        self.tcx.normalize_mir_const_after_erasing_regions(arg)
+        Ok(self.tcx.normalize_mir_const_after_erasing_regions(arg))
+    }
+}
+
+struct TryNormalizeAfterErasingRegionsFolder<'tcx> {
+    tcx: TyCtxt<'tcx>,
+    param_env: ty::ParamEnv<'tcx>,
+}
+
+impl<'tcx> TryNormalizeAfterErasingRegionsFolder<'tcx> {
+    fn new(tcx: TyCtxt<'tcx>, param_env: ty::ParamEnv<'tcx>) -> Self {
+        TryNormalizeAfterErasingRegionsFolder { tcx, param_env }
+    }
+
+    #[instrument(skip(self), level = "debug")]
+    fn try_normalize_generic_arg_after_erasing_regions(
+        &self,
+        arg: ty::GenericArg<'tcx>,
+    ) -> Result<ty::GenericArg<'tcx>, NoSolution> {
+        let arg = self.param_env.and(arg);
+        debug!(?arg);
+
+        self.tcx.try_normalize_generic_arg_after_erasing_regions(arg)
+    }
+}
+
+impl TypeFolder<'tcx> for TryNormalizeAfterErasingRegionsFolder<'tcx> {
+    type Error = NormalizationError<'tcx>;
+
+    fn tcx(&self) -> TyCtxt<'tcx> {
+        self.tcx
+    }
+
+    fn fold_ty(&mut self, ty: Ty<'tcx>) -> Result<Ty<'tcx>, Self::Error> {
+        match self.try_normalize_generic_arg_after_erasing_regions(ty.into()) {
+            Ok(t) => Ok(t.expect_ty()),
+            Err(_) => Err(NormalizationError::Type(ty)),
+        }
+    }
+
+    fn fold_const(
+        &mut self,
+        c: &'tcx ty::Const<'tcx>,
+    ) -> Result<&'tcx ty::Const<'tcx>, Self::Error> {
+        match self.try_normalize_generic_arg_after_erasing_regions(c.into()) {
+            Ok(t) => Ok(t.expect_const()),
+            Err(_) => Err(NormalizationError::Const(*c)),
+        }
+    }
+
+    fn fold_mir_const(
+        &mut self,
+        c: mir::ConstantKind<'tcx>,
+    ) -> Result<mir::ConstantKind<'tcx>, Self::Error> {
+        // FIXME: This *probably* needs canonicalization too!
+        let arg = self.param_env.and(c);
+        match self.tcx.try_normalize_mir_const_after_erasing_regions(arg) {
+            Ok(c) => Ok(c),
+            Err(_) => Err(NormalizationError::ConstantKind(c)),
+        }
     }
 }
index 175295b3199e8e2e2c1bf0cc5115ba53133d8657..f454b95862bab57b319630ac74d2115c083f3abb 100644 (file)
@@ -2016,24 +2016,24 @@ fn tcx<'b>(&'b self) -> TyCtxt<'tcx> {
     fn fold_binder<T: TypeFoldable<'tcx>>(
         &mut self,
         t: ty::Binder<'tcx, T>,
-    ) -> ty::Binder<'tcx, T> {
+    ) -> Result<ty::Binder<'tcx, T>, Self::Error> {
         self.current_index.shift_in(1);
         let t = t.super_fold_with(self);
         self.current_index.shift_out(1);
         t
     }
 
-    fn fold_ty(&mut self, t: Ty<'tcx>) -> Ty<'tcx> {
+    fn fold_ty(&mut self, t: Ty<'tcx>) -> Result<Ty<'tcx>, Self::Error> {
         match *t.kind() {
             _ if t.has_vars_bound_at_or_above(self.current_index) || t.has_placeholders() => {
                 return t.super_fold_with(self);
             }
             _ => {}
         }
-        t
+        Ok(t)
     }
 
-    fn fold_region(&mut self, r: ty::Region<'tcx>) -> ty::Region<'tcx> {
+    fn fold_region(&mut self, r: ty::Region<'tcx>) -> Result<ty::Region<'tcx>, Self::Error> {
         let name = &mut self.name;
         let region = match *r {
             ty::ReLateBound(_, br) => self.region_map.entry(br).or_insert_with(|| name(br)),
@@ -2049,13 +2049,13 @@ fn fold_region(&mut self, r: ty::Region<'tcx>) -> ty::Region<'tcx> {
                     }
                 }
             }
-            _ => return r,
+            _ => return Ok(r),
         };
         if let ty::ReLateBound(debruijn1, br) = *region {
             assert_eq!(debruijn1, ty::INNERMOST);
-            self.tcx.mk_region(ty::ReLateBound(self.current_index, br))
+            Ok(self.tcx.mk_region(ty::ReLateBound(self.current_index, br)))
         } else {
-            region
+            Ok(region)
         }
     }
 }
@@ -2193,7 +2193,7 @@ fn name_by_region_index(index: usize) -> Symbol {
                 name: &mut name,
                 region_map: BTreeMap::new(),
             };
-            let new_value = value.clone().skip_binder().fold_with(&mut folder);
+            let new_value = value.clone().skip_binder().fold_with(&mut folder).into_ok();
             let region_map = folder.region_map;
             start_or_continue(&mut self, "", "> ");
             (new_value, region_map)
index 0f8e80806e31e430edc9dc4ff13fc80fb94b4489..ee6eed0f39b2d33dfe044c3bf3bdcf1b8a866d3c 100644 (file)
@@ -669,8 +669,8 @@ fn lift_to_tcx(self, tcx: TyCtxt<'tcx>) -> Option<Self::Lifted> {
 
 /// AdtDefs are basically the same as a DefId.
 impl<'tcx> TypeFoldable<'tcx> for &'tcx ty::AdtDef {
-    fn super_fold_with<F: TypeFolder<'tcx>>(self, _folder: &mut F) -> Self {
-        self
+    fn super_fold_with<F: TypeFolder<'tcx>>(self, _folder: &mut F) -> Result<Self, F::Error> {
+        Ok(self)
     }
 
     fn super_visit_with<V: TypeVisitor<'tcx>>(&self, _visitor: &mut V) -> ControlFlow<V::BreakTy> {
@@ -679,8 +679,8 @@ fn super_visit_with<V: TypeVisitor<'tcx>>(&self, _visitor: &mut V) -> ControlFlo
 }
 
 impl<'tcx, T: TypeFoldable<'tcx>, U: TypeFoldable<'tcx>> TypeFoldable<'tcx> for (T, U) {
-    fn super_fold_with<F: TypeFolder<'tcx>>(self, folder: &mut F) -> (T, U) {
-        (self.0.fold_with(folder), self.1.fold_with(folder))
+    fn super_fold_with<F: TypeFolder<'tcx>>(self, folder: &mut F) -> Result<(T, U), F::Error> {
+        Ok((self.0.fold_with(folder)?, self.1.fold_with(folder)?))
     }
 
     fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> {
@@ -692,8 +692,8 @@ fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow
 impl<'tcx, A: TypeFoldable<'tcx>, B: TypeFoldable<'tcx>, C: TypeFoldable<'tcx>> TypeFoldable<'tcx>
     for (A, B, C)
 {
-    fn super_fold_with<F: TypeFolder<'tcx>>(self, folder: &mut F) -> (A, B, C) {
-        (self.0.fold_with(folder), self.1.fold_with(folder), self.2.fold_with(folder))
+    fn super_fold_with<F: TypeFolder<'tcx>>(self, folder: &mut F) -> Result<(A, B, C), F::Error> {
+        Ok((self.0.fold_with(folder)?, self.1.fold_with(folder)?, self.2.fold_with(folder)?))
     }
 
     fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> {
@@ -718,9 +718,9 @@ impl<'tcx, T, E> TypeFoldable<'tcx> for Result<T, E> {
 }
 
 impl<'tcx, T: TypeFoldable<'tcx>> TypeFoldable<'tcx> for Rc<T> {
-    fn super_fold_with<F: TypeFolder<'tcx>>(self, folder: &mut F) -> Self {
+    fn super_fold_with<F: TypeFolder<'tcx>>(self, folder: &mut F) -> Result<Self, F::Error> {
         // FIXME: Reuse the `Rc` here.
-        Rc::new((*self).clone().fold_with(folder))
+        Ok(Rc::new((*self).clone().fold_with(folder)?))
     }
 
     fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> {
@@ -729,9 +729,9 @@ fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow
 }
 
 impl<'tcx, T: TypeFoldable<'tcx>> TypeFoldable<'tcx> for Arc<T> {
-    fn super_fold_with<F: TypeFolder<'tcx>>(self, folder: &mut F) -> Self {
+    fn super_fold_with<F: TypeFolder<'tcx>>(self, folder: &mut F) -> Result<Self, F::Error> {
         // FIXME: Reuse the `Arc` here.
-        Arc::new((*self).clone().fold_with(folder))
+        Ok(Arc::new((*self).clone().fold_with(folder)?))
     }
 
     fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> {
@@ -740,8 +740,8 @@ fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow
 }
 
 impl<'tcx, T: TypeFoldable<'tcx>> TypeFoldable<'tcx> for Box<T> {
-    fn super_fold_with<F: TypeFolder<'tcx>>(self, folder: &mut F) -> Self {
-        self.map_id(|value| value.fold_with(folder))
+    fn super_fold_with<F: TypeFolder<'tcx>>(self, folder: &mut F) -> Result<Self, F::Error> {
+        self.try_map_id(|value| value.fold_with(folder))
     }
 
     fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> {
@@ -750,8 +750,8 @@ fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow
 }
 
 impl<'tcx, T: TypeFoldable<'tcx>> TypeFoldable<'tcx> for Vec<T> {
-    fn super_fold_with<F: TypeFolder<'tcx>>(self, folder: &mut F) -> Self {
-        self.map_id(|t| t.fold_with(folder))
+    fn super_fold_with<F: TypeFolder<'tcx>>(self, folder: &mut F) -> Result<Self, F::Error> {
+        self.try_map_id(|t| t.fold_with(folder))
     }
 
     fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> {
@@ -760,8 +760,8 @@ fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow
 }
 
 impl<'tcx, T: TypeFoldable<'tcx>> TypeFoldable<'tcx> for Box<[T]> {
-    fn super_fold_with<F: TypeFolder<'tcx>>(self, folder: &mut F) -> Self {
-        self.map_id(|t| t.fold_with(folder))
+    fn super_fold_with<F: TypeFolder<'tcx>>(self, folder: &mut F) -> Result<Self, F::Error> {
+        self.try_map_id(|t| t.fold_with(folder))
     }
 
     fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> {
@@ -770,11 +770,11 @@ fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow
 }
 
 impl<'tcx, T: TypeFoldable<'tcx>> TypeFoldable<'tcx> for ty::Binder<'tcx, T> {
-    fn super_fold_with<F: TypeFolder<'tcx>>(self, folder: &mut F) -> Self {
-        self.map_bound(|ty| ty.fold_with(folder))
+    fn super_fold_with<F: TypeFolder<'tcx>>(self, folder: &mut F) -> Result<Self, F::Error> {
+        self.try_map_bound(|ty| ty.fold_with(folder))
     }
 
-    fn fold_with<F: TypeFolder<'tcx>>(self, folder: &mut F) -> Self {
+    fn fold_with<F: TypeFolder<'tcx>>(self, folder: &mut F) -> Result<Self, F::Error> {
         folder.fold_binder(self)
     }
 
@@ -788,7 +788,7 @@ fn visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow<V::Br
 }
 
 impl<'tcx> TypeFoldable<'tcx> for &'tcx ty::List<ty::Binder<'tcx, ty::ExistentialPredicate<'tcx>>> {
-    fn super_fold_with<F: TypeFolder<'tcx>>(self, folder: &mut F) -> Self {
+    fn super_fold_with<F: TypeFolder<'tcx>>(self, folder: &mut F) -> Result<Self, F::Error> {
         ty::util::fold_list(self, folder, |tcx, v| tcx.intern_poly_existential_predicates(v))
     }
 
@@ -798,7 +798,7 @@ fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow
 }
 
 impl<'tcx> TypeFoldable<'tcx> for &'tcx ty::List<Ty<'tcx>> {
-    fn super_fold_with<F: TypeFolder<'tcx>>(self, folder: &mut F) -> Self {
+    fn super_fold_with<F: TypeFolder<'tcx>>(self, folder: &mut F) -> Result<Self, F::Error> {
         ty::util::fold_list(self, folder, |tcx, v| tcx.intern_type_list(v))
     }
 
@@ -808,7 +808,7 @@ fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow
 }
 
 impl<'tcx> TypeFoldable<'tcx> for &'tcx ty::List<ProjectionKind> {
-    fn super_fold_with<F: TypeFolder<'tcx>>(self, folder: &mut F) -> Self {
+    fn super_fold_with<F: TypeFolder<'tcx>>(self, folder: &mut F) -> Result<Self, F::Error> {
         ty::util::fold_list(self, folder, |tcx, v| tcx.intern_projs(v))
     }
 
@@ -818,24 +818,24 @@ fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow
 }
 
 impl<'tcx> TypeFoldable<'tcx> for ty::instance::Instance<'tcx> {
-    fn super_fold_with<F: TypeFolder<'tcx>>(self, folder: &mut F) -> Self {
+    fn super_fold_with<F: TypeFolder<'tcx>>(self, folder: &mut F) -> Result<Self, F::Error> {
         use crate::ty::InstanceDef::*;
-        Self {
-            substs: self.substs.fold_with(folder),
+        Ok(Self {
+            substs: self.substs.fold_with(folder)?,
             def: match self.def {
-                Item(def) => Item(def.fold_with(folder)),
-                VtableShim(did) => VtableShim(did.fold_with(folder)),
-                ReifyShim(did) => ReifyShim(did.fold_with(folder)),
-                Intrinsic(did) => Intrinsic(did.fold_with(folder)),
-                FnPtrShim(did, ty) => FnPtrShim(did.fold_with(folder), ty.fold_with(folder)),
-                Virtual(did, i) => Virtual(did.fold_with(folder), i),
+                Item(def) => Item(def.fold_with(folder)?),
+                VtableShim(did) => VtableShim(did.fold_with(folder)?),
+                ReifyShim(did) => ReifyShim(did.fold_with(folder)?),
+                Intrinsic(did) => Intrinsic(did.fold_with(folder)?),
+                FnPtrShim(did, ty) => FnPtrShim(did.fold_with(folder)?, ty.fold_with(folder)?),
+                Virtual(did, i) => Virtual(did.fold_with(folder)?, i),
                 ClosureOnceShim { call_once, track_caller } => {
-                    ClosureOnceShim { call_once: call_once.fold_with(folder), track_caller }
+                    ClosureOnceShim { call_once: call_once.fold_with(folder)?, track_caller }
                 }
-                DropGlue(did, ty) => DropGlue(did.fold_with(folder), ty.fold_with(folder)),
-                CloneShim(did, ty) => CloneShim(did.fold_with(folder), ty.fold_with(folder)),
+                DropGlue(did, ty) => DropGlue(did.fold_with(folder)?, ty.fold_with(folder)?),
+                CloneShim(did, ty) => CloneShim(did.fold_with(folder)?, ty.fold_with(folder)?),
             },
-        }
+        })
     }
 
     fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> {
@@ -860,8 +860,8 @@ fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow
 }
 
 impl<'tcx> TypeFoldable<'tcx> for interpret::GlobalId<'tcx> {
-    fn super_fold_with<F: TypeFolder<'tcx>>(self, folder: &mut F) -> Self {
-        Self { instance: self.instance.fold_with(folder), promoted: self.promoted }
+    fn super_fold_with<F: TypeFolder<'tcx>>(self, folder: &mut F) -> Result<Self, F::Error> {
+        Ok(Self { instance: self.instance.fold_with(folder)?, promoted: self.promoted })
     }
 
     fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> {
@@ -870,26 +870,26 @@ fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow
 }
 
 impl<'tcx> TypeFoldable<'tcx> for Ty<'tcx> {
-    fn super_fold_with<F: TypeFolder<'tcx>>(self, folder: &mut F) -> Self {
+    fn super_fold_with<F: TypeFolder<'tcx>>(self, folder: &mut F) -> Result<Self, F::Error> {
         let kind = match *self.kind() {
-            ty::RawPtr(tm) => ty::RawPtr(tm.fold_with(folder)),
-            ty::Array(typ, sz) => ty::Array(typ.fold_with(folder), sz.fold_with(folder)),
-            ty::Slice(typ) => ty::Slice(typ.fold_with(folder)),
-            ty::Adt(tid, substs) => ty::Adt(tid, substs.fold_with(folder)),
+            ty::RawPtr(tm) => ty::RawPtr(tm.fold_with(folder)?),
+            ty::Array(typ, sz) => ty::Array(typ.fold_with(folder)?, sz.fold_with(folder)?),
+            ty::Slice(typ) => ty::Slice(typ.fold_with(folder)?),
+            ty::Adt(tid, substs) => ty::Adt(tid, substs.fold_with(folder)?),
             ty::Dynamic(trait_ty, region) => {
-                ty::Dynamic(trait_ty.fold_with(folder), region.fold_with(folder))
+                ty::Dynamic(trait_ty.fold_with(folder)?, region.fold_with(folder)?)
             }
-            ty::Tuple(ts) => ty::Tuple(ts.fold_with(folder)),
-            ty::FnDef(def_id, substs) => ty::FnDef(def_id, substs.fold_with(folder)),
-            ty::FnPtr(f) => ty::FnPtr(f.fold_with(folder)),
-            ty::Ref(r, ty, mutbl) => ty::Ref(r.fold_with(folder), ty.fold_with(folder), mutbl),
+            ty::Tuple(ts) => ty::Tuple(ts.fold_with(folder)?),
+            ty::FnDef(def_id, substs) => ty::FnDef(def_id, substs.fold_with(folder)?),
+            ty::FnPtr(f) => ty::FnPtr(f.fold_with(folder)?),
+            ty::Ref(r, ty, mutbl) => ty::Ref(r.fold_with(folder)?, ty.fold_with(folder)?, mutbl),
             ty::Generator(did, substs, movability) => {
-                ty::Generator(did, substs.fold_with(folder), movability)
+                ty::Generator(did, substs.fold_with(folder)?, movability)
             }
-            ty::GeneratorWitness(types) => ty::GeneratorWitness(types.fold_with(folder)),
-            ty::Closure(did, substs) => ty::Closure(did, substs.fold_with(folder)),
-            ty::Projection(data) => ty::Projection(data.fold_with(folder)),
-            ty::Opaque(did, substs) => ty::Opaque(did, substs.fold_with(folder)),
+            ty::GeneratorWitness(types) => ty::GeneratorWitness(types.fold_with(folder)?),
+            ty::Closure(did, substs) => ty::Closure(did, substs.fold_with(folder)?),
+            ty::Projection(data) => ty::Projection(data.fold_with(folder)?),
+            ty::Opaque(did, substs) => ty::Opaque(did, substs.fold_with(folder)?),
 
             ty::Bool
             | ty::Char
@@ -903,13 +903,13 @@ fn super_fold_with<F: TypeFolder<'tcx>>(self, folder: &mut F) -> Self {
             | ty::Bound(..)
             | ty::Placeholder(..)
             | ty::Never
-            | ty::Foreign(..) => return self,
+            | ty::Foreign(..) => return Ok(self),
         };
 
-        if *self.kind() == kind { self } else { folder.tcx().mk_ty(kind) }
+        Ok(if *self.kind() == kind { self } else { folder.tcx().mk_ty(kind) })
     }
 
-    fn fold_with<F: TypeFolder<'tcx>>(self, folder: &mut F) -> Self {
+    fn fold_with<F: TypeFolder<'tcx>>(self, folder: &mut F) -> Result<Self, F::Error> {
         folder.fold_ty(self)
     }
 
@@ -961,11 +961,11 @@ fn visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow<V::Br
 }
 
 impl<'tcx> TypeFoldable<'tcx> for ty::Region<'tcx> {
-    fn super_fold_with<F: TypeFolder<'tcx>>(self, _folder: &mut F) -> Self {
-        self
+    fn super_fold_with<F: TypeFolder<'tcx>>(self, _folder: &mut F) -> Result<Self, F::Error> {
+        Ok(self)
     }
 
-    fn fold_with<F: TypeFolder<'tcx>>(self, folder: &mut F) -> Self {
+    fn fold_with<F: TypeFolder<'tcx>>(self, folder: &mut F) -> Result<Self, F::Error> {
         folder.fold_region(self)
     }
 
@@ -979,13 +979,13 @@ fn visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow<V::Br
 }
 
 impl<'tcx> TypeFoldable<'tcx> for ty::Predicate<'tcx> {
-    fn fold_with<F: TypeFolder<'tcx>>(self, folder: &mut F) -> Self {
+    fn fold_with<F: TypeFolder<'tcx>>(self, folder: &mut F) -> Result<Self, F::Error> {
         folder.fold_predicate(self)
     }
 
-    fn super_fold_with<F: TypeFolder<'tcx>>(self, folder: &mut F) -> Self {
-        let new = self.inner.kind.fold_with(folder);
-        folder.tcx().reuse_or_mk_predicate(self, new)
+    fn super_fold_with<F: TypeFolder<'tcx>>(self, folder: &mut F) -> Result<Self, F::Error> {
+        let new = self.inner.kind.fold_with(folder)?;
+        Ok(folder.tcx().reuse_or_mk_predicate(self, new))
     }
 
     fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> {
@@ -1006,7 +1006,7 @@ fn has_type_flags(&self, flags: ty::TypeFlags) -> bool {
 }
 
 impl<'tcx> TypeFoldable<'tcx> for &'tcx ty::List<ty::Predicate<'tcx>> {
-    fn super_fold_with<F: TypeFolder<'tcx>>(self, folder: &mut F) -> Self {
+    fn super_fold_with<F: TypeFolder<'tcx>>(self, folder: &mut F) -> Result<Self, F::Error> {
         ty::util::fold_list(self, folder, |tcx, v| tcx.intern_predicates(v))
     }
 
@@ -1016,8 +1016,8 @@ fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow
 }
 
 impl<'tcx, T: TypeFoldable<'tcx>, I: Idx> TypeFoldable<'tcx> for IndexVec<I, T> {
-    fn super_fold_with<F: TypeFolder<'tcx>>(self, folder: &mut F) -> Self {
-        self.map_id(|x| x.fold_with(folder))
+    fn super_fold_with<F: TypeFolder<'tcx>>(self, folder: &mut F) -> Result<Self, F::Error> {
+        self.try_map_id(|x| x.fold_with(folder))
     }
 
     fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> {
@@ -1026,17 +1026,17 @@ fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow
 }
 
 impl<'tcx> TypeFoldable<'tcx> for &'tcx ty::Const<'tcx> {
-    fn super_fold_with<F: TypeFolder<'tcx>>(self, folder: &mut F) -> Self {
-        let ty = self.ty.fold_with(folder);
-        let val = self.val.fold_with(folder);
+    fn super_fold_with<F: TypeFolder<'tcx>>(self, folder: &mut F) -> Result<Self, F::Error> {
+        let ty = self.ty.fold_with(folder)?;
+        let val = self.val.fold_with(folder)?;
         if ty != self.ty || val != self.val {
-            folder.tcx().mk_const(ty::Const { ty, val })
+            Ok(folder.tcx().mk_const(ty::Const { ty, val }))
         } else {
-            self
+            Ok(self)
         }
     }
 
-    fn fold_with<F: TypeFolder<'tcx>>(self, folder: &mut F) -> Self {
+    fn fold_with<F: TypeFolder<'tcx>>(self, folder: &mut F) -> Result<Self, F::Error> {
         folder.fold_const(self)
     }
 
@@ -1051,16 +1051,16 @@ fn visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow<V::Br
 }
 
 impl<'tcx> TypeFoldable<'tcx> for ty::ConstKind<'tcx> {
-    fn super_fold_with<F: TypeFolder<'tcx>>(self, folder: &mut F) -> Self {
-        match self {
-            ty::ConstKind::Infer(ic) => ty::ConstKind::Infer(ic.fold_with(folder)),
-            ty::ConstKind::Param(p) => ty::ConstKind::Param(p.fold_with(folder)),
-            ty::ConstKind::Unevaluated(uv) => ty::ConstKind::Unevaluated(uv.fold_with(folder)),
+    fn super_fold_with<F: TypeFolder<'tcx>>(self, folder: &mut F) -> Result<Self, F::Error> {
+        Ok(match self {
+            ty::ConstKind::Infer(ic) => ty::ConstKind::Infer(ic.fold_with(folder)?),
+            ty::ConstKind::Param(p) => ty::ConstKind::Param(p.fold_with(folder)?),
+            ty::ConstKind::Unevaluated(uv) => ty::ConstKind::Unevaluated(uv.fold_with(folder)?),
             ty::ConstKind::Value(_)
             | ty::ConstKind::Bound(..)
             | ty::ConstKind::Placeholder(..)
             | ty::ConstKind::Error(_) => self,
-        }
+        })
     }
 
     fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> {
@@ -1077,8 +1077,8 @@ fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow
 }
 
 impl<'tcx> TypeFoldable<'tcx> for InferConst<'tcx> {
-    fn super_fold_with<F: TypeFolder<'tcx>>(self, _folder: &mut F) -> Self {
-        self
+    fn super_fold_with<F: TypeFolder<'tcx>>(self, _folder: &mut F) -> Result<Self, F::Error> {
+        Ok(self)
     }
 
     fn super_visit_with<V: TypeVisitor<'tcx>>(&self, _visitor: &mut V) -> ControlFlow<V::BreakTy> {
@@ -1087,12 +1087,12 @@ fn super_visit_with<V: TypeVisitor<'tcx>>(&self, _visitor: &mut V) -> ControlFlo
 }
 
 impl<'tcx> TypeFoldable<'tcx> for ty::Unevaluated<'tcx> {
-    fn super_fold_with<F: TypeFolder<'tcx>>(self, folder: &mut F) -> Self {
-        ty::Unevaluated {
+    fn super_fold_with<F: TypeFolder<'tcx>>(self, folder: &mut F) -> Result<Self, F::Error> {
+        Ok(ty::Unevaluated {
             def: self.def,
-            substs_: Some(self.substs(folder.tcx()).fold_with(folder)),
+            substs_: Some(self.substs(folder.tcx()).fold_with(folder)?),
             promoted: self.promoted,
-        }
+        })
     }
 
     fn visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> {
@@ -1112,12 +1112,12 @@ fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow
 }
 
 impl<'tcx> TypeFoldable<'tcx> for ty::Unevaluated<'tcx, ()> {
-    fn super_fold_with<F: TypeFolder<'tcx>>(self, folder: &mut F) -> Self {
-        ty::Unevaluated {
+    fn super_fold_with<F: TypeFolder<'tcx>>(self, folder: &mut F) -> Result<Self, F::Error> {
+        Ok(ty::Unevaluated {
             def: self.def,
-            substs_: Some(self.substs(folder.tcx()).fold_with(folder)),
+            substs_: Some(self.substs(folder.tcx()).fold_with(folder)?),
             promoted: self.promoted,
-        }
+        })
     }
 
     fn visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> {
index c2b32cd06ea0a66c4e28f9597bc76a25c3b3684d..fcbf15b3bca47adbbdf71c79dd693cf89f75b0c0 100644 (file)
@@ -1101,6 +1101,18 @@ pub fn map_bound<F, U: TypeFoldable<'tcx>>(self, f: F) -> Binder<'tcx, U>
         Binder(value, self.1)
     }
 
+    pub fn try_map_bound<F, U: TypeFoldable<'tcx>, E>(self, f: F) -> Result<Binder<'tcx, U>, E>
+    where
+        F: FnOnce(T) -> Result<U, E>,
+    {
+        let value = f(self.0)?;
+        if cfg!(debug_assertions) {
+            let mut validator = ValidateBoundVars::new(self.1);
+            value.visit_with(&mut validator);
+        }
+        Ok(Binder(value, self.1))
+    }
+
     /// Wraps a `value` in a binder, using the same bound variables as the
     /// current `Binder`. This should not be used if the new value *changes*
     /// the bound variables. Note: the (old or new) value itself does not
index 73a8e18949de06ad6a4d8d5b3dc0c8329b5c22bf..ffa495ce4803fba8217d5a0ddd86eb0dfb227ab6 100644 (file)
@@ -153,11 +153,11 @@ fn lift_to_tcx(self, tcx: TyCtxt<'tcx>) -> Option<Self::Lifted> {
 }
 
 impl<'tcx> TypeFoldable<'tcx> for GenericArg<'tcx> {
-    fn super_fold_with<F: TypeFolder<'tcx>>(self, folder: &mut F) -> Self {
+    fn super_fold_with<F: TypeFolder<'tcx>>(self, folder: &mut F) -> Result<Self, F::Error> {
         match self.unpack() {
-            GenericArgKind::Lifetime(lt) => lt.fold_with(folder).into(),
-            GenericArgKind::Type(ty) => ty.fold_with(folder).into(),
-            GenericArgKind::Const(ct) => ct.fold_with(folder).into(),
+            GenericArgKind::Lifetime(lt) => lt.fold_with(folder).map(Into::into),
+            GenericArgKind::Type(ty) => ty.fold_with(folder).map(Into::into),
+            GenericArgKind::Const(ct) => ct.fold_with(folder).map(Into::into),
         }
     }
 
@@ -372,7 +372,7 @@ pub fn truncate_to(&self, tcx: TyCtxt<'tcx>, generics: &ty::Generics) -> SubstsR
 }
 
 impl<'tcx> TypeFoldable<'tcx> for SubstsRef<'tcx> {
-    fn super_fold_with<F: TypeFolder<'tcx>>(self, folder: &mut F) -> Self {
+    fn super_fold_with<F: TypeFolder<'tcx>>(self, folder: &mut F) -> Result<Self, F::Error> {
         // This code is hot enough that it's worth specializing for the most
         // common length lists, to avoid the overhead of `SmallVec` creation.
         // The match arms are in order of frequency. The 1, 2, and 0 cases are
@@ -381,22 +381,27 @@ fn super_fold_with<F: TypeFolder<'tcx>>(self, folder: &mut F) -> Self {
         // calling `intern_substs`.
         match self.len() {
             1 => {
-                let param0 = self[0].fold_with(folder);
-                if param0 == self[0] { self } else { folder.tcx().intern_substs(&[param0]) }
+                let param0 = self[0].fold_with(folder)?;
+                if param0 == self[0] { Ok(self) } else { Ok(folder.tcx().intern_substs(&[param0])) }
             }
             2 => {
-                let param0 = self[0].fold_with(folder);
-                let param1 = self[1].fold_with(folder);
+                let param0 = self[0].fold_with(folder)?;
+                let param1 = self[1].fold_with(folder)?;
                 if param0 == self[0] && param1 == self[1] {
-                    self
+                    Ok(self)
                 } else {
-                    folder.tcx().intern_substs(&[param0, param1])
+                    Ok(folder.tcx().intern_substs(&[param0, param1]))
                 }
             }
-            0 => self,
+            0 => Ok(self),
             _ => {
-                let params: SmallVec<[_; 8]> = self.iter().map(|k| k.fold_with(folder)).collect();
-                if params[..] == self[..] { self } else { folder.tcx().intern_substs(&params) }
+                let params: SmallVec<[_; 8]> =
+                    self.iter().map(|k| k.fold_with(folder)).collect::<Result<_, _>>()?;
+                if params[..] == self[..] {
+                    Ok(self)
+                } else {
+                    Ok(folder.tcx().intern_substs(&params))
+                }
             }
         }
     }
@@ -434,7 +439,7 @@ fn subst_spanned(
         span: Option<Span>,
     ) -> T {
         let mut folder = SubstFolder { tcx, substs, span, binders_passed: 0 };
-        self.fold_with(&mut folder)
+        self.fold_with(&mut folder).into_ok()
     }
 }
 
@@ -460,14 +465,14 @@ fn tcx<'b>(&'b self) -> TyCtxt<'tcx> {
     fn fold_binder<T: TypeFoldable<'tcx>>(
         &mut self,
         t: ty::Binder<'tcx, T>,
-    ) -> ty::Binder<'tcx, T> {
+    ) -> Result<ty::Binder<'tcx, T>, Self::Error> {
         self.binders_passed += 1;
-        let t = t.super_fold_with(self);
+        let t = t.super_fold_with(self)?;
         self.binders_passed -= 1;
-        t
+        Ok(t)
     }
 
-    fn fold_region(&mut self, r: ty::Region<'tcx>) -> ty::Region<'tcx> {
+    fn fold_region(&mut self, r: ty::Region<'tcx>) -> Result<ty::Region<'tcx>, Self::Error> {
         // Note: This routine only handles regions that are bound on
         // type declarations and other outer declarations, not those
         // bound in *fn types*. Region substitution of the bound
@@ -477,7 +482,7 @@ fn fold_region(&mut self, r: ty::Region<'tcx>) -> ty::Region<'tcx> {
             ty::ReEarlyBound(data) => {
                 let rk = self.substs.get(data.index as usize).map(|k| k.unpack());
                 match rk {
-                    Some(GenericArgKind::Lifetime(lt)) => self.shift_region_through_binders(lt),
+                    Some(GenericArgKind::Lifetime(lt)) => Ok(self.shift_region_through_binders(lt)),
                     _ => {
                         let span = self.span.unwrap_or(DUMMY_SP);
                         let msg = format!(
@@ -489,31 +494,37 @@ fn fold_region(&mut self, r: ty::Region<'tcx>) -> ty::Region<'tcx> {
                     }
                 }
             }
-            _ => r,
+            _ => Ok(r),
         }
     }
 
-    fn fold_ty(&mut self, t: Ty<'tcx>) -> Ty<'tcx> {
+    fn fold_ty(&mut self, t: Ty<'tcx>) -> Result<Ty<'tcx>, Self::Error> {
         if !t.potentially_needs_subst() {
-            return t;
+            return Ok(t);
         }
 
         match *t.kind() {
-            ty::Param(p) => self.ty_for_param(p, t),
+            ty::Param(p) => Ok(self.ty_for_param(p, t)),
             _ => t.super_fold_with(self),
         }
     }
 
-    fn fold_const(&mut self, c: &'tcx ty::Const<'tcx>) -> &'tcx ty::Const<'tcx> {
+    fn fold_const(
+        &mut self,
+        c: &'tcx ty::Const<'tcx>,
+    ) -> Result<&'tcx ty::Const<'tcx>, Self::Error> {
         if let ty::ConstKind::Param(p) = c.val {
-            self.const_for_param(p, c)
+            Ok(self.const_for_param(p, c))
         } else {
             c.super_fold_with(self)
         }
     }
 
     #[inline]
-    fn fold_mir_const(&mut self, c: mir::ConstantKind<'tcx>) -> mir::ConstantKind<'tcx> {
+    fn fold_mir_const(
+        &mut self,
+        c: mir::ConstantKind<'tcx>,
+    ) -> Result<mir::ConstantKind<'tcx>, Self::Error> {
         c.super_fold_with(self)
     }
 }
index 6e7acb244d1597a14fe80673f764381419335e5e..5137f9650633a38dcdfc09009a359ee1fcdc98c7 100644 (file)
@@ -574,14 +574,14 @@ fn expand_opaque_ty(&mut self, def_id: DefId, substs: SubstsRef<'tcx>) -> Option
         if self.found_any_recursion {
             return None;
         }
-        let substs = substs.fold_with(self);
+        let substs = substs.fold_with(self).into_ok();
         if !self.check_recursion || self.seen_opaque_tys.insert(def_id) {
             let expanded_ty = match self.expanded_cache.get(&(def_id, substs)) {
                 Some(expanded_ty) => expanded_ty,
                 None => {
                     let generic_ty = self.tcx.type_of(def_id);
                     let concrete_ty = generic_ty.subst(self.tcx, substs);
-                    let expanded_ty = self.fold_ty(concrete_ty);
+                    let expanded_ty = self.fold_ty(concrete_ty).into_ok();
                     self.expanded_cache.insert((def_id, substs), expanded_ty);
                     expanded_ty
                 }
@@ -605,13 +605,13 @@ fn tcx(&self) -> TyCtxt<'tcx> {
         self.tcx
     }
 
-    fn fold_ty(&mut self, t: Ty<'tcx>) -> Ty<'tcx> {
+    fn fold_ty(&mut self, t: Ty<'tcx>) -> Result<Ty<'tcx>, Self::Error> {
         if let ty::Opaque(def_id, substs) = t.kind {
-            self.expand_opaque_ty(def_id, substs).unwrap_or(t)
+            Ok(self.expand_opaque_ty(def_id, substs).unwrap_or(t))
         } else if t.has_opaque_types() {
             t.super_fold_with(self)
         } else {
-            t
+            Ok(t)
         }
     }
 }
@@ -1046,25 +1046,31 @@ pub fn fold_list<'tcx, F, T>(
     list: &'tcx ty::List<T>,
     folder: &mut F,
     intern: impl FnOnce(TyCtxt<'tcx>, &[T]) -> &'tcx ty::List<T>,
-) -> &'tcx ty::List<T>
+) -> Result<&'tcx ty::List<T>, F::Error>
 where
     F: TypeFolder<'tcx>,
     T: TypeFoldable<'tcx> + PartialEq + Copy,
 {
     let mut iter = list.iter();
     // Look for the first element that changed
-    if let Some((i, new_t)) = iter.by_ref().enumerate().find_map(|(i, t)| {
-        let new_t = t.fold_with(folder);
-        if new_t == t { None } else { Some((i, new_t)) }
+    match iter.by_ref().enumerate().find_map(|(i, t)| match t.fold_with(folder) {
+        Ok(new_t) if new_t == t => None,
+        new_t => Some((i, new_t)),
     }) {
-        // An element changed, prepare to intern the resulting list
-        let mut new_list = SmallVec::<[_; 8]>::with_capacity(list.len());
-        new_list.extend_from_slice(&list[..i]);
-        new_list.push(new_t);
-        new_list.extend(iter.map(|t| t.fold_with(folder)));
-        intern(folder.tcx(), &new_list)
-    } else {
-        list
+        Some((i, Ok(new_t))) => {
+            // An element changed, prepare to intern the resulting list
+            let mut new_list = SmallVec::<[_; 8]>::with_capacity(list.len());
+            new_list.extend_from_slice(&list[..i]);
+            new_list.push(new_t);
+            for t in iter {
+                new_list.push(t.fold_with(folder)?)
+            }
+            Ok(intern(folder.tcx(), &new_list))
+        }
+        Some((_, Err(err))) => {
+            return Err(err);
+        }
+        None => Ok(list),
     }
 }
 
@@ -1086,7 +1092,7 @@ pub fn normalize_opaque_types(
         check_recursion: false,
         tcx,
     };
-    val.fold_with(&mut visitor)
+    val.fold_with(&mut visitor).into_ok()
 }
 
 pub fn provide(providers: &mut ty::query::Providers) {
index 790d9243fbaec874db7488ff817c615d5068cb1e..c45946a9e2a982d6ca43e534934250481922453a 100644 (file)
@@ -316,28 +316,6 @@ fn visit_local(&mut self, local: &mut Local, context: PlaceContext, location: Lo
         }
     }
 
-    fn process_projection_elem(
-        &mut self,
-        elem: PlaceElem<'tcx>,
-        _: Location,
-    ) -> Option<PlaceElem<'tcx>> {
-        match elem {
-            PlaceElem::Index(local) => {
-                if let Some(replacement) = self.replacements.for_src(local) {
-                    bug!(
-                        "cannot replace {:?} with {:?} in index projection {:?}",
-                        local,
-                        replacement,
-                        elem,
-                    );
-                } else {
-                    None
-                }
-            }
-            _ => None,
-        }
-    }
-
     fn visit_place(&mut self, place: &mut Place<'tcx>, context: PlaceContext, location: Location) {
         if let Some(replacement) = self.replacements.for_src(place.local) {
             // Rebase `place`s projections onto `replacement`'s.
index f9ef31462780731a9375aa0ec7f4f379c17da875..b0bea7312a7ebac251e6bdbdca8bbbb4c14edf9d 100644 (file)
@@ -27,7 +27,7 @@
 use rustc_hir::intravisit::{self, NestedVisitorMap, Visitor};
 use rustc_index::vec::IndexVec;
 use rustc_middle::mir::visit::Visitor as _;
-use rustc_middle::mir::{dump_mir, traversal, Body, ConstQualifs, MirPhase, Promoted};
+use rustc_middle::mir::{dump_mir, traversal, Body, ConstQualifs, MirPass, MirPhase, Promoted};
 use rustc_middle::ty::query::Providers;
 use rustc_middle::ty::{self, TyCtxt, TypeFoldable};
 use rustc_span::{Span, Symbol};
@@ -78,7 +78,6 @@
 use rustc_const_eval::transform::check_consts;
 use rustc_const_eval::transform::promote_consts;
 use rustc_const_eval::transform::validate;
-pub use rustc_const_eval::transform::MirPass;
 use rustc_mir_dataflow::rustc_peek;
 
 pub fn provide(providers: &mut Providers) {
index 6c423a2bb5756c79476adf6a8186781b61c29914..3bcb71b64f455e2cf0ba4dcd55f4a9c85d50b6e0 100644 (file)
@@ -35,24 +35,4 @@ fn tcx(&self) -> TyCtxt<'tcx> {
     fn visit_ty(&mut self, ty: &mut Ty<'tcx>, _: TyContext) {
         *ty = self.tcx.normalize_erasing_regions(self.param_env, ty);
     }
-
-    #[inline]
-    fn process_projection_elem(
-        &mut self,
-        elem: PlaceElem<'tcx>,
-        _: Location,
-    ) -> Option<PlaceElem<'tcx>> {
-        match elem {
-            PlaceElem::Field(field, ty) => {
-                let new_ty = self.tcx.normalize_erasing_regions(self.param_env, ty);
-                if ty != new_ty { Some(PlaceElem::Field(field, new_ty)) } else { None }
-            }
-            // None of those contain a Ty.
-            PlaceElem::Index(..)
-            | PlaceElem::Deref
-            | PlaceElem::ConstantIndex { .. }
-            | PlaceElem::Subslice { .. }
-            | PlaceElem::Downcast(..) => None,
-        }
-    }
 }
index ce39d07656f2a529adde22f0bbdc8386512cbf20..55af2c9ddd32f1cb9a5455e443a0e76b364d530a 100644 (file)
@@ -1,6 +1,9 @@
+use super::pat::Expected;
 use super::ty::AllowPlus;
-use super::TokenType;
-use super::{BlockMode, Parser, PathStyle, Restrictions, SemiColonMode, SeqSep, TokenExpectType};
+use super::{
+    BlockMode, Parser, PathStyle, RecoverColon, RecoverComma, Restrictions, SemiColonMode, SeqSep,
+    TokenExpectType, TokenType,
+};
 
 use rustc_ast as ast;
 use rustc_ast::ptr::P;
@@ -19,6 +22,8 @@
 use rustc_span::symbol::{kw, Ident};
 use rustc_span::{MultiSpan, Span, SpanSnippetError, DUMMY_SP};
 
+use std::mem::take;
+
 use tracing::{debug, trace};
 
 const TURBOFISH_SUGGESTION_STR: &str =
@@ -2075,4 +2080,177 @@ pub(super) fn incorrect_move_async_order_found(
         );
         err
     }
+
+    /// Some special error handling for the "top-level" patterns in a match arm,
+    /// `for` loop, `let`, &c. (in contrast to subpatterns within such).
+    crate fn maybe_recover_colon_colon_in_pat_typo(
+        &mut self,
+        mut first_pat: P<Pat>,
+        ra: RecoverColon,
+        expected: Expected,
+    ) -> P<Pat> {
+        if RecoverColon::Yes != ra || token::Colon != self.token.kind {
+            return first_pat;
+        }
+        if !matches!(first_pat.kind, PatKind::Ident(_, _, None) | PatKind::Path(..))
+            || !self.look_ahead(1, |token| token.is_ident() && !token.is_reserved_ident())
+        {
+            return first_pat;
+        }
+        // The pattern looks like it might be a path with a `::` -> `:` typo:
+        // `match foo { bar:baz => {} }`
+        let span = self.token.span;
+        // We only emit "unexpected `:`" error here if we can successfully parse the
+        // whole pattern correctly in that case.
+        let snapshot = self.clone();
+
+        // Create error for "unexpected `:`".
+        match self.expected_one_of_not_found(&[], &[]) {
+            Err(mut err) => {
+                self.bump(); // Skip the `:`.
+                match self.parse_pat_no_top_alt(expected) {
+                    Err(mut inner_err) => {
+                        // Carry on as if we had not done anything, callers will emit a
+                        // reasonable error.
+                        inner_err.cancel();
+                        err.cancel();
+                        *self = snapshot;
+                    }
+                    Ok(mut pat) => {
+                        // We've parsed the rest of the pattern.
+                        let new_span = first_pat.span.to(pat.span);
+                        let mut show_sugg = false;
+                        // Try to construct a recovered pattern.
+                        match &mut pat.kind {
+                            PatKind::Struct(qself @ None, path, ..)
+                            | PatKind::TupleStruct(qself @ None, path, _)
+                            | PatKind::Path(qself @ None, path) => match &first_pat.kind {
+                                PatKind::Ident(_, ident, _) => {
+                                    path.segments.insert(0, PathSegment::from_ident(ident.clone()));
+                                    path.span = new_span;
+                                    show_sugg = true;
+                                    first_pat = pat;
+                                }
+                                PatKind::Path(old_qself, old_path) => {
+                                    path.segments = old_path
+                                        .segments
+                                        .iter()
+                                        .cloned()
+                                        .chain(take(&mut path.segments))
+                                        .collect();
+                                    path.span = new_span;
+                                    *qself = old_qself.clone();
+                                    first_pat = pat;
+                                    show_sugg = true;
+                                }
+                                _ => {}
+                            },
+                            PatKind::Ident(BindingMode::ByValue(Mutability::Not), ident, None) => {
+                                match &first_pat.kind {
+                                    PatKind::Ident(_, old_ident, _) => {
+                                        let path = PatKind::Path(
+                                            None,
+                                            Path {
+                                                span: new_span,
+                                                segments: vec![
+                                                    PathSegment::from_ident(old_ident.clone()),
+                                                    PathSegment::from_ident(ident.clone()),
+                                                ],
+                                                tokens: None,
+                                            },
+                                        );
+                                        first_pat = self.mk_pat(new_span, path);
+                                        show_sugg = true;
+                                    }
+                                    PatKind::Path(old_qself, old_path) => {
+                                        let mut segments = old_path.segments.clone();
+                                        segments.push(PathSegment::from_ident(ident.clone()));
+                                        let path = PatKind::Path(
+                                            old_qself.clone(),
+                                            Path { span: new_span, segments, tokens: None },
+                                        );
+                                        first_pat = self.mk_pat(new_span, path);
+                                        show_sugg = true;
+                                    }
+                                    _ => {}
+                                }
+                            }
+                            _ => {}
+                        }
+                        if show_sugg {
+                            err.span_suggestion(
+                                span,
+                                "maybe write a path separator here",
+                                "::".to_string(),
+                                Applicability::MaybeIncorrect,
+                            );
+                        } else {
+                            first_pat = self.mk_pat(new_span, PatKind::Wild);
+                        }
+                        err.emit();
+                    }
+                }
+            }
+            _ => {
+                // Carry on as if we had not done anything. This should be unreachable.
+                *self = snapshot;
+            }
+        };
+        first_pat
+    }
+
+    /// Some special error handling for the "top-level" patterns in a match arm,
+    /// `for` loop, `let`, &c. (in contrast to subpatterns within such).
+    crate fn maybe_recover_unexpected_comma(
+        &mut self,
+        lo: Span,
+        rc: RecoverComma,
+    ) -> PResult<'a, ()> {
+        if rc == RecoverComma::No || self.token != token::Comma {
+            return Ok(());
+        }
+
+        // An unexpected comma after a top-level pattern is a clue that the
+        // user (perhaps more accustomed to some other language) forgot the
+        // parentheses in what should have been a tuple pattern; return a
+        // suggestion-enhanced error here rather than choking on the comma later.
+        let comma_span = self.token.span;
+        self.bump();
+        if let Err(mut err) = self.skip_pat_list() {
+            // We didn't expect this to work anyway; we just wanted to advance to the
+            // end of the comma-sequence so we know the span to suggest parenthesizing.
+            err.cancel();
+        }
+        let seq_span = lo.to(self.prev_token.span);
+        let mut err = self.struct_span_err(comma_span, "unexpected `,` in pattern");
+        if let Ok(seq_snippet) = self.span_to_snippet(seq_span) {
+            const MSG: &str = "try adding parentheses to match on a tuple...";
+
+            err.span_suggestion(
+                seq_span,
+                MSG,
+                format!("({})", seq_snippet),
+                Applicability::MachineApplicable,
+            );
+            err.span_suggestion(
+                seq_span,
+                "...or a vertical bar to match on multiple alternatives",
+                seq_snippet.replace(",", " |"),
+                Applicability::MachineApplicable,
+            );
+        }
+        Err(err)
+    }
+
+    /// Parse and throw away a parenthesized comma separated
+    /// sequence of patterns until `)` is reached.
+    fn skip_pat_list(&mut self) -> PResult<'a, ()> {
+        while !self.check(&token::CloseDelim(token::Paren)) {
+            self.parse_pat_no_top_alt(None)?;
+            if !self.eat(&token::Comma) {
+                return Ok(());
+            }
+        }
+        Ok(())
+    }
 }
index bb3947bb47a2550bd5e82d3a633fd7c006bcbf28..ac3123c40e3d96d78190fccbb073386a8ffe31d4 100644 (file)
@@ -3,14 +3,16 @@
 use rustc_ast::mut_visit::{noop_visit_pat, MutVisitor};
 use rustc_ast::ptr::P;
 use rustc_ast::token;
-use rustc_ast::{self as ast, AttrVec, Attribute, MacCall, Pat, PatField, PatKind, RangeEnd};
-use rustc_ast::{BindingMode, Expr, ExprKind, Mutability, Path, QSelf, RangeSyntax};
+use rustc_ast::{
+    self as ast, AttrVec, Attribute, BindingMode, Expr, ExprKind, MacCall, Mutability, Pat,
+    PatField, PatKind, Path, QSelf, RangeEnd, RangeSyntax,
+};
 use rustc_ast_pretty::pprust;
 use rustc_errors::{struct_span_err, Applicability, DiagnosticBuilder, PResult};
 use rustc_span::source_map::{respan, Span, Spanned};
 use rustc_span::symbol::{kw, sym, Ident};
 
-type Expected = Option<&'static str>;
+pub(super) type Expected = Option<&'static str>;
 
 /// `Expected` for function and lambda parameter patterns.
 pub(super) const PARAM_EXPECTED: Expected = Some("parameter name");
@@ -98,55 +100,9 @@ fn parse_pat_allow_top_alt_inner(
             // If we parsed a leading `|` which should be gated,
             // then we should really gate the leading `|`.
             // This complicated procedure is done purely for diagnostics UX.
-            let mut first_pat = first_pat;
-
-            if let (RecoverColon::Yes, token::Colon) = (ra, &self.token.kind) {
-                if matches!(
-                    first_pat.kind,
-                    PatKind::Ident(BindingMode::ByValue(Mutability::Not), _, None)
-                        | PatKind::Path(..)
-                ) && self.look_ahead(1, |token| token.is_ident() && !token.is_reserved_ident())
-                {
-                    // The pattern looks like it might be a path with a `::` -> `:` typo:
-                    // `match foo { bar:baz => {} }`
-                    let span = self.token.span;
-                    // We only emit "unexpected `:`" error here if we can successfully parse the
-                    // whole pattern correctly in that case.
-                    let snapshot = self.clone();
-
-                    // Create error for "unexpected `:`".
-                    match self.expected_one_of_not_found(&[], &[]) {
-                        Err(mut err) => {
-                            self.bump(); // Skip the `:`.
-                            match self.parse_pat_no_top_alt(expected) {
-                                Err(mut inner_err) => {
-                                    // Carry on as if we had not done anything, callers will emit a
-                                    // reasonable error.
-                                    inner_err.cancel();
-                                    err.cancel();
-                                    *self = snapshot;
-                                }
-                                Ok(pat) => {
-                                    // We've parsed the rest of the pattern.
-                                    err.span_suggestion(
-                                        span,
-                                        "maybe write a path separator here",
-                                        "::".to_string(),
-                                        Applicability::MachineApplicable,
-                                    );
-                                    err.emit();
-                                    first_pat =
-                                        self.mk_pat(first_pat.span.to(pat.span), PatKind::Wild);
-                                }
-                            }
-                        }
-                        _ => {
-                            // Carry on as if we had not done anything. This should be unreachable.
-                            *self = snapshot;
-                        }
-                    };
-                }
-            }
+
+            // Check if the user wrote `foo:bar` instead of `foo::bar`.
+            let first_pat = self.maybe_recover_colon_colon_in_pat_typo(first_pat, ra, expected);
 
             if let Some(leading_vert_span) = leading_vert_span {
                 // If there was a leading vert, treat this as an or-pattern. This improves
@@ -321,57 +277,6 @@ fn ban_unexpected_or_or(&mut self, lo: Option<Span>) {
         err.emit();
     }
 
-    /// Some special error handling for the "top-level" patterns in a match arm,
-    /// `for` loop, `let`, &c. (in contrast to subpatterns within such).
-    fn maybe_recover_unexpected_comma(&mut self, lo: Span, rc: RecoverComma) -> PResult<'a, ()> {
-        if rc == RecoverComma::No || self.token != token::Comma {
-            return Ok(());
-        }
-
-        // An unexpected comma after a top-level pattern is a clue that the
-        // user (perhaps more accustomed to some other language) forgot the
-        // parentheses in what should have been a tuple pattern; return a
-        // suggestion-enhanced error here rather than choking on the comma later.
-        let comma_span = self.token.span;
-        self.bump();
-        if let Err(mut err) = self.skip_pat_list() {
-            // We didn't expect this to work anyway; we just wanted to advance to the
-            // end of the comma-sequence so we know the span to suggest parenthesizing.
-            err.cancel();
-        }
-        let seq_span = lo.to(self.prev_token.span);
-        let mut err = self.struct_span_err(comma_span, "unexpected `,` in pattern");
-        if let Ok(seq_snippet) = self.span_to_snippet(seq_span) {
-            const MSG: &str = "try adding parentheses to match on a tuple...";
-
-            err.span_suggestion(
-                seq_span,
-                MSG,
-                format!("({})", seq_snippet),
-                Applicability::MachineApplicable,
-            );
-            err.span_suggestion(
-                seq_span,
-                "...or a vertical bar to match on multiple alternatives",
-                seq_snippet.replace(",", " |"),
-                Applicability::MachineApplicable,
-            );
-        }
-        Err(err)
-    }
-
-    /// Parse and throw away a parenthesized comma separated
-    /// sequence of patterns until `)` is reached.
-    fn skip_pat_list(&mut self) -> PResult<'a, ()> {
-        while !self.check(&token::CloseDelim(token::Paren)) {
-            self.parse_pat_no_top_alt(None)?;
-            if !self.eat(&token::Comma) {
-                return Ok(());
-            }
-        }
-        Ok(())
-    }
-
     /// A `|` or possibly `||` token shouldn't be here. Ban it.
     fn ban_illegal_vert(&mut self, lo: Option<Span>, pos: &str, ctx: &str) {
         let span = self.token.span;
@@ -1168,7 +1073,7 @@ pub(super) fn mk_pat_ident(&self, span: Span, bm: BindingMode, ident: Ident) ->
         self.mk_pat(span, PatKind::Ident(bm, ident, None))
     }
 
-    fn mk_pat(&self, span: Span, kind: PatKind) -> P<Pat> {
+    pub(super) fn mk_pat(&self, span: Span, kind: PatKind) -> P<Pat> {
         P(Pat { kind, span, id: ast::DUMMY_NODE_ID, tokens: None })
     }
 }
index f761eaae5ab73652822d584ac0c4b0fd0ef7f92b..7c0b3a57da976857ede72d3871a864f93e9e7493 100644 (file)
@@ -32,7 +32,7 @@ pub(crate) fn target_from_impl_item<'tcx>(
     match impl_item.kind {
         hir::ImplItemKind::Const(..) => Target::AssocConst,
         hir::ImplItemKind::Fn(..) => {
-            let parent_hir_id = tcx.hir().get_parent_item(impl_item.hir_id());
+            let parent_hir_id = tcx.hir().get_parent_item(impl_item.hir_id()).expect_owner();
             let containing_item = tcx.hir().expect_item(parent_hir_id);
             let containing_impl_is_for_trait = match &containing_item.kind {
                 hir::ItemKind::Impl(impl_) => impl_.of_trait.is_some(),
@@ -582,7 +582,7 @@ fn check_doc_alias_value(
             Target::Impl => Some("implementation block"),
             Target::ForeignMod => Some("extern block"),
             Target::AssocTy => {
-                let parent_hir_id = self.tcx.hir().get_parent_item(hir_id);
+                let parent_hir_id = self.tcx.hir().get_parent_item(hir_id).expect_owner();
                 let containing_item = self.tcx.hir().expect_item(parent_hir_id);
                 if Target::from_item(containing_item) == Target::Impl {
                     Some("type alias in implementation block")
@@ -591,7 +591,7 @@ fn check_doc_alias_value(
                 }
             }
             Target::AssocConst => {
-                let parent_hir_id = self.tcx.hir().get_parent_item(hir_id);
+                let parent_hir_id = self.tcx.hir().get_parent_item(hir_id).expect_owner();
                 let containing_item = self.tcx.hir().expect_item(parent_hir_id);
                 // We can't link to trait impl's consts.
                 let err = "associated constant in trait implementation block";
index ff8bd37238d6bc7db187fb58509da637e6919df1..10b8c3104fcad1eba4031a54fdf9becd7e2f6c40 100644 (file)
@@ -124,12 +124,12 @@ fn visit_attribute(&mut self, _: rustc_hir::HirId, attr: &'tcx Attribute) {
     }
 }
 
-fn get_lib_features(tcx: TyCtxt<'_>, (): ()) -> LibFeatures {
+fn lib_features(tcx: TyCtxt<'_>, (): ()) -> LibFeatures {
     let mut collector = LibFeatureCollector::new(tcx);
     tcx.hir().walk_attributes(&mut collector);
     collector.lib_features
 }
 
 pub fn provide(providers: &mut Providers) {
-    providers.get_lib_features = get_lib_features;
+    providers.lib_features = lib_features;
 }
index bd1e9520ee9fe40cac3f6bae237469b21cb262df..fc56a339215bed380262090e34046a566e6c4856 100644 (file)
@@ -173,8 +173,7 @@ fn def_id_represents_local_inlined_item(&self, def_id: DefId) -> bool {
                             // Check the impl. If the generics on the self
                             // type of the impl require inlining, this method
                             // does too.
-                            let impl_hir_id = self.tcx.hir().local_def_id_to_hir_id(impl_did);
-                            match self.tcx.hir().expect_item(impl_hir_id).kind {
+                            match self.tcx.hir().expect_item(impl_did).kind {
                                 hir::ItemKind::Impl { .. } => {
                                     let generics = self.tcx.generics_of(impl_did);
                                     generics.requires_monomorphization(self.tcx)
index 6a8feb041da19f5978c4cf6055f79e127bf61ffc..ae423070392e1804d9a0baf249a976c5d20b4c58 100644 (file)
@@ -11,7 +11,7 @@
 use rustc_hir as hir;
 use rustc_hir::def_id::DefId;
 use rustc_hir::intravisit::{self, NestedVisitorMap, Visitor};
-use rustc_hir::{Arm, Block, Expr, Local, Node, Pat, PatKind, Stmt};
+use rustc_hir::{Arm, Block, Expr, Local, Pat, PatKind, Stmt};
 use rustc_index::vec::Idx;
 use rustc_middle::middle::region::*;
 use rustc_middle::ty::query::Providers;
@@ -837,19 +837,7 @@ fn region_scope_tree(tcx: TyCtxt<'_>, def_id: DefId) -> &ScopeTree {
 
         let body = tcx.hir().body(body_id);
         visitor.scope_tree.root_body = Some(body.value.hir_id);
-
-        // If the item is an associated const or a method,
-        // record its impl/trait parent, as it can also have
-        // lifetime parameters free in this body.
-        match tcx.hir().get(id) {
-            Node::ImplItem(_) | Node::TraitItem(_) => {
-                visitor.scope_tree.root_parent = Some(tcx.hir().get_parent_item(id));
-            }
-            _ => {}
-        }
-
         visitor.visit_body(body);
-
         visitor.scope_tree
     } else {
         ScopeTree::default()
index 8c9f04bef13769ac3cc65aa9da5a49283cd4d2af..92911c3cd2455c7789ad572b10f87b5d221b9f0e 100644 (file)
@@ -970,7 +970,7 @@ pub fn check_unused_or_stable_features(tcx: TyCtxt<'_>) {
 
     // We always collect the lib features declared in the current crate, even if there are
     // no unknown features, because the collection also does feature attribute validation.
-    let local_defined_features = tcx.lib_features().to_vec();
+    let local_defined_features = tcx.lib_features(()).to_vec();
     if !remaining_lib_features.is_empty() {
         check_features(&mut remaining_lib_features, &local_defined_features);
 
index 11668146f7b105560054110ed66e1c3d2cdd79f7..e3d2c9837cf51063799c52bda6db6223ab1be56e 100644 (file)
@@ -559,8 +559,7 @@ fn update_macro_reachable_def(
             // have normal  hygine, so we can treat them like other items without type
             // privacy and mark them reachable.
             DefKind::Macro(_) => {
-                let hir_id = self.tcx.hir().local_def_id_to_hir_id(def_id);
-                let item = self.tcx.hir().expect_item(hir_id);
+                let item = self.tcx.hir().expect_item(def_id);
                 if let hir::ItemKind::Macro(MacroDef { macro_rules: false, .. }) = item.kind {
                     if vis.is_accessible_from(module.to_def_id(), self.tcx) {
                         self.update(def_id, level);
@@ -581,8 +580,7 @@ fn update_macro_reachable_def(
             DefKind::Struct | DefKind::Union => {
                 // While structs and unions have type privacy, their fields do not.
                 if vis.is_public() {
-                    let item =
-                        self.tcx.hir().expect_item(self.tcx.hir().local_def_id_to_hir_id(def_id));
+                    let item = self.tcx.hir().expect_item(def_id);
                     if let hir::ItemKind::Struct(ref struct_def, _)
                     | hir::ItemKind::Union(ref struct_def, _) = item.kind
                     {
@@ -653,9 +651,7 @@ fn update_visibility_of_intermediate_use_statements(
                 // If the module is `self`, i.e. the current crate,
                 // there will be no corresponding item.
                 .filter(|def_id| def_id.index != CRATE_DEF_INDEX || def_id.krate != LOCAL_CRATE)
-                .and_then(|def_id| {
-                    def_id.as_local().map(|def_id| self.tcx.hir().local_def_id_to_hir_id(def_id))
-                })
+                .and_then(|def_id| def_id.as_local())
                 .map(|module_hir_id| self.tcx.hir().expect_item(module_hir_id))
             {
                 if let hir::ItemKind::Mod(m) = &item.kind {
index 2e4cb4ff7270d75cd451d9b0f3e3ef301667ec56..6a13627a56314f11cb9359ca9348ed8bafeae7a6 100644 (file)
@@ -1178,7 +1178,7 @@ fn lookup_import_candidates_from_module<FilterFn>(
 
     fn binding_description(&self, b: &NameBinding<'_>, ident: Ident, from_prelude: bool) -> String {
         let res = b.res();
-        if b.span.is_dummy() {
+        if b.span.is_dummy() || self.session.source_map().span_to_snippet(b.span).is_err() {
             // These already contain the "built-in" prefix or look bad with it.
             let add_built_in =
                 !matches!(b.res(), Res::NonMacroAttr(..) | Res::PrimTy(..) | Res::ToolMod);
index 39e710cb77f3fafd9129d6ad80061aea48ef3837..f9d609f9c9ce6ef6b8c47a730747aa9df7b4f5a3 100644 (file)
@@ -445,7 +445,7 @@ fn do_resolve(
     trait_definition_only: bool,
     with_scope_for_path: bool,
 ) -> NamedRegionMap {
-    let item = tcx.hir().expect_item(tcx.hir().local_def_id_to_hir_id(local_def_id));
+    let item = tcx.hir().expect_item(local_def_id);
     let mut named_region_map = NamedRegionMap {
         defs: Default::default(),
         late_bound: Default::default(),
@@ -1134,7 +1134,7 @@ fn visit_trait_item(&mut self, trait_item: &'tcx hir::TraitItem<'tcx>) {
                 self.missing_named_lifetime_spots.push((&trait_item.generics).into());
                 let tcx = self.tcx;
                 self.visit_early_late(
-                    Some(tcx.hir().get_parent_item(trait_item.hir_id())),
+                    Some(tcx.hir().get_parent_did(trait_item.hir_id())),
                     trait_item.hir_id(),
                     &sig.decl,
                     &trait_item.generics,
@@ -1203,7 +1203,7 @@ fn visit_impl_item(&mut self, impl_item: &'tcx hir::ImplItem<'tcx>) {
                 self.missing_named_lifetime_spots.push((&impl_item.generics).into());
                 let tcx = self.tcx;
                 self.visit_early_late(
-                    Some(tcx.hir().get_parent_item(impl_item.hir_id())),
+                    Some(tcx.hir().get_parent_did(impl_item.hir_id())),
                     impl_item.hir_id(),
                     &sig.decl,
                     &impl_item.generics,
@@ -2176,7 +2176,7 @@ fn check_uses_for_lifetimes_defined_by_scope(&mut self) {
     /// ordering is not important there.
     fn visit_early_late<F>(
         &mut self,
-        parent_id: Option<hir::HirId>,
+        parent_id: Option<LocalDefId>,
         hir_id: hir::HirId,
         decl: &'tcx hir::FnDecl<'tcx>,
         generics: &'tcx hir::Generics<'tcx>,
@@ -2758,7 +2758,7 @@ fn visit_fn_like_elision(
 
             Node::TraitItem(&hir::TraitItem { kind: hir::TraitItemKind::Fn(_, ref m), .. }) => {
                 if let hir::ItemKind::Trait(.., ref trait_items) =
-                    self.tcx.hir().expect_item(self.tcx.hir().get_parent_item(parent)).kind
+                    self.tcx.hir().expect_item(self.tcx.hir().get_parent_did(parent)).kind
                 {
                     assoc_item_kind =
                         trait_items.iter().find(|ti| ti.id.hir_id() == parent).map(|ti| ti.kind);
@@ -2771,7 +2771,7 @@ fn visit_fn_like_elision(
 
             Node::ImplItem(&hir::ImplItem { kind: hir::ImplItemKind::Fn(_, body), .. }) => {
                 if let hir::ItemKind::Impl(hir::Impl { ref self_ty, ref items, .. }) =
-                    self.tcx.hir().expect_item(self.tcx.hir().get_parent_item(parent)).kind
+                    self.tcx.hir().expect_item(self.tcx.hir().get_parent_did(parent)).kind
                 {
                     impl_self = Some(self_ty);
                     assoc_item_kind =
index d17e8875a1ec0d9d58354143f6189a8a9ac3927a..a8ae4736c040295a39c84686ffd3ddbef4afd832 100644 (file)
@@ -1430,12 +1430,9 @@ fn new_module(
     }
 
     pub fn next_node_id(&mut self) -> NodeId {
-        let next = self
-            .next_node_id
-            .as_usize()
-            .checked_add(1)
-            .expect("input too large; ran out of NodeIds");
-        self.next_node_id = ast::NodeId::from_usize(next);
+        let next =
+            self.next_node_id.as_u32().checked_add(1).expect("input too large; ran out of NodeIds");
+        self.next_node_id = ast::NodeId::from_u32(next);
         self.next_node_id
     }
 
index ab3c122053c5ebd777d5c65d17fbdb48dcc59118..16b68d95858b87b9c63ef82cc17def481aa69aed 100644 (file)
@@ -833,6 +833,13 @@ pub fn is_empty(&self) -> bool {
             Passes::All => false,
         }
     }
+
+    pub fn extend(&mut self, passes: impl IntoIterator<Item = String>) {
+        match *self {
+            Passes::Some(ref mut v) => v.extend(passes),
+            Passes::All => {}
+        }
+    }
 }
 
 pub const fn default_lib_output() -> CrateType {
index 4165e750df50f4bbdcf5145171d1456691796575..779f29e3dfedf32824e7b9cb558bc58e01f3436b 100644 (file)
@@ -567,7 +567,7 @@ mod parse {
             v => {
                 let mut passes = vec![];
                 if parse_list(&mut passes, v) {
-                    *slot = Passes::Some(passes);
+                    slot.extend(passes);
                     true
                 } else {
                     false
index d590776676bef53dd3067f5bc6b542a0c21fcefd..315b706fbc44ddb6583f0a412a6aea9f26385559 100644 (file)
@@ -264,7 +264,15 @@ pub fn expn_data(self) -> ExpnData {
         HygieneData::with(|data| data.expn_data(self).clone())
     }
 
+    #[inline]
     pub fn is_descendant_of(self, ancestor: ExpnId) -> bool {
+        // a few "fast path" cases to avoid locking HygieneData
+        if ancestor == ExpnId::root() || ancestor == self {
+            return true;
+        }
+        if ancestor.krate != self.krate {
+            return false;
+        }
         HygieneData::with(|data| data.is_descendant_of(self, ancestor))
     }
 
@@ -376,13 +384,22 @@ fn expn_data(&self, expn_id: ExpnId) -> &ExpnData {
     }
 
     fn is_descendant_of(&self, mut expn_id: ExpnId, ancestor: ExpnId) -> bool {
-        while expn_id != ancestor {
+        // a couple "fast path" cases to avoid traversing parents in the loop below
+        if ancestor == ExpnId::root() {
+            return true;
+        }
+        if expn_id.krate != ancestor.krate {
+            return false;
+        }
+        loop {
+            if expn_id == ancestor {
+                return true;
+            }
             if expn_id == ExpnId::root() {
                 return false;
             }
             expn_id = self.expn_data(expn_id).parent;
         }
-        true
     }
 
     fn normalize_to_macros_2_0(&self, ctxt: SyntaxContext) -> SyntaxContext {
@@ -1223,6 +1240,7 @@ pub fn register_expn_id(
     data: ExpnData,
     hash: ExpnHash,
 ) -> ExpnId {
+    debug_assert!(data.parent == ExpnId::root() || krate == data.parent.krate);
     let expn_id = ExpnId { krate, local_id };
     HygieneData::with(|hygiene_data| {
         let _old_data = hygiene_data.foreign_expn_data.insert(expn_id, data);
index 1820e33b19bf4fc0ae332bc78aeb3ab8e6359d23..ecc352c1a49b5bc5f1de2d98b30ed34212a9ac4b 100644 (file)
@@ -22,6 +22,7 @@
 #![feature(never_type)]
 #![feature(crate_visibility_modifier)]
 #![feature(control_flow_enum)]
+#![feature(unwrap_infallible)]
 #![recursion_limit = "512"] // For rustdoc
 
 #[macro_use]
index 75d57d78e3b0294be8d2138590248c775ddb6048..9052dff0aaa837514b2eadfe507eb6184c079b4e 100644 (file)
@@ -65,14 +65,16 @@ fn infer_opaque_definition_from_instantiation(
         // Convert the type from the function into a type valid outside
         // the function, by replacing invalid regions with 'static,
         // after producing an error for each of them.
-        let definition_ty = instantiated_ty.fold_with(&mut ReverseMapper::new(
-            self.tcx,
-            self.is_tainted_by_errors(),
-            def_id,
-            map,
-            instantiated_ty,
-            span,
-        ));
+        let definition_ty = instantiated_ty
+            .fold_with(&mut ReverseMapper::new(
+                self.tcx,
+                self.is_tainted_by_errors(),
+                def_id,
+                map,
+                instantiated_ty,
+                span,
+            ))
+            .into_ok();
         debug!(?definition_ty);
 
         definition_ty
@@ -123,14 +125,14 @@ fn fold_kind_mapping_missing_regions_to_empty(
     ) -> GenericArg<'tcx> {
         assert!(!self.map_missing_regions_to_empty);
         self.map_missing_regions_to_empty = true;
-        let kind = kind.fold_with(self);
+        let kind = kind.fold_with(self).into_ok();
         self.map_missing_regions_to_empty = false;
         kind
     }
 
     fn fold_kind_normally(&mut self, kind: GenericArg<'tcx>) -> GenericArg<'tcx> {
         assert!(!self.map_missing_regions_to_empty);
-        kind.fold_with(self)
+        kind.fold_with(self).into_ok()
     }
 }
 
@@ -140,17 +142,17 @@ fn tcx(&self) -> TyCtxt<'tcx> {
     }
 
     #[instrument(skip(self), level = "debug")]
-    fn fold_region(&mut self, r: ty::Region<'tcx>) -> ty::Region<'tcx> {
+    fn fold_region(&mut self, r: ty::Region<'tcx>) -> Result<ty::Region<'tcx>, Self::Error> {
         match r {
             // Ignore bound regions and `'static` regions that appear in the
             // type, we only need to remap regions that reference lifetimes
             // from the function declaraion.
             // This would ignore `'r` in a type like `for<'r> fn(&'r u32)`.
-            ty::ReLateBound(..) | ty::ReStatic => return r,
+            ty::ReLateBound(..) | ty::ReStatic => return Ok(r),
 
             // If regions have been erased (by writeback), don't try to unerase
             // them.
-            ty::ReErased => return r,
+            ty::ReErased => return Ok(r),
 
             // The regions that we expect from borrow checking.
             ty::ReEarlyBound(_) | ty::ReFree(_) | ty::ReEmpty(ty::UniverseIndex::ROOT) => {}
@@ -165,10 +167,10 @@ fn fold_region(&mut self, r: ty::Region<'tcx>) -> ty::Region<'tcx> {
 
         let generics = self.tcx().generics_of(self.opaque_type_def_id);
         match self.map.get(&r.into()).map(|k| k.unpack()) {
-            Some(GenericArgKind::Lifetime(r1)) => r1,
+            Some(GenericArgKind::Lifetime(r1)) => Ok(r1),
             Some(u) => panic!("region mapped to unexpected kind: {:?}", u),
             None if self.map_missing_regions_to_empty || self.tainted_by_errors => {
-                self.tcx.lifetimes.re_root_empty
+                Ok(self.tcx.lifetimes.re_root_empty)
             }
             None if generics.parent.is_some() => {
                 if let Some(hidden_ty) = self.hidden_ty.take() {
@@ -180,7 +182,7 @@ fn fold_region(&mut self, r: ty::Region<'tcx>) -> ty::Region<'tcx> {
                     )
                     .emit();
                 }
-                self.tcx.lifetimes.re_root_empty
+                Ok(self.tcx.lifetimes.re_root_empty)
             }
             None => {
                 self.tcx
@@ -196,12 +198,12 @@ fn fold_region(&mut self, r: ty::Region<'tcx>) -> ty::Region<'tcx> {
                     )
                     .emit();
 
-                self.tcx().lifetimes.re_static
+                Ok(self.tcx().lifetimes.re_static)
             }
         }
     }
 
-    fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> {
+    fn fold_ty(&mut self, ty: Ty<'tcx>) -> Result<Ty<'tcx>, Self::Error> {
         match *ty.kind() {
             ty::Closure(def_id, substs) => {
                 // I am a horrible monster and I pray for death. When
@@ -239,7 +241,7 @@ fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> {
                     }
                 }));
 
-                self.tcx.mk_closure(def_id, substs)
+                Ok(self.tcx.mk_closure(def_id, substs))
             }
 
             ty::Generator(def_id, substs, movability) => {
@@ -254,7 +256,7 @@ fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> {
                     }
                 }));
 
-                self.tcx.mk_generator(def_id, substs, movability)
+                Ok(self.tcx.mk_generator(def_id, substs, movability))
             }
 
             ty::Param(param) => {
@@ -262,7 +264,7 @@ fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> {
                 match self.map.get(&ty.into()).map(|k| k.unpack()) {
                     // Found it in the substitution list; replace with the parameter from the
                     // opaque type.
-                    Some(GenericArgKind::Type(t1)) => t1,
+                    Some(GenericArgKind::Type(t1)) => Ok(t1),
                     Some(u) => panic!("type mapped to unexpected kind: {:?}", u),
                     None => {
                         debug!(?param, ?self.map);
@@ -278,7 +280,7 @@ fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> {
                             )
                             .emit();
 
-                        self.tcx().ty_error()
+                        Ok(self.tcx().ty_error())
                     }
                 }
             }
@@ -287,10 +289,13 @@ fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> {
         }
     }
 
-    fn fold_const(&mut self, ct: &'tcx ty::Const<'tcx>) -> &'tcx ty::Const<'tcx> {
+    fn fold_const(
+        &mut self,
+        ct: &'tcx ty::Const<'tcx>,
+    ) -> Result<&'tcx ty::Const<'tcx>, Self::Error> {
         trace!("checking const {:?}", ct);
         // Find a const parameter
-        match ct.val {
+        Ok(match ct.val {
             ty::ConstKind::Param(..) => {
                 // Look it up in the substitution list.
                 match self.map.get(&ct.into()).map(|k| k.unpack()) {
@@ -317,7 +322,7 @@ fn fold_const(&mut self, ct: &'tcx ty::Const<'tcx>) -> &'tcx ty::Const<'tcx> {
             }
 
             _ => ct,
-        }
+        })
     }
 }
 
index 54f7b91080dd9fb0a9cae74dea7ecd43517972a5..7af32b2f3b17462867835e27194859303f7aa1f0 100644 (file)
@@ -860,11 +860,11 @@ fn tcx<'b>(&'b self) -> TyCtxt<'tcx> {
         self.tcx
     }
 
-    fn fold_region(&mut self, r: ty::Region<'tcx>) -> ty::Region<'tcx> {
-        (match r {
+    fn fold_region(&mut self, r: ty::Region<'tcx>) -> Result<ty::Region<'tcx>, Self::Error> {
+        Ok((match r {
             ty::ReVar(vid) => self.vid_to_region.get(vid).cloned(),
             _ => None,
         })
-        .unwrap_or_else(|| r.super_fold_with(self))
+        .unwrap_or_else(|| r.super_fold_with(self).into_ok()))
     }
 }
index f8df0e2595973ea54800a053bcd71a742b00bdf5..72339da571df4d7eb1b2ca56d28a7c9ad3799170 100644 (file)
@@ -539,11 +539,6 @@ fn report_selection_error(
                         // is otherwise overwhelming and unhelpful (see #85844 for an
                         // example).
 
-                        let trait_is_debug =
-                            self.tcx.is_diagnostic_item(sym::Debug, trait_ref.def_id());
-                        let trait_is_display =
-                            self.tcx.is_diagnostic_item(sym::Display, trait_ref.def_id());
-
                         let in_std_macro =
                             match obligation.cause.span.ctxt().outer_expn_data().macro_def_id {
                                 Some(macro_def_id) => {
@@ -553,7 +548,12 @@ fn report_selection_error(
                                 None => false,
                             };
 
-                        if in_std_macro && (trait_is_debug || trait_is_display) {
+                        if in_std_macro
+                            && matches!(
+                                self.tcx.get_diagnostic_name(trait_ref.def_id()),
+                                Some(sym::Debug | sym::Display)
+                            )
+                        {
                             err.emit();
                             return;
                         }
@@ -1898,15 +1898,15 @@ fn tcx<'b>(&'b self) -> TyCtxt<'tcx> {
                 self.infcx.tcx
             }
 
-            fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> {
+            fn fold_ty(&mut self, ty: Ty<'tcx>) -> Result<Ty<'tcx>, Self::Error> {
                 if let ty::Param(ty::ParamTy { name, .. }) = *ty.kind() {
                     let infcx = self.infcx;
-                    self.var_map.entry(ty).or_insert_with(|| {
+                    Ok(self.var_map.entry(ty).or_insert_with(|| {
                         infcx.next_ty_var(TypeVariableOrigin {
                             kind: TypeVariableOriginKind::TypeParameterDefinition(name, None),
                             span: DUMMY_SP,
                         })
-                    })
+                    }))
                 } else {
                     ty.super_fold_with(self)
                 }
@@ -1916,8 +1916,9 @@ fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> {
         self.probe(|_| {
             let mut selcx = SelectionContext::new(self);
 
-            let cleaned_pred =
-                pred.fold_with(&mut ParamToVarFolder { infcx: self, var_map: Default::default() });
+            let cleaned_pred = pred
+                .fold_with(&mut ParamToVarFolder { infcx: self, var_map: Default::default() })
+                .into_ok();
 
             let cleaned_pred = super::project::normalize(
                 &mut selcx,
index b8c66931cbe52ef093ce8cfb2629d29f72ec7268..0911b2c529ab25b00bc520c58cf4f1fdad1c4864 100644 (file)
@@ -339,7 +339,7 @@ fn fold<T: TypeFoldable<'tcx>>(&mut self, value: T) -> T {
         if !needs_normalization(&value, self.param_env.reveal()) {
             value
         } else {
-            value.fold_with(self)
+            value.fold_with(self).into_ok()
         }
     }
 }
@@ -352,16 +352,16 @@ fn tcx<'c>(&'c self) -> TyCtxt<'tcx> {
     fn fold_binder<T: TypeFoldable<'tcx>>(
         &mut self,
         t: ty::Binder<'tcx, T>,
-    ) -> ty::Binder<'tcx, T> {
+    ) -> Result<ty::Binder<'tcx, T>, Self::Error> {
         self.universes.push(None);
         let t = t.super_fold_with(self);
         self.universes.pop();
         t
     }
 
-    fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> {
+    fn fold_ty(&mut self, ty: Ty<'tcx>) -> Result<Ty<'tcx>, Self::Error> {
         if !needs_normalization(&ty, self.param_env.reveal()) {
-            return ty;
+            return Ok(ty);
         }
 
         // We try to be a little clever here as a performance optimization in
@@ -387,14 +387,14 @@ fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> {
         // replace bound vars if the current type is a `Projection` and we need
         // to make sure we don't forget to fold the substs regardless.
 
-        match *ty.kind() {
+        Ok(match *ty.kind() {
             // This is really important. While we *can* handle this, this has
             // severe performance implications for large opaque types with
             // late-bound regions. See `issue-88862` benchmark.
             ty::Opaque(def_id, substs) if !substs.has_escaping_bound_vars() => {
                 // Only normalize `impl Trait` after type-checking, usually in codegen.
                 match self.param_env.reveal() {
-                    Reveal::UserFacing => ty.super_fold_with(self),
+                    Reveal::UserFacing => ty.super_fold_with(self)?,
 
                     Reveal::All => {
                         let recursion_limit = self.tcx().recursion_limit();
@@ -408,11 +408,11 @@ fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> {
                             self.selcx.infcx().report_overflow_error(&obligation, true);
                         }
 
-                        let substs = substs.super_fold_with(self);
+                        let substs = substs.super_fold_with(self)?;
                         let generic_ty = self.tcx().type_of(def_id);
                         let concrete_ty = generic_ty.subst(self.tcx(), substs);
                         self.depth += 1;
-                        let folded_ty = self.fold_ty(concrete_ty);
+                        let folded_ty = self.fold_ty(concrete_ty)?;
                         self.depth -= 1;
                         folded_ty
                     }
@@ -426,7 +426,7 @@ fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> {
                 // register an obligation to *later* project, since we know
                 // there won't be bound vars there.
 
-                let data = data.super_fold_with(self);
+                let data = data.super_fold_with(self)?;
                 let normalized_ty = normalize_projection_type(
                     self.selcx,
                     self.param_env,
@@ -461,7 +461,7 @@ fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> {
                 let infcx = self.selcx.infcx();
                 let (data, mapped_regions, mapped_types, mapped_consts) =
                     BoundVarReplacer::replace_bound_vars(infcx, &mut self.universes, data);
-                let data = data.super_fold_with(self);
+                let data = data.super_fold_with(self)?;
                 let normalized_ty = opt_normalize_projection_type(
                     self.selcx,
                     self.param_env,
@@ -473,16 +473,18 @@ fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> {
                 .ok()
                 .flatten()
                 .map(|normalized_ty| {
-                    PlaceholderReplacer::replace_placeholders(
-                        infcx,
-                        mapped_regions,
-                        mapped_types,
-                        mapped_consts,
-                        &self.universes,
-                        normalized_ty,
-                    )
+                    Ok({
+                        PlaceholderReplacer::replace_placeholders(
+                            infcx,
+                            mapped_regions,
+                            mapped_types,
+                            mapped_consts,
+                            &self.universes,
+                            normalized_ty,
+                        )
+                    })
                 })
-                .unwrap_or_else(|| ty.super_fold_with(self));
+                .unwrap_or_else(|| ty.super_fold_with(self))?;
 
                 debug!(
                     ?self.depth,
@@ -494,16 +496,19 @@ fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> {
                 normalized_ty
             }
 
-            _ => ty.super_fold_with(self),
-        }
+            _ => ty.super_fold_with(self)?,
+        })
     }
 
-    fn fold_const(&mut self, constant: &'tcx ty::Const<'tcx>) -> &'tcx ty::Const<'tcx> {
+    fn fold_const(
+        &mut self,
+        constant: &'tcx ty::Const<'tcx>,
+    ) -> Result<&'tcx ty::Const<'tcx>, Self::Error> {
         if self.selcx.tcx().lazy_normalization() {
-            constant
+            Ok(constant)
         } else {
-            let constant = constant.super_fold_with(self);
-            constant.eval(self.selcx.tcx(), self.param_env)
+            let constant = constant.super_fold_with(self)?;
+            Ok(constant.eval(self.selcx.tcx(), self.param_env))
         }
     }
 }
@@ -550,7 +555,7 @@ pub fn replace_bound_vars<T: TypeFoldable<'tcx>>(
             universe_indices,
         };
 
-        let value = value.super_fold_with(&mut replacer);
+        let value = value.super_fold_with(&mut replacer).into_ok();
 
         (value, replacer.mapped_regions, replacer.mapped_types, replacer.mapped_consts)
     }
@@ -577,14 +582,14 @@ fn tcx<'b>(&'b self) -> TyCtxt<'tcx> {
     fn fold_binder<T: TypeFoldable<'tcx>>(
         &mut self,
         t: ty::Binder<'tcx, T>,
-    ) -> ty::Binder<'tcx, T> {
+    ) -> Result<ty::Binder<'tcx, T>, Self::Error> {
         self.current_index.shift_in(1);
         let t = t.super_fold_with(self);
         self.current_index.shift_out(1);
         t
     }
 
-    fn fold_region(&mut self, r: ty::Region<'tcx>) -> ty::Region<'tcx> {
+    fn fold_region(&mut self, r: ty::Region<'tcx>) -> Result<ty::Region<'tcx>, Self::Error> {
         match *r {
             ty::ReLateBound(debruijn, _)
                 if debruijn.as_usize() + 1
@@ -596,13 +601,13 @@ fn fold_region(&mut self, r: ty::Region<'tcx>) -> ty::Region<'tcx> {
                 let universe = self.universe_for(debruijn);
                 let p = ty::PlaceholderRegion { universe, name: br.kind };
                 self.mapped_regions.insert(p, br);
-                self.infcx.tcx.mk_region(ty::RePlaceholder(p))
+                Ok(self.infcx.tcx.mk_region(ty::RePlaceholder(p)))
             }
-            _ => r,
+            _ => Ok(r),
         }
     }
 
-    fn fold_ty(&mut self, t: Ty<'tcx>) -> Ty<'tcx> {
+    fn fold_ty(&mut self, t: Ty<'tcx>) -> Result<Ty<'tcx>, Self::Error> {
         match *t.kind() {
             ty::Bound(debruijn, _)
                 if debruijn.as_usize() + 1
@@ -614,14 +619,17 @@ fn fold_ty(&mut self, t: Ty<'tcx>) -> Ty<'tcx> {
                 let universe = self.universe_for(debruijn);
                 let p = ty::PlaceholderType { universe, name: bound_ty.var };
                 self.mapped_types.insert(p, bound_ty);
-                self.infcx.tcx.mk_ty(ty::Placeholder(p))
+                Ok(self.infcx.tcx.mk_ty(ty::Placeholder(p)))
             }
             _ if t.has_vars_bound_at_or_above(self.current_index) => t.super_fold_with(self),
-            _ => t,
+            _ => Ok(t),
         }
     }
 
-    fn fold_const(&mut self, ct: &'tcx ty::Const<'tcx>) -> &'tcx ty::Const<'tcx> {
+    fn fold_const(
+        &mut self,
+        ct: &'tcx ty::Const<'tcx>,
+    ) -> Result<&'tcx ty::Const<'tcx>, Self::Error> {
         match *ct {
             ty::Const { val: ty::ConstKind::Bound(debruijn, _), ty: _ }
                 if debruijn.as_usize() + 1
@@ -638,10 +646,10 @@ fn fold_const(&mut self, ct: &'tcx ty::Const<'tcx>) -> &'tcx ty::Const<'tcx> {
                     name: ty::BoundConst { var: bound_const, ty },
                 };
                 self.mapped_consts.insert(p, bound_const);
-                self.infcx.tcx.mk_const(ty::Const { val: ty::ConstKind::Placeholder(p), ty })
+                Ok(self.infcx.tcx.mk_const(ty::Const { val: ty::ConstKind::Placeholder(p), ty }))
             }
             _ if ct.has_vars_bound_at_or_above(self.current_index) => ct.super_fold_with(self),
-            _ => ct,
+            _ => Ok(ct),
         }
     }
 }
@@ -673,7 +681,7 @@ pub fn replace_placeholders<T: TypeFoldable<'tcx>>(
             universe_indices,
             current_index: ty::INNERMOST,
         };
-        value.super_fold_with(&mut replacer)
+        value.super_fold_with(&mut replacer).into_ok()
     }
 }
 
@@ -685,9 +693,9 @@ fn tcx<'b>(&'b self) -> TyCtxt<'tcx> {
     fn fold_binder<T: TypeFoldable<'tcx>>(
         &mut self,
         t: ty::Binder<'tcx, T>,
-    ) -> ty::Binder<'tcx, T> {
+    ) -> Result<ty::Binder<'tcx, T>, Self::Error> {
         if !t.has_placeholders() && !t.has_infer_regions() {
-            return t;
+            return Ok(t);
         }
         self.current_index.shift_in(1);
         let t = t.super_fold_with(self);
@@ -695,7 +703,7 @@ fn fold_binder<T: TypeFoldable<'tcx>>(
         t
     }
 
-    fn fold_region(&mut self, r0: ty::Region<'tcx>) -> ty::Region<'tcx> {
+    fn fold_region(&mut self, r0: ty::Region<'tcx>) -> Result<ty::Region<'tcx>, Self::Error> {
         let r1 = match r0 {
             ty::ReVar(_) => self
                 .infcx
@@ -729,10 +737,10 @@ fn fold_region(&mut self, r0: ty::Region<'tcx>) -> ty::Region<'tcx> {
 
         debug!(?r0, ?r1, ?r2, "fold_region");
 
-        r2
+        Ok(r2)
     }
 
-    fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> {
+    fn fold_ty(&mut self, ty: Ty<'tcx>) -> Result<Ty<'tcx>, Self::Error> {
         match *ty.kind() {
             ty::Placeholder(p) => {
                 let replace_var = self.mapped_types.get(&p);
@@ -746,18 +754,21 @@ fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> {
                         let db = ty::DebruijnIndex::from_usize(
                             self.universe_indices.len() - index + self.current_index.as_usize() - 1,
                         );
-                        self.tcx().mk_ty(ty::Bound(db, *replace_var))
+                        Ok(self.tcx().mk_ty(ty::Bound(db, *replace_var)))
                     }
-                    None => ty,
+                    None => Ok(ty),
                 }
             }
 
             _ if ty.has_placeholders() || ty.has_infer_regions() => ty.super_fold_with(self),
-            _ => ty,
+            _ => Ok(ty),
         }
     }
 
-    fn fold_const(&mut self, ct: &'tcx ty::Const<'tcx>) -> &'tcx ty::Const<'tcx> {
+    fn fold_const(
+        &mut self,
+        ct: &'tcx ty::Const<'tcx>,
+    ) -> Result<&'tcx ty::Const<'tcx>, Self::Error> {
         if let ty::Const { val: ty::ConstKind::Placeholder(p), ty } = *ct {
             let replace_var = self.mapped_consts.get(&p);
             match replace_var {
@@ -770,10 +781,11 @@ fn fold_const(&mut self, ct: &'tcx ty::Const<'tcx>) -> &'tcx ty::Const<'tcx> {
                     let db = ty::DebruijnIndex::from_usize(
                         self.universe_indices.len() - index + self.current_index.as_usize() - 1,
                     );
-                    self.tcx()
-                        .mk_const(ty::Const { val: ty::ConstKind::Bound(db, *replace_var), ty })
+                    Ok(self
+                        .tcx()
+                        .mk_const(ty::Const { val: ty::ConstKind::Bound(db, *replace_var), ty }))
                 }
-                None => ct,
+                None => Ok(ct),
             }
         } else {
             ct.super_fold_with(self)
@@ -1534,7 +1546,8 @@ fn confirm_candidate<'cx, 'tcx>(
     // when possible for this to work. See `auto-trait-projection-recursion.rs`
     // for a case where this matters.
     if progress.ty.has_infer_regions() {
-        progress.ty = OpportunisticRegionResolver::new(selcx.infcx()).fold_ty(progress.ty);
+        progress.ty =
+            OpportunisticRegionResolver::new(selcx.infcx()).fold_ty(progress.ty).into_ok();
     }
     progress
 }
index 1364cf1c9953512f925106e382f141a3bc893a5d..af507feffba5b5ed615b24f7dac83074c41166d2 100644 (file)
@@ -61,7 +61,6 @@ fn normalize<T>(&self, value: T) -> Result<Normalized<'tcx, T>, NoSolution>
             cause: self.cause,
             param_env: self.param_env,
             obligations: vec![],
-            error: false,
             cache: SsoHashMap::new(),
             anon_depth: 0,
             universes: vec![],
@@ -100,11 +99,7 @@ fn normalize<T>(&self, value: T) -> Result<Normalized<'tcx, T>, NoSolution>
             std::any::type_name::<T>(),
             normalizer.obligations,
         );
-        if normalizer.error {
-            Err(NoSolution)
-        } else {
-            Ok(Normalized { value: result, obligations: normalizer.obligations })
-        }
+        result.map(|value| Normalized { value, obligations: normalizer.obligations })
     }
 }
 
@@ -171,12 +166,13 @@ struct QueryNormalizer<'cx, 'tcx> {
     param_env: ty::ParamEnv<'tcx>,
     obligations: Vec<PredicateObligation<'tcx>>,
     cache: SsoHashMap<Ty<'tcx>, Ty<'tcx>>,
-    error: bool,
     anon_depth: usize,
     universes: Vec<Option<ty::UniverseIndex>>,
 }
 
 impl<'cx, 'tcx> TypeFolder<'tcx> for QueryNormalizer<'cx, 'tcx> {
+    type Error = NoSolution;
+
     fn tcx<'c>(&'c self) -> TyCtxt<'tcx> {
         self.infcx.tcx
     }
@@ -184,7 +180,7 @@ fn tcx<'c>(&'c self) -> TyCtxt<'tcx> {
     fn fold_binder<T: TypeFoldable<'tcx>>(
         &mut self,
         t: ty::Binder<'tcx, T>,
-    ) -> ty::Binder<'tcx, T> {
+    ) -> Result<ty::Binder<'tcx, T>, Self::Error> {
         self.universes.push(None);
         let t = t.super_fold_with(self);
         self.universes.pop();
@@ -192,13 +188,13 @@ fn fold_binder<T: TypeFoldable<'tcx>>(
     }
 
     #[instrument(level = "debug", skip(self))]
-    fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> {
+    fn fold_ty(&mut self, ty: Ty<'tcx>) -> Result<Ty<'tcx>, Self::Error> {
         if !needs_normalization(&ty, self.param_env.reveal()) {
-            return ty;
+            return Ok(ty);
         }
 
         if let Some(ty) = self.cache.get(&ty) {
-            return ty;
+            return Ok(ty);
         }
 
         // See note in `rustc_trait_selection::traits::project` about why we
@@ -215,7 +211,7 @@ fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> {
                     Reveal::UserFacing => ty.super_fold_with(self),
 
                     Reveal::All => {
-                        let substs = substs.super_fold_with(self);
+                        let substs = substs.super_fold_with(self)?;
                         let recursion_limit = self.tcx().recursion_limit();
                         if !recursion_limit.value_within_limit(self.anon_depth) {
                             let obligation = Obligation::with_depth(
@@ -252,7 +248,7 @@ fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> {
                 // we don't need to replace them with placeholders (see branch below).
 
                 let tcx = self.infcx.tcx;
-                let data = data.super_fold_with(self);
+                let data = data.super_fold_with(self)?;
 
                 let mut orig_values = OriginalQueryValues::default();
                 // HACK(matthewjasper) `'static` is special-cased in selection,
@@ -262,39 +258,22 @@ fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> {
                     .canonicalize_query_keep_static(self.param_env.and(data), &mut orig_values);
                 debug!("QueryNormalizer: c_data = {:#?}", c_data);
                 debug!("QueryNormalizer: orig_values = {:#?}", orig_values);
-                match tcx.normalize_projection_ty(c_data) {
-                    Ok(result) => {
-                        // We don't expect ambiguity.
-                        if result.is_ambiguous() {
-                            self.error = true;
-                            return ty.super_fold_with(self);
-                        }
-
-                        match self.infcx.instantiate_query_response_and_region_obligations(
-                            self.cause,
-                            self.param_env,
-                            &orig_values,
-                            result,
-                        ) {
-                            Ok(InferOk { value: result, obligations }) => {
-                                debug!("QueryNormalizer: result = {:#?}", result);
-                                debug!("QueryNormalizer: obligations = {:#?}", obligations);
-                                self.obligations.extend(obligations);
-                                result.normalized_ty
-                            }
-
-                            Err(_) => {
-                                self.error = true;
-                                ty.super_fold_with(self)
-                            }
-                        }
-                    }
-
-                    Err(NoSolution) => {
-                        self.error = true;
-                        ty.super_fold_with(self)
-                    }
+                let result = tcx.normalize_projection_ty(c_data)?;
+                // We don't expect ambiguity.
+                if result.is_ambiguous() {
+                    return Err(NoSolution);
                 }
+                let InferOk { value: result, obligations } =
+                    self.infcx.instantiate_query_response_and_region_obligations(
+                        self.cause,
+                        self.param_env,
+                        &orig_values,
+                        result,
+                    )?;
+                debug!("QueryNormalizer: result = {:#?}", result);
+                debug!("QueryNormalizer: obligations = {:#?}", obligations);
+                self.obligations.extend(obligations);
+                Ok(result.normalized_ty)
             }
 
             ty::Projection(data) => {
@@ -308,7 +287,7 @@ fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> {
                         &mut self.universes,
                         data,
                     );
-                let data = data.super_fold_with(self);
+                let data = data.super_fold_with(self)?;
 
                 let mut orig_values = OriginalQueryValues::default();
                 // HACK(matthewjasper) `'static` is special-cased in selection,
@@ -318,57 +297,49 @@ fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> {
                     .canonicalize_query_keep_static(self.param_env.and(data), &mut orig_values);
                 debug!("QueryNormalizer: c_data = {:#?}", c_data);
                 debug!("QueryNormalizer: orig_values = {:#?}", orig_values);
-                match tcx.normalize_projection_ty(c_data) {
-                    Ok(result) => {
-                        // We don't expect ambiguity.
-                        if result.is_ambiguous() {
-                            self.error = true;
-                            return ty.super_fold_with(self);
-                        }
-                        match self.infcx.instantiate_query_response_and_region_obligations(
-                            self.cause,
-                            self.param_env,
-                            &orig_values,
-                            result,
-                        ) {
-                            Ok(InferOk { value: result, obligations }) => {
-                                debug!("QueryNormalizer: result = {:#?}", result);
-                                debug!("QueryNormalizer: obligations = {:#?}", obligations);
-                                self.obligations.extend(obligations);
-                                crate::traits::project::PlaceholderReplacer::replace_placeholders(
-                                    infcx,
-                                    mapped_regions,
-                                    mapped_types,
-                                    mapped_consts,
-                                    &self.universes,
-                                    result.normalized_ty,
-                                )
-                            }
-                            Err(_) => {
-                                self.error = true;
-                                ty.super_fold_with(self)
-                            }
-                        }
-                    }
-                    Err(NoSolution) => {
-                        self.error = true;
-                        ty.super_fold_with(self)
-                    }
+                let result = tcx.normalize_projection_ty(c_data)?;
+                // We don't expect ambiguity.
+                if result.is_ambiguous() {
+                    return Err(NoSolution);
                 }
+                let InferOk { value: result, obligations } =
+                    self.infcx.instantiate_query_response_and_region_obligations(
+                        self.cause,
+                        self.param_env,
+                        &orig_values,
+                        result,
+                    )?;
+                debug!("QueryNormalizer: result = {:#?}", result);
+                debug!("QueryNormalizer: obligations = {:#?}", obligations);
+                self.obligations.extend(obligations);
+                Ok(crate::traits::project::PlaceholderReplacer::replace_placeholders(
+                    infcx,
+                    mapped_regions,
+                    mapped_types,
+                    mapped_consts,
+                    &self.universes,
+                    result.normalized_ty,
+                ))
             }
 
             _ => ty.super_fold_with(self),
-        })();
+        })()?;
         self.cache.insert(ty, res);
-        res
+        Ok(res)
     }
 
-    fn fold_const(&mut self, constant: &'tcx ty::Const<'tcx>) -> &'tcx ty::Const<'tcx> {
-        let constant = constant.super_fold_with(self);
-        constant.eval(self.infcx.tcx, self.param_env)
+    fn fold_const(
+        &mut self,
+        constant: &'tcx ty::Const<'tcx>,
+    ) -> Result<&'tcx ty::Const<'tcx>, Self::Error> {
+        let constant = constant.super_fold_with(self)?;
+        Ok(constant.eval(self.infcx.tcx, self.param_env))
     }
 
-    fn fold_mir_const(&mut self, constant: mir::ConstantKind<'tcx>) -> mir::ConstantKind<'tcx> {
+    fn fold_mir_const(
+        &mut self,
+        constant: mir::ConstantKind<'tcx>,
+    ) -> Result<mir::ConstantKind<'tcx>, Self::Error> {
         constant.super_fold_with(self)
     }
 }
index 0ff3611f8f80d61ef1ef25ed69906bc6d2e0fb83..6e3e3b9b14480d383fdad71dd9a6829647b5b61f 100644 (file)
@@ -536,7 +536,10 @@ fn assemble_candidates_from_impls(
         // This helps us avoid overflow: see issue #72839
         // Since compilation is already guaranteed to fail, this is just
         // to try to show the 'nicest' possible errors to the user.
-        if obligation.references_error() {
+        // We don't check for errors in the `ParamEnv` - in practice,
+        // it seems to cause us to be overly aggressive in deciding
+        // to give up searching for candidates, leading to spurious errors.
+        if obligation.predicate.references_error() {
             return;
         }
 
index 2aa214694cb1472cd54827befdd2ee2b50a0b7d9..767cb1618bb67d35239db630af41e98e8bad37e3 100644 (file)
@@ -2222,6 +2222,7 @@ fn push_stack<'o>(
             .predicate
             .to_poly_trait_ref()
             .fold_with(&mut self.freshener)
+            .into_ok()
             .with_constness(obligation.predicate.skip_binder().constness);
 
         let dfn = previous_stack.cache.next_dfn();
index 1d457d6761fd084c1e0c7bab1c98ba5f0746921b..fdff07302c2407fbe7e8c72c5844870e5f1b715d 100644 (file)
@@ -45,7 +45,7 @@ fn where_clauses_for(
         predicates
             .iter()
             .map(|(wc, _)| wc.subst(self.interner.tcx, bound_vars))
-            .map(|wc| wc.fold_with(&mut regions_substitutor))
+            .map(|wc| wc.fold_with(&mut regions_substitutor).into_ok())
             .filter_map(|wc| LowerInto::<Option<chalk_ir::QuantifiedWhereClause<RustInterner<'tcx>>>>::lower_into(wc, &self.interner)).collect()
     }
 
@@ -287,7 +287,7 @@ fn impl_datum(
         let trait_ref = trait_ref.subst(self.interner.tcx, bound_vars);
         let mut regions_substitutor =
             lowering::RegionsSubstitutor::new(self.interner.tcx, self.reempty_placeholder);
-        let trait_ref = trait_ref.fold_with(&mut regions_substitutor);
+        let trait_ref = trait_ref.fold_with(&mut regions_substitutor).into_ok();
 
         let where_clauses = self.where_clauses_for(def_id, bound_vars);
 
@@ -335,7 +335,7 @@ fn impls_for_trait(
             let self_ty = self_ty.subst(self.interner.tcx, bound_vars);
             let mut regions_substitutor =
                 lowering::RegionsSubstitutor::new(self.interner.tcx, self.reempty_placeholder);
-            let self_ty = self_ty.fold_with(&mut regions_substitutor);
+            let self_ty = self_ty.fold_with(&mut regions_substitutor).into_ok();
             let lowered_ty = self_ty.lower_into(&self.interner);
 
             parameters[0].assert_ty_ref(&self.interner).could_match(
@@ -501,22 +501,24 @@ fn opaque_ty_data(
                 .iter()
                 .map(|(bound, _)| bound.subst(self.interner.tcx, &bound_vars))
                 .map(|bound| {
-                    bound.fold_with(&mut ty::fold::BottomUpFolder {
-                        tcx: self.interner.tcx,
-                        ty_op: |ty| {
-                            if let ty::Opaque(def_id, substs) = *ty.kind() {
-                                if def_id == opaque_ty_id.0 && substs == identity_substs {
-                                    return self.interner.tcx.mk_ty(ty::Bound(
-                                        ty::INNERMOST,
-                                        ty::BoundTy::from(ty::BoundVar::from_u32(0)),
-                                    ));
+                    bound
+                        .fold_with(&mut ty::fold::BottomUpFolder {
+                            tcx: self.interner.tcx,
+                            ty_op: |ty| {
+                                if let ty::Opaque(def_id, substs) = *ty.kind() {
+                                    if def_id == opaque_ty_id.0 && substs == identity_substs {
+                                        return self.interner.tcx.mk_ty(ty::Bound(
+                                            ty::INNERMOST,
+                                            ty::BoundTy::from(ty::BoundVar::from_u32(0)),
+                                        ));
+                                    }
                                 }
-                            }
-                            ty
-                        },
-                        lt_op: |lt| lt,
-                        ct_op: |ct| ct,
-                    })
+                                ty
+                            },
+                            lt_op: |lt| lt,
+                            ct_op: |ct| ct,
+                        })
+                        .into_ok()
                 })
                 .filter_map(|bound| {
                     LowerInto::<
index e24f699adf6b398d9ec8ee263fa037f6a532752f..66073facf4b0c1f10bfa59e3ed2ea39ac1053c25 100644 (file)
@@ -817,7 +817,7 @@ fn lower_into(
         .collect();
 
     let mut bound_var_substitutor = NamedBoundVarSubstitutor::new(tcx, &named_parameters);
-    let new_ty = ty.skip_binder().fold_with(&mut bound_var_substitutor);
+    let new_ty = ty.skip_binder().fold_with(&mut bound_var_substitutor).into_ok();
 
     for var in named_parameters.values() {
         parameters.insert(*var, chalk_ir::VariableKind::Lifetime);
@@ -943,20 +943,23 @@ fn tcx<'b>(&'b self) -> TyCtxt<'tcx> {
         self.tcx
     }
 
-    fn fold_binder<T: TypeFoldable<'tcx>>(&mut self, t: Binder<'tcx, T>) -> Binder<'tcx, T> {
+    fn fold_binder<T: TypeFoldable<'tcx>>(
+        &mut self,
+        t: Binder<'tcx, T>,
+    ) -> Result<Binder<'tcx, T>, Self::Error> {
         self.binder_index.shift_in(1);
         let result = t.super_fold_with(self);
         self.binder_index.shift_out(1);
         result
     }
 
-    fn fold_region(&mut self, r: Region<'tcx>) -> Region<'tcx> {
+    fn fold_region(&mut self, r: Region<'tcx>) -> Result<Region<'tcx>, Self::Error> {
         match r {
             ty::ReLateBound(index, br) if *index == self.binder_index => match br.kind {
                 ty::BrNamed(def_id, _name) => match self.named_parameters.get(&def_id) {
                     Some(idx) => {
                         let new_br = ty::BoundRegion { var: br.var, kind: ty::BrAnon(*idx) };
-                        return self.tcx.mk_region(RegionKind::ReLateBound(*index, new_br));
+                        return Ok(self.tcx.mk_region(RegionKind::ReLateBound(*index, new_br)));
                     }
                     None => panic!("Missing `BrNamed`."),
                 },
@@ -999,32 +1002,35 @@ fn tcx<'b>(&'b self) -> TyCtxt<'tcx> {
         self.tcx
     }
 
-    fn fold_binder<T: TypeFoldable<'tcx>>(&mut self, t: Binder<'tcx, T>) -> Binder<'tcx, T> {
+    fn fold_binder<T: TypeFoldable<'tcx>>(
+        &mut self,
+        t: Binder<'tcx, T>,
+    ) -> Result<Binder<'tcx, T>, Self::Error> {
         self.binder_index.shift_in(1);
         let result = t.super_fold_with(self);
         self.binder_index.shift_out(1);
         result
     }
 
-    fn fold_ty(&mut self, t: Ty<'tcx>) -> Ty<'tcx> {
+    fn fold_ty(&mut self, t: Ty<'tcx>) -> Result<Ty<'tcx>, Self::Error> {
         match *t.kind() {
             // FIXME(chalk): currently we convert params to placeholders starting at
             // index `0`. To support placeholders, we'll actually need to do a
             // first pass to collect placeholders. Then we can insert params after.
             ty::Placeholder(_) => unimplemented!(),
             ty::Param(param) => match self.list.iter().position(|r| r == &param) {
-                Some(idx) => self.tcx.mk_ty(ty::Placeholder(ty::PlaceholderType {
+                Some(idx) => Ok(self.tcx.mk_ty(ty::Placeholder(ty::PlaceholderType {
                     universe: ty::UniverseIndex::from_usize(0),
                     name: ty::BoundVar::from_usize(idx),
-                })),
+                }))),
                 None => {
                     self.list.push(param);
                     let idx = self.list.len() - 1 + self.next_ty_placeholder;
                     self.params.insert(idx, param);
-                    self.tcx.mk_ty(ty::Placeholder(ty::PlaceholderType {
+                    Ok(self.tcx.mk_ty(ty::Placeholder(ty::PlaceholderType {
                         universe: ty::UniverseIndex::from_usize(0),
                         name: ty::BoundVar::from_usize(idx),
-                    }))
+                    })))
                 }
             },
 
@@ -1032,7 +1038,7 @@ fn fold_ty(&mut self, t: Ty<'tcx>) -> Ty<'tcx> {
         }
     }
 
-    fn fold_region(&mut self, r: Region<'tcx>) -> Region<'tcx> {
+    fn fold_region(&mut self, r: Region<'tcx>) -> Result<Region<'tcx>, Self::Error> {
         match r {
             // FIXME(chalk) - jackh726 - this currently isn't hit in any tests.
             // This covers any region variables in a goal, right?
@@ -1042,14 +1048,14 @@ fn fold_region(&mut self, r: Region<'tcx>) -> Region<'tcx> {
                         var: ty::BoundVar::from_u32(*idx),
                         kind: ty::BrAnon(*idx),
                     };
-                    self.tcx.mk_region(RegionKind::ReLateBound(self.binder_index, br))
+                    Ok(self.tcx.mk_region(RegionKind::ReLateBound(self.binder_index, br)))
                 }
                 None => {
                     let idx = self.named_regions.len() as u32;
                     let br =
                         ty::BoundRegion { var: ty::BoundVar::from_u32(idx), kind: ty::BrAnon(idx) };
                     self.named_regions.insert(_re.def_id, idx);
-                    self.tcx.mk_region(RegionKind::ReLateBound(self.binder_index, br))
+                    Ok(self.tcx.mk_region(RegionKind::ReLateBound(self.binder_index, br)))
                 }
             },
 
@@ -1125,11 +1131,11 @@ fn tcx<'b>(&'b self) -> TyCtxt<'tcx> {
         self.tcx
     }
 
-    fn fold_region(&mut self, r: Region<'tcx>) -> Region<'tcx> {
+    fn fold_region(&mut self, r: Region<'tcx>) -> Result<Region<'tcx>, Self::Error> {
         match r {
             ty::ReEmpty(ui) => {
                 assert_eq!(ui.as_usize(), 0);
-                self.reempty_placeholder
+                Ok(self.reempty_placeholder)
             }
 
             _ => r.super_fold_with(self),
index b7275bac19048f701feeae31fb0f31654a51bf7a..a6f7c4d7988f697ed0fb37dd39c5cdcd5d04b20e 100644 (file)
 
     let mut params_substitutor =
         ParamsSubstitutor::new(tcx, placeholders_collector.next_ty_placeholder);
-    let obligation = obligation.fold_with(&mut params_substitutor);
+    let obligation = obligation.fold_with(&mut params_substitutor).into_ok();
     // FIXME(chalk): we really should be substituting these back in the solution
     let _params: FxHashMap<usize, ParamTy> = params_substitutor.params;
 
     let mut regions_substitutor = RegionsSubstitutor::new(tcx, reempty_placeholder);
-    let obligation = obligation.fold_with(&mut regions_substitutor);
+    let obligation = obligation.fold_with(&mut regions_substitutor).into_ok();
 
     let max_universe = obligation.max_universe.index();
 
index 8612499623be628ea17c66230ed0cc2af5b3dd0a..ea70a8d9e3a0d30fd9504f496e21b3cebee49669 100644 (file)
@@ -4,6 +4,7 @@
 #![feature(crate_visibility_modifier)]
 #![feature(in_band_lifetimes)]
 #![feature(nll)]
+#![feature(unwrap_infallible)]
 #![recursion_limit = "256"]
 
 #[macro_use]
index 61ab5e28b6796151eabdf015a72abfc247aa0a41..4f35909df7f6a8d1ff200a93dad4dcbc21fe5b2c 100644 (file)
         normalize_mir_const_after_erasing_regions: |tcx, goal| {
             normalize_after_erasing_regions(tcx, goal)
         },
+        try_normalize_generic_arg_after_erasing_regions: |tcx, goal| {
+            debug!("try_normalize_generic_arg_after_erasing_regions(goal={:#?}", goal);
+
+            try_normalize_after_erasing_regions(tcx, goal)
+        },
+        try_normalize_mir_const_after_erasing_regions: |tcx, goal| {
+            try_normalize_after_erasing_regions(tcx, goal)
+        },
         ..*p
     };
 }
@@ -56,6 +64,38 @@ fn normalize_after_erasing_regions<'tcx, T: TypeFoldable<'tcx> + PartialEq + Cop
     })
 }
 
+#[instrument(level = "debug", skip(tcx))]
+fn try_normalize_after_erasing_regions<'tcx, T: TypeFoldable<'tcx> + PartialEq + Copy>(
+    tcx: TyCtxt<'tcx>,
+    goal: ParamEnvAnd<'tcx, T>,
+) -> Result<T, NoSolution> {
+    let ParamEnvAnd { param_env, value } = goal;
+    tcx.infer_ctxt().enter(|infcx| {
+        let cause = ObligationCause::dummy();
+        match infcx.at(&cause, param_env).normalize(value) {
+            Ok(Normalized { value: normalized_value, obligations: normalized_obligations }) => {
+                // We don't care about the `obligations`; they are
+                // always only region relations, and we are about to
+                // erase those anyway:
+                debug_assert_eq!(
+                    normalized_obligations.iter().find(|p| not_outlives_predicate(&p.predicate)),
+                    None,
+                );
+
+                let resolved_value = infcx.resolve_vars_if_possible(normalized_value);
+                // It's unclear when `resolve_vars` would have an effect in a
+                // fresh `InferCtxt`. If this assert does trigger, it will give
+                // us a test case.
+                debug_assert_eq!(normalized_value, resolved_value);
+                let erased = infcx.tcx.erase_regions(resolved_value);
+                debug_assert!(!erased.needs_infer(), "{:?}", erased);
+                Ok(erased)
+            }
+            Err(NoSolution) => Err(NoSolution),
+        }
+    })
+}
+
 fn not_outlives_predicate(p: &ty::Predicate<'tcx>) -> bool {
     match p.kind().skip_binder() {
         ty::PredicateKind::RegionOutlives(..) | ty::PredicateKind::TypeOutlives(..) => false,
index af3706f886e9cbce53fb4e6be54c5ee1872432e4..711a6f2fbebdd44d792d736b2a5e32704a6234e4 100644 (file)
@@ -123,7 +123,7 @@ fn associated_item(tcx: TyCtxt<'_>, def_id: DefId) -> ty::AssocItem {
     let id = tcx.hir().local_def_id_to_hir_id(def_id.expect_local());
     let parent_id = tcx.hir().get_parent_item(id);
     let parent_def_id = tcx.hir().local_def_id(parent_id);
-    let parent_item = tcx.hir().expect_item(parent_id);
+    let parent_item = tcx.hir().expect_item(parent_def_id);
     match parent_item.kind {
         hir::ItemKind::Impl(ref impl_) => {
             if let Some(impl_item_ref) =
@@ -158,8 +158,7 @@ fn associated_item(tcx: TyCtxt<'_>, def_id: DefId) -> ty::AssocItem {
 }
 
 fn impl_defaultness(tcx: TyCtxt<'_>, def_id: DefId) -> hir::Defaultness {
-    let hir_id = tcx.hir().local_def_id_to_hir_id(def_id.expect_local());
-    let item = tcx.hir().expect_item(hir_id);
+    let item = tcx.hir().expect_item(def_id.expect_local());
     if let hir::ItemKind::Impl(impl_) = &item.kind {
         impl_.defaultness
     } else {
@@ -168,8 +167,7 @@ fn impl_defaultness(tcx: TyCtxt<'_>, def_id: DefId) -> hir::Defaultness {
 }
 
 fn impl_constness(tcx: TyCtxt<'_>, def_id: DefId) -> hir::Constness {
-    let hir_id = tcx.hir().local_def_id_to_hir_id(def_id.expect_local());
-    let item = tcx.hir().expect_item(hir_id);
+    let item = tcx.hir().expect_item(def_id.expect_local());
     if let hir::ItemKind::Impl(impl_) = &item.kind {
         impl_.constness
     } else {
@@ -202,8 +200,7 @@ fn adt_sized_constraint(tcx: TyCtxt<'_>, def_id: DefId) -> ty::AdtSizedConstrain
 }
 
 fn associated_item_def_ids(tcx: TyCtxt<'_>, def_id: DefId) -> &[DefId] {
-    let id = tcx.hir().local_def_id_to_hir_id(def_id.expect_local());
-    let item = tcx.hir().expect_item(id);
+    let item = tcx.hir().expect_item(def_id.expect_local());
     match item.kind {
         hir::ItemKind::Trait(.., ref trait_item_refs) => tcx.arena.alloc_from_iter(
             trait_item_refs.iter().map(|trait_item_ref| trait_item_ref.id.def_id.to_def_id()),
index bb1d9744e66fe068447885de77b80c62f789339a..2061f955d968fb9258877e17167976d376d8416a 100644 (file)
@@ -458,7 +458,7 @@ pub(super) fn check_opaque_for_inheriting_lifetimes(
     def_id: LocalDefId,
     span: Span,
 ) {
-    let item = tcx.hir().expect_item(tcx.hir().local_def_id_to_hir_id(def_id));
+    let item = tcx.hir().expect_item(def_id);
     debug!(?item, ?span);
 
     struct FoundParentLifetime;
index 77f7cccc04ba4fe5a5fa0995f8530454b39cea63..9912d4b39586c05ce2cf112f857fc5de67590be0 100644 (file)
@@ -1637,11 +1637,10 @@ fn add_impl_trait_explanation<'a>(
                 let ty = <dyn AstConv<'_>>::ast_ty_to_ty(fcx, ty);
                 // Get the `impl Trait`'s `DefId`.
                 if let ty::Opaque(def_id, _) = ty.kind() {
-                    let hir_id = fcx.tcx.hir().local_def_id_to_hir_id(def_id.expect_local());
                     // Get the `impl Trait`'s `Item` so that we can get its trait bounds and
                     // get the `Trait`'s `DefId`.
                     if let hir::ItemKind::OpaqueTy(hir::OpaqueTy { bounds, .. }) =
-                        fcx.tcx.hir().expect_item(hir_id).kind
+                        fcx.tcx.hir().expect_item(def_id.expect_local()).kind
                     {
                         // Are of this `impl Trait`'s traits object safe?
                         is_object_safe = bounds.iter().all(|bound| {
index 4d4662f73a9556023a59408bb35103ec7563856c..44fc81a889d1732b404cee3674066f1e1f2744e4 100644 (file)
@@ -264,14 +264,9 @@ fn compare_predicate_entailment<'tcx>(
         // First liberate late bound regions and subst placeholders
         let trait_sig = tcx.liberate_late_bound_regions(impl_m.def_id, tcx.fn_sig(trait_m.def_id));
         let trait_sig = trait_sig.subst(tcx, trait_to_placeholder_substs);
-        // Next, add all inputs and output as well-formed tys. Importantly,
-        // we have to do this before normalization, since the normalized ty may
-        // not contain the input parameters. See issue #87748.
-        wf_tys.extend(trait_sig.inputs_and_output.iter());
         let trait_sig =
             inh.normalize_associated_types_in(impl_m_span, impl_m_hir_id, param_env, trait_sig);
-        // Also add the resulting inputs and output as well-formed.
-        // This probably isn't strictly necessary.
+        // Add the resulting inputs and output as well-formed.
         wf_tys.extend(trait_sig.inputs_and_output.iter());
         let trait_fty = tcx.mk_fn_ptr(ty::Binder::dummy(trait_sig));
 
@@ -322,9 +317,7 @@ fn compare_predicate_entailment<'tcx>(
                     // When the `impl` receiver is an arbitrary self type, like `self: Box<Self>`, the
                     // span points only at the type `Box<Self`>, but we want to cover the whole
                     // argument pattern and type.
-                    let impl_m_hir_id =
-                        tcx.hir().local_def_id_to_hir_id(impl_m.def_id.expect_local());
-                    let span = match tcx.hir().expect_impl_item(impl_m_hir_id).kind {
+                    let span = match tcx.hir().expect_impl_item(impl_m.def_id.expect_local()).kind {
                         ImplItemKind::Fn(ref sig, body) => tcx
                             .hir()
                             .body_param_names(body)
@@ -346,9 +339,7 @@ fn compare_predicate_entailment<'tcx>(
                     if trait_sig.inputs().len() == *i {
                         // Suggestion to change output type. We do not suggest in `async` functions
                         // to avoid complex logic or incorrect output.
-                        let impl_m_hir_id =
-                            tcx.hir().local_def_id_to_hir_id(impl_m.def_id.expect_local());
-                        match tcx.hir().expect_impl_item(impl_m_hir_id).kind {
+                        match tcx.hir().expect_impl_item(impl_m.def_id.expect_local()).kind {
                             ImplItemKind::Fn(ref sig, _)
                                 if sig.header.asyncness == hir::IsAsync::NotAsync =>
                             {
@@ -467,22 +458,19 @@ fn extract_spans_for_error_reporting<'a, 'tcx>(
     trait_m: &ty::AssocItem,
 ) -> (Span, Option<Span>) {
     let tcx = infcx.tcx;
-    let impl_m_hir_id = tcx.hir().local_def_id_to_hir_id(impl_m.def_id.expect_local());
-    let mut impl_args = match tcx.hir().expect_impl_item(impl_m_hir_id).kind {
+    let mut impl_args = match tcx.hir().expect_impl_item(impl_m.def_id.expect_local()).kind {
         ImplItemKind::Fn(ref sig, _) => {
             sig.decl.inputs.iter().map(|t| t.span).chain(iter::once(sig.decl.output.span()))
         }
         _ => bug!("{:?} is not a method", impl_m),
     };
-    let trait_args = trait_m.def_id.as_local().map(|def_id| {
-        let trait_m_hir_id = tcx.hir().local_def_id_to_hir_id(def_id);
-        match tcx.hir().expect_trait_item(trait_m_hir_id).kind {
+    let trait_args =
+        trait_m.def_id.as_local().map(|def_id| match tcx.hir().expect_trait_item(def_id).kind {
             TraitItemKind::Fn(ref sig, _) => {
                 sig.decl.inputs.iter().map(|t| t.span).chain(iter::once(sig.decl.output.span()))
             }
             _ => bug!("{:?} is not a TraitItemKind::Fn", trait_m),
-        }
-    });
+        });
 
     match *terr {
         TypeError::ArgumentMutability(i) => {
@@ -600,8 +588,7 @@ fn compare_number_of_generics<'tcx>(
             err_occurred = true;
 
             let (trait_spans, impl_trait_spans) = if let Some(def_id) = trait_.def_id.as_local() {
-                let trait_hir_id = tcx.hir().local_def_id_to_hir_id(def_id);
-                let trait_item = tcx.hir().expect_trait_item(trait_hir_id);
+                let trait_item = tcx.hir().expect_trait_item(def_id);
                 if trait_item.generics.params.is_empty() {
                     (Some(vec![trait_item.generics.span]), vec![])
                 } else {
@@ -622,8 +609,7 @@ fn compare_number_of_generics<'tcx>(
                 (trait_span.map(|s| vec![s]), vec![])
             };
 
-            let impl_hir_id = tcx.hir().local_def_id_to_hir_id(impl_.def_id.expect_local());
-            let impl_item = tcx.hir().expect_impl_item(impl_hir_id);
+            let impl_item = tcx.hir().expect_impl_item(impl_.def_id.expect_local());
             let impl_item_impl_trait_spans: Vec<Span> = impl_item
                 .generics
                 .params
@@ -711,8 +697,7 @@ fn compare_number_of_method_arguments<'tcx>(
     let impl_number_args = impl_m_fty.inputs().skip_binder().len();
     if trait_number_args != impl_number_args {
         let trait_span = if let Some(def_id) = trait_m.def_id.as_local() {
-            let trait_id = tcx.hir().local_def_id_to_hir_id(def_id);
-            match tcx.hir().expect_trait_item(trait_id).kind {
+            match tcx.hir().expect_trait_item(def_id).kind {
                 TraitItemKind::Fn(ref trait_m_sig, _) => {
                     let pos = if trait_number_args > 0 { trait_number_args - 1 } else { 0 };
                     if let Some(arg) = trait_m_sig.decl.inputs.get(pos) {
@@ -730,8 +715,7 @@ fn compare_number_of_method_arguments<'tcx>(
         } else {
             trait_item_span
         };
-        let impl_m_hir_id = tcx.hir().local_def_id_to_hir_id(impl_m.def_id.expect_local());
-        let impl_span = match tcx.hir().expect_impl_item(impl_m_hir_id).kind {
+        let impl_span = match tcx.hir().expect_impl_item(impl_m.def_id.expect_local()).kind {
             ImplItemKind::Fn(ref impl_m_sig, _) => {
                 let pos = if impl_number_args > 0 { impl_number_args - 1 } else { 0 };
                 if let Some(arg) = impl_m_sig.decl.inputs.get(pos) {
@@ -1055,7 +1039,7 @@ fn compare_const_param_types<'tcx>(
             );
 
             // Locate the Span containing just the type of the offending impl
-            match tcx.hir().expect_impl_item(impl_c_hir_id).kind {
+            match tcx.hir().expect_impl_item(impl_c.def_id.expect_local()).kind {
                 ImplItemKind::Const(ref ty, _) => cause.make_mut().span = ty.span,
                 _ => bug!("{:?} is not a impl const", impl_c),
             }
@@ -1068,11 +1052,9 @@ fn compare_const_param_types<'tcx>(
                 trait_c.ident
             );
 
-            let trait_c_hir_id =
-                trait_c.def_id.as_local().map(|def_id| tcx.hir().local_def_id_to_hir_id(def_id));
-            let trait_c_span = trait_c_hir_id.map(|trait_c_hir_id| {
+            let trait_c_span = trait_c.def_id.as_local().map(|trait_c_def_id| {
                 // Add a label to the Span containing just the type of the const
-                match tcx.hir().expect_trait_item(trait_c_hir_id).kind {
+                match tcx.hir().expect_trait_item(trait_c_def_id).kind {
                     TraitItemKind::Const(ref ty, _) => ty.span,
                     _ => bug!("{:?} is not a trait const", trait_c),
                 }
index 142a0a8fc2501e922c4a35058f87537cec07aed7..43156a1041cfc9d9b0f5b90afe392705a516c880 100644 (file)
@@ -1097,12 +1097,9 @@ pub(in super::super) fn could_remove_semicolon(
                         (_, _) => return None,
                     };
 
-                let last_hir_id = self.tcx.hir().local_def_id_to_hir_id(last_local_id);
-                let exp_hir_id = self.tcx.hir().local_def_id_to_hir_id(exp_local_id);
-
                 match (
-                    &self.tcx.hir().expect_item(last_hir_id).kind,
-                    &self.tcx.hir().expect_item(exp_hir_id).kind,
+                    &self.tcx.hir().expect_item(last_local_id).kind,
+                    &self.tcx.hir().expect_item(exp_local_id).kind,
                 ) {
                     (
                         hir::ItemKind::OpaqueTy(hir::OpaqueTy { bounds: last_bounds, .. }),
index 5c8056b244242343791656967f54d2cd9a92f61a..bc2859719e8ebb66a16e586bed3a4f742ec4d980 100644 (file)
@@ -345,10 +345,7 @@ fn trait_path(&self, span: Span, expr_hir_id: HirId, trait_def_id: DefId) -> Opt
         let import_items: Vec<_> = applicable_trait
             .import_ids
             .iter()
-            .map(|&import_id| {
-                let hir_id = self.tcx.hir().local_def_id_to_hir_id(import_id);
-                self.tcx.hir().expect_item(hir_id)
-            })
+            .map(|&import_id| self.tcx.hir().expect_item(import_id))
             .collect();
 
         // Find an identifier with which this trait was imported (note that `_` doesn't count).
index e7fba3a70ff42d986aa05c28240426c3f8731ff3..7bfd3f0ee804733ba763844cd99d693e55478724 100644 (file)
@@ -391,7 +391,6 @@ fn typeck_with_fallback<'tcx>(
             let mut wf_tys = FxHashSet::default();
             // Compute the fty from point of view of inside the fn.
             let fn_sig = tcx.liberate_late_bound_regions(def_id.to_def_id(), fn_sig);
-            wf_tys.extend(fn_sig.inputs_and_output.iter());
             let fn_sig = inh.normalize_associated_types_in(
                 body.value.span,
                 body_id.hir_id,
index f83209f57a897cf54145fd76295746c45faa4e65..1c4e0522bef8fac63307ddb78ce3355b0f507128 100644 (file)
@@ -442,8 +442,8 @@ fn check_overloaded_binop(
                             let mut eraser = TypeParamEraser(self, expr.span);
                             let needs_bound = self
                                 .lookup_op_method(
-                                    eraser.fold_ty(lhs_ty),
-                                    &[eraser.fold_ty(rhs_ty)],
+                                    eraser.fold_ty(lhs_ty).into_ok(),
+                                    &[eraser.fold_ty(rhs_ty).into_ok()],
                                     Op::Binary(op, is_assign),
                                 )
                                 .is_ok();
@@ -1015,12 +1015,12 @@ fn tcx(&self) -> TyCtxt<'tcx> {
         self.0.tcx
     }
 
-    fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> {
+    fn fold_ty(&mut self, ty: Ty<'tcx>) -> Result<Ty<'tcx>, Self::Error> {
         match ty.kind() {
-            ty::Param(_) => self.0.next_ty_var(TypeVariableOrigin {
+            ty::Param(_) => Ok(self.0.next_ty_var(TypeVariableOrigin {
                 kind: TypeVariableOriginKind::MiscVariable,
                 span: self.1,
-            }),
+            })),
             _ => ty.super_fold_with(self),
         }
     }
index 0050ac99cb19a8c32ac804792a94b2ec2b099783..33a0c3275ca2a4d412a1daa19475f885c5287254 100644 (file)
@@ -84,8 +84,7 @@ fn with_fcx<F>(&mut self, f: F)
 /// the types first.
 #[instrument(skip(tcx), level = "debug")]
 pub fn check_item_well_formed(tcx: TyCtxt<'_>, def_id: LocalDefId) {
-    let hir_id = tcx.hir().local_def_id_to_hir_id(def_id);
-    let item = tcx.hir().expect_item(hir_id);
+    let item = tcx.hir().expect_item(def_id);
 
     debug!(
         ?item.def_id,
@@ -197,7 +196,7 @@ pub fn check_item_well_formed(tcx: TyCtxt<'_>, def_id: LocalDefId) {
 
 pub fn check_trait_item(tcx: TyCtxt<'_>, def_id: LocalDefId) {
     let hir_id = tcx.hir().local_def_id_to_hir_id(def_id);
-    let trait_item = tcx.hir().expect_trait_item(hir_id);
+    let trait_item = tcx.hir().expect_trait_item(def_id);
 
     let (method_sig, span) = match trait_item.kind {
         hir::TraitItemKind::Fn(ref sig, _) => (Some(sig), trait_item.span),
@@ -207,8 +206,8 @@ pub fn check_trait_item(tcx: TyCtxt<'_>, def_id: LocalDefId) {
     check_object_unsafe_self_trait_by_name(tcx, trait_item);
     check_associated_item(tcx, trait_item.def_id, span, method_sig);
 
-    let encl_trait_hir_id = tcx.hir().get_parent_item(hir_id);
-    let encl_trait = tcx.hir().expect_item(encl_trait_hir_id);
+    let encl_trait_def_id = tcx.hir().get_parent_did(hir_id);
+    let encl_trait = tcx.hir().expect_item(encl_trait_def_id);
     let encl_trait_def_id = encl_trait.def_id.to_def_id();
     let fn_lang_item_name = if Some(encl_trait_def_id) == tcx.lang_items().fn_trait() {
         Some("fn")
@@ -680,8 +679,7 @@ fn check_object_unsafe_self_trait_by_name(tcx: TyCtxt<'_>, item: &hir::TraitItem
 }
 
 pub fn check_impl_item(tcx: TyCtxt<'_>, def_id: LocalDefId) {
-    let hir_id = tcx.hir().local_def_id_to_hir_id(def_id);
-    let impl_item = tcx.hir().expect_impl_item(hir_id);
+    let impl_item = tcx.hir().expect_impl_item(def_id);
 
     let (method_sig, span) = match impl_item.kind {
         hir::ImplItemKind::Fn(ref sig, _) => (Some(sig), impl_item.span),
@@ -1060,6 +1058,20 @@ fn check_item_type(tcx: TyCtxt<'_>, item_id: LocalDefId, ty_span: Span, allow_fo
             );
         }
 
+        // Ensure that the end result is `Sync` in a non-thread local `static`.
+        let should_check_for_sync = tcx.static_mutability(item_id.to_def_id())
+            == Some(hir::Mutability::Not)
+            && !tcx.is_foreign_item(item_id.to_def_id())
+            && !tcx.is_thread_local_static(item_id.to_def_id());
+
+        if should_check_for_sync {
+            fcx.register_bound(
+                item_ty,
+                tcx.require_lang_item(LangItem::Sync, Some(ty_span)),
+                traits::ObligationCause::new(ty_span, fcx.body_id, traits::SharedStatic),
+            );
+        }
+
         // No implied bounds in a const, etc.
         FxHashSet::default()
     });
@@ -1322,11 +1334,6 @@ fn check_fn_or_method<'fcx, 'tcx>(
 ) {
     let sig = fcx.tcx.liberate_late_bound_regions(def_id, sig);
 
-    // Unnormalized types in signature are WF too
-    implied_bounds.extend(sig.inputs());
-    // FIXME(#27579) return types should not be implied bounds
-    implied_bounds.insert(sig.output());
-
     // Normalize the input and output types one at a time, using a different
     // `WellFormedLoc` for each. We cannot call `normalize_associated_types`
     // on the entire `FnSig`, since this would use the same `WellFormedLoc`
index fdc8b6b5e64519d57642ad6549ec858d880fcc89..a5965411020a4a429c4dd6e865b69c2639aa7ecc 100644 (file)
@@ -658,7 +658,7 @@ fn resolve<T>(&mut self, x: T, span: &dyn Locatable) -> T
         T: TypeFoldable<'tcx>,
     {
         let mut resolver = Resolver::new(self.fcx, span, self.body);
-        let x = x.fold_with(&mut resolver);
+        let x = x.fold_with(&mut resolver).into_ok();
         if cfg!(debug_assertions) && x.needs_infer() {
             span_bug!(span.to_span(self.fcx.tcx), "writeback: `{:?}` has inference variables", x);
         }
@@ -749,15 +749,15 @@ impl<'tcx> TypeFolder<'tcx> for EraseEarlyRegions<'tcx> {
     fn tcx<'b>(&'b self) -> TyCtxt<'tcx> {
         self.tcx
     }
-    fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> {
+    fn fold_ty(&mut self, ty: Ty<'tcx>) -> Result<Ty<'tcx>, Self::Error> {
         if ty.has_type_flags(ty::TypeFlags::HAS_POTENTIAL_FREE_REGIONS) {
             ty.super_fold_with(self)
         } else {
-            ty
+            Ok(ty)
         }
     }
-    fn fold_region(&mut self, r: ty::Region<'tcx>) -> ty::Region<'tcx> {
-        if let ty::ReLateBound(..) = r { r } else { self.tcx.lifetimes.re_erased }
+    fn fold_region(&mut self, r: ty::Region<'tcx>) -> Result<ty::Region<'tcx>, Self::Error> {
+        Ok(if let ty::ReLateBound(..) = r { r } else { self.tcx.lifetimes.re_erased })
     }
 }
 
@@ -766,7 +766,7 @@ fn tcx<'a>(&'a self) -> TyCtxt<'tcx> {
         self.tcx
     }
 
-    fn fold_ty(&mut self, t: Ty<'tcx>) -> Ty<'tcx> {
+    fn fold_ty(&mut self, t: Ty<'tcx>) -> Result<Ty<'tcx>, Self::Error> {
         match self.infcx.fully_resolve(t) {
             Ok(t) => {
                 // Do not anonymize late-bound regions
@@ -779,18 +779,21 @@ fn fold_ty(&mut self, t: Ty<'tcx>) -> Ty<'tcx> {
                 debug!("Resolver::fold_ty: input type `{:?}` not fully resolvable", t);
                 self.report_type_error(t);
                 self.replaced_with_error = true;
-                self.tcx().ty_error()
+                Ok(self.tcx().ty_error())
             }
         }
     }
 
-    fn fold_region(&mut self, r: ty::Region<'tcx>) -> ty::Region<'tcx> {
+    fn fold_region(&mut self, r: ty::Region<'tcx>) -> Result<ty::Region<'tcx>, Self::Error> {
         debug_assert!(!r.is_late_bound(), "Should not be resolving bound region.");
-        self.tcx.lifetimes.re_erased
+        Ok(self.tcx.lifetimes.re_erased)
     }
 
-    fn fold_const(&mut self, ct: &'tcx ty::Const<'tcx>) -> &'tcx ty::Const<'tcx> {
-        match self.infcx.fully_resolve(ct) {
+    fn fold_const(
+        &mut self,
+        ct: &'tcx ty::Const<'tcx>,
+    ) -> Result<&'tcx ty::Const<'tcx>, Self::Error> {
+        Ok(match self.infcx.fully_resolve(ct) {
             Ok(ct) => self.infcx.tcx.erase_regions(ct),
             Err(_) => {
                 debug!("Resolver::fold_const: input const `{:?}` not fully resolvable", ct);
@@ -798,7 +801,7 @@ fn fold_const(&mut self, ct: &'tcx ty::Const<'tcx>) -> &'tcx ty::Const<'tcx> {
                 self.replaced_with_error = true;
                 self.tcx().const_error(ct.ty)
             }
-        }
+        })
     }
 }
 
index 89ce3700aadcdee53a01a18bb51ca65300b39217..79ed83d59ed9728c5c292e82e345a596c7cde65a 100644 (file)
@@ -119,13 +119,13 @@ fn unused_crates_lint(tcx: TyCtxt<'_>) {
 
     for extern_crate in &crates_to_lint {
         let def_id = extern_crate.def_id.expect_local();
-        let id = tcx.hir().local_def_id_to_hir_id(def_id);
-        let item = tcx.hir().expect_item(id);
+        let item = tcx.hir().expect_item(def_id);
 
         // If the crate is fully unused, we suggest removing it altogether.
         // We do this in any edition.
         if extern_crate.warn_if_unused {
             if let Some(&span) = unused_extern_crates.get(&def_id) {
+                let id = tcx.hir().local_def_id_to_hir_id(def_id);
                 tcx.struct_span_lint_hir(lint, id, span, |lint| {
                     // Removal suggestion span needs to include attributes (Issue #54400)
                     let span_with_attrs = tcx
@@ -173,6 +173,7 @@ fn unused_crates_lint(tcx: TyCtxt<'_>) {
         if !tcx.get_attrs(extern_crate.def_id).is_empty() {
             continue;
         }
+        let id = tcx.hir().local_def_id_to_hir_id(def_id);
         tcx.struct_span_lint_hir(lint, id, extern_crate.span, |lint| {
             // Otherwise, we can convert it into a `use` of some kind.
             let base_replacement = match extern_crate.orig_name {
index 372e83592b9c51335fcc04e529071d6684c5b06a..dfb4304ab02c4de8a860d906af82a655f40b5934 100644 (file)
@@ -52,8 +52,7 @@ fn visit_implementation_of_drop(tcx: TyCtxt<'_>, impl_did: LocalDefId) {
         return;
     }
 
-    let impl_hir_id = tcx.hir().local_def_id_to_hir_id(impl_did);
-    let sp = match tcx.hir().expect_item(impl_hir_id).kind {
+    let sp = match tcx.hir().expect_item(impl_did).kind {
         ItemKind::Impl(ref impl_) => impl_.self_ty.span,
         _ => bug!("expected Drop impl item"),
     };
@@ -78,7 +77,7 @@ fn visit_implementation_of_copy(tcx: TyCtxt<'_>, impl_did: LocalDefId) {
     match can_type_implement_copy(tcx, param_env, self_type) {
         Ok(()) => {}
         Err(CopyImplementationError::InfrigingFields(fields)) => {
-            let item = tcx.hir().expect_item(impl_hir_id);
+            let item = tcx.hir().expect_item(impl_did);
             let span = if let ItemKind::Impl(hir::Impl { of_trait: Some(ref tr), .. }) = item.kind {
                 tr.path.span
             } else {
@@ -97,7 +96,7 @@ fn visit_implementation_of_copy(tcx: TyCtxt<'_>, impl_did: LocalDefId) {
             err.emit()
         }
         Err(CopyImplementationError::NotAnAdt) => {
-            let item = tcx.hir().expect_item(impl_hir_id);
+            let item = tcx.hir().expect_item(impl_did);
             let span =
                 if let ItemKind::Impl(ref impl_) = item.kind { impl_.self_ty.span } else { span };
 
@@ -292,8 +291,8 @@ pub fn coerce_unsized_info(tcx: TyCtxt<'tcx>, impl_did: DefId) -> CoerceUnsizedI
     debug!("compute_coerce_unsized_info(impl_did={:?})", impl_did);
 
     // this provider should only get invoked for local def-ids
-    let impl_hir_id = tcx.hir().local_def_id_to_hir_id(impl_did.expect_local());
-    let span = tcx.hir().span(impl_hir_id);
+    let impl_did = impl_did.expect_local();
+    let span = tcx.def_span(impl_did);
 
     let coerce_unsized_trait = tcx.require_lang_item(LangItem::CoerceUnsized, Some(span));
 
@@ -315,6 +314,7 @@ pub fn coerce_unsized_info(tcx: TyCtxt<'tcx>, impl_did: DefId) -> CoerceUnsizedI
     debug!("visit_implementation_of_coerce_unsized: {:?} -> {:?} (free)", source, target);
 
     tcx.infer_ctxt().enter(|infcx| {
+        let impl_hir_id = tcx.hir().local_def_id_to_hir_id(impl_did);
         let cause = ObligationCause::misc(span, impl_hir_id);
         let check_mutbl = |mt_a: ty::TypeAndMut<'tcx>,
                            mt_b: ty::TypeAndMut<'tcx>,
@@ -452,13 +452,13 @@ pub fn coerce_unsized_info(tcx: TyCtxt<'tcx>, impl_did: DefId) -> CoerceUnsizedI
                     .emit();
                     return err_info;
                 } else if diff_fields.len() > 1 {
-                    let item = tcx.hir().expect_item(impl_hir_id);
+                    let item = tcx.hir().expect_item(impl_did);
                     let span = if let ItemKind::Impl(hir::Impl { of_trait: Some(ref t), .. }) =
                         item.kind
                     {
                         t.path.span
                     } else {
-                        tcx.hir().span(impl_hir_id)
+                        tcx.def_span(impl_did)
                     };
 
                     struct_span_err!(
@@ -530,7 +530,11 @@ pub fn coerce_unsized_info(tcx: TyCtxt<'tcx>, impl_did: DefId) -> CoerceUnsizedI
 
         // Finally, resolve all regions.
         let outlives_env = OutlivesEnvironment::new(param_env);
-        infcx.resolve_regions_and_report_errors(impl_did, &outlives_env, RegionckMode::default());
+        infcx.resolve_regions_and_report_errors(
+            impl_did.to_def_id(),
+            &outlives_env,
+            RegionckMode::default(),
+        );
 
         CoerceUnsizedInfo { custom_kind: kind }
     })
index b9db8a6be5916bbc7b000970e6921b7e6e64c393..4b41730ffd50bd59f353e744f1ac2161b041c457 100644 (file)
@@ -431,7 +431,7 @@ fn projected_ty_from_poly_trait_ref(
             match self.node() {
                 hir::Node::Field(_) | hir::Node::Ctor(_) | hir::Node::Variant(_) => {
                     let item =
-                        self.tcx.hir().expect_item(self.tcx.hir().get_parent_item(self.hir_id()));
+                        self.tcx.hir().expect_item(self.tcx.hir().get_parent_did(self.hir_id()));
                     match &item.kind {
                         hir::ItemKind::Enum(_, generics)
                         | hir::ItemKind::Struct(_, generics)
@@ -666,7 +666,7 @@ fn type_parameter_bounds_in_generics(
                 Some(assoc_name) => self.bound_defines_assoc_item(b, assoc_name),
                 None => true,
             })
-            .flat_map(|b| predicates_from_bound(self, ty, b));
+            .flat_map(|b| predicates_from_bound(self, ty, b, ty::List::empty()));
 
         let param_def_id = self.tcx.hir().local_def_id(param_id).to_def_id();
         let from_where_clauses = ast_generics
@@ -685,15 +685,17 @@ fn type_parameter_bounds_in_generics(
                 } else {
                     None
                 };
+                let bvars = self.tcx.late_bound_vars(bp.bounded_ty.hir_id);
+
                 bp.bounds
                     .iter()
                     .filter(|b| match assoc_name {
                         Some(assoc_name) => self.bound_defines_assoc_item(b, assoc_name),
                         None => true,
                     })
-                    .filter_map(move |b| bt.map(|bt| (bt, b)))
+                    .filter_map(move |b| bt.map(|bt| (bt, b, bvars)))
             })
-            .flat_map(|(bt, b)| predicates_from_bound(self, bt, b));
+            .flat_map(|(bt, b, bvars)| predicates_from_bound(self, bt, b, bvars));
 
         from_ty_params.chain(from_where_clauses).collect()
     }
@@ -1182,8 +1184,7 @@ fn super_predicates_that_define_assoc_type(
 }
 
 fn trait_def(tcx: TyCtxt<'_>, def_id: DefId) -> ty::TraitDef {
-    let hir_id = tcx.hir().local_def_id_to_hir_id(def_id.expect_local());
-    let item = tcx.hir().expect_item(hir_id);
+    let item = tcx.hir().expect_item(def_id.expect_local());
 
     let (is_auto, unsafety) = match item.kind {
         hir::ItemKind::Trait(is_auto, unsafety, ..) => (is_auto == hir::IsAuto::Yes, unsafety),
@@ -1878,9 +1879,7 @@ fn fn_sig(tcx: TyCtxt<'_>, def_id: DefId) -> ty::PolyFnSig<'_> {
 
 fn impl_trait_ref(tcx: TyCtxt<'_>, def_id: DefId) -> Option<ty::TraitRef<'_>> {
     let icx = ItemCtxt::new(tcx, def_id);
-
-    let hir_id = tcx.hir().local_def_id_to_hir_id(def_id.expect_local());
-    match tcx.hir().expect_item(hir_id).kind {
+    match tcx.hir().expect_item(def_id.expect_local()).kind {
         hir::ItemKind::Impl(ref impl_) => impl_.of_trait.as_ref().map(|ast_trait_ref| {
             let selfty = tcx.type_of(def_id);
             <dyn AstConv<'_>>::instantiate_mono_trait_ref(&icx, ast_trait_ref, selfty)
@@ -1890,9 +1889,8 @@ fn impl_trait_ref(tcx: TyCtxt<'_>, def_id: DefId) -> Option<ty::TraitRef<'_>> {
 }
 
 fn impl_polarity(tcx: TyCtxt<'_>, def_id: DefId) -> ty::ImplPolarity {
-    let hir_id = tcx.hir().local_def_id_to_hir_id(def_id.expect_local());
     let is_rustc_reservation = tcx.has_attr(def_id, sym::rustc_reservation_impl);
-    let item = tcx.hir().expect_item(hir_id);
+    let item = tcx.hir().expect_item(def_id.expect_local());
     match &item.kind {
         hir::ItemKind::Impl(hir::Impl {
             polarity: hir::ImplPolarity::Negative(span),
@@ -2433,14 +2431,10 @@ fn predicates_from_bound<'tcx>(
     astconv: &dyn AstConv<'tcx>,
     param_ty: Ty<'tcx>,
     bound: &'tcx hir::GenericBound<'tcx>,
+    bound_vars: &'tcx ty::List<ty::BoundVariableKind>,
 ) -> Vec<(ty::Predicate<'tcx>, Span)> {
     let mut bounds = Bounds::default();
-    astconv.add_bounds(
-        param_ty,
-        std::array::IntoIter::new([bound]),
-        &mut bounds,
-        ty::List::empty(),
-    );
+    astconv.add_bounds(param_ty, [bound].into_iter(), &mut bounds, bound_vars);
     bounds.predicates(astconv.tcx(), param_ty)
 }
 
@@ -3227,7 +3221,7 @@ fn check_target_feature_trait_unsafe(tcx: TyCtxt<'_>, id: LocalDefId, attr_span:
     let hir_id = tcx.hir().local_def_id_to_hir_id(id);
     let node = tcx.hir().get(hir_id);
     if let Node::ImplItem(hir::ImplItem { kind: hir::ImplItemKind::Fn(..), .. }) = node {
-        let parent_id = tcx.hir().get_parent_item(hir_id);
+        let parent_id = tcx.hir().get_parent_did(hir_id);
         let parent_item = tcx.hir().expect_item(parent_id);
         if let hir::ItemKind::Impl(hir::Impl { of_trait: Some(_), .. }) = parent_item.kind {
             tcx.sess
index 04a68250ced0cd0a44387b6fa7d3abf868b03351..1ea379c57389a1035052985f142ba5c71c11bf22 100644 (file)
@@ -729,17 +729,17 @@ fn tcx(&self) -> TyCtxt<'tcx> {
             self.tcx
         }
 
-        fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> {
+        fn fold_ty(&mut self, ty: Ty<'tcx>) -> Result<Ty<'tcx>, Self::Error> {
             if !self.success {
-                return ty;
+                return Ok(ty);
             }
 
             match ty.kind() {
-                ty::FnDef(def_id, _) => self.tcx.mk_fn_ptr(self.tcx.fn_sig(*def_id)),
+                ty::FnDef(def_id, _) => Ok(self.tcx.mk_fn_ptr(self.tcx.fn_sig(*def_id))),
                 // FIXME: non-capturing closures should also suggest a function pointer
                 ty::Closure(..) | ty::Generator(..) => {
                     self.success = false;
-                    ty
+                    Ok(ty)
                 }
                 _ => ty.super_fold_with(self),
             }
@@ -761,7 +761,7 @@ fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> {
 
                 // Suggesting unnameable types won't help.
                 let mut mk_nameable = MakeNameable::new(tcx);
-                let ty = mk_nameable.fold_ty(ty);
+                let ty = mk_nameable.fold_ty(ty).into_ok();
                 let sugg_ty = if mk_nameable.success { Some(ty) } else { None };
                 if let Some(sugg_ty) = sugg_ty {
                     err.span_suggestion(
@@ -785,7 +785,7 @@ fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> {
 
             if !ty.references_error() {
                 let mut mk_nameable = MakeNameable::new(tcx);
-                let ty = mk_nameable.fold_ty(ty);
+                let ty = mk_nameable.fold_ty(ty).into_ok();
                 let sugg_ty = if mk_nameable.success { Some(ty) } else { None };
                 if let Some(sugg_ty) = sugg_ty {
                     diag.span_suggestion(
index a49eda6572de2cb3cf3248d6a5e317a3ab8ee893..f9de6376b0ff5e572964c8edc8c3b7abd6469d4e 100644 (file)
@@ -71,8 +71,11 @@ fn nested_visit_map(&mut self) -> NestedVisitorMap<Self::Map> {
         fn visit_ty(&mut self, ty: &'tcx hir::Ty<'tcx>) {
             self.tcx.infer_ctxt().enter(|infcx| {
                 let mut fulfill = traits::FulfillmentContext::new();
-                let tcx_ty =
-                    self.icx.to_ty(ty).fold_with(&mut EraseAllBoundRegions { tcx: self.tcx });
+                let tcx_ty = self
+                    .icx
+                    .to_ty(ty)
+                    .fold_with(&mut EraseAllBoundRegions { tcx: self.tcx })
+                    .into_ok();
                 let cause = traits::ObligationCause::new(
                     ty.span,
                     self.hir_id,
@@ -183,7 +186,7 @@ impl<'tcx> TypeFolder<'tcx> for EraseAllBoundRegions<'tcx> {
     fn tcx<'a>(&'a self) -> TyCtxt<'tcx> {
         self.tcx
     }
-    fn fold_region(&mut self, r: Region<'tcx>) -> Region<'tcx> {
-        if let ty::ReLateBound(..) = r { &ty::ReErased } else { r }
+    fn fold_region(&mut self, r: Region<'tcx>) -> Result<Region<'tcx>, Self::Error> {
+        if let ty::ReLateBound(..) = r { Ok(&ty::ReErased) } else { Ok(r) }
     }
 }
index 0881cf07586b367b88210919adef6be38f15c779..c0f0b3fe7046ec2c34fe78af4dbf93b43a44b3e7 100644 (file)
@@ -71,6 +71,7 @@
 #![feature(slice_partition_dedup)]
 #![feature(control_flow_enum)]
 #![feature(hash_drain_filter)]
+#![feature(unwrap_infallible)]
 #![recursion_limit = "256"]
 
 #[macro_use]
index 4ab38c802a1599ef507e4bac8aa96d06056fe5d5..3d38e73305a37a577667e03a2cfc5491e4080bd4 100644 (file)
@@ -289,6 +289,14 @@ fn do_reserve_and_handle<T, A: Allocator>(
         }
     }
 
+    /// A specialized version of `reserve()` used only by the hot and
+    /// oft-instantiated `Vec::push()`, which does its own capacity check.
+    #[cfg(not(no_global_oom_handling))]
+    #[inline(never)]
+    pub fn reserve_for_push(&mut self, len: usize) {
+        handle_reserve(self.grow_amortized(len, 1));
+    }
+
     /// The same as `reserve`, but returns on errors instead of panicking or aborting.
     pub fn try_reserve(&mut self, len: usize, additional: usize) -> Result<(), TryReserveError> {
         if self.needs_to_grow(len, additional) {
index 8c15a24409bab17793101ddfc1e174cd8edad0a7..ff322f0da97c6e069f62f2e9432e593011cd5e62 100644 (file)
@@ -77,3 +77,87 @@ fn reserve_does_not_overallocate() {
         assert!(v.capacity() >= 12 + 12 / 2);
     }
 }
+
+struct ZST;
+
+// A `RawVec` holding zero-sized elements should always look like this.
+fn zst_sanity<T>(v: &RawVec<T>) {
+    assert_eq!(v.capacity(), usize::MAX);
+    assert_eq!(v.ptr(), core::ptr::Unique::<T>::dangling().as_ptr());
+    assert_eq!(v.current_memory(), None);
+}
+
+#[test]
+fn zst() {
+    let cap_err = Err(crate::collections::TryReserveErrorKind::CapacityOverflow.into());
+
+    assert_eq!(std::mem::size_of::<ZST>(), 0);
+
+    // All these different ways of creating the RawVec produce the same thing.
+
+    let v: RawVec<ZST> = RawVec::new();
+    zst_sanity(&v);
+
+    let v: RawVec<ZST> = RawVec::with_capacity_in(100, Global);
+    zst_sanity(&v);
+
+    let v: RawVec<ZST> = RawVec::with_capacity_in(100, Global);
+    zst_sanity(&v);
+
+    let v: RawVec<ZST> = RawVec::allocate_in(0, AllocInit::Uninitialized, Global);
+    zst_sanity(&v);
+
+    let v: RawVec<ZST> = RawVec::allocate_in(100, AllocInit::Uninitialized, Global);
+    zst_sanity(&v);
+
+    let mut v: RawVec<ZST> = RawVec::allocate_in(usize::MAX, AllocInit::Uninitialized, Global);
+    zst_sanity(&v);
+
+    // Check all these operations work as expected with zero-sized elements.
+
+    assert!(!v.needs_to_grow(100, usize::MAX - 100));
+    assert!(v.needs_to_grow(101, usize::MAX - 100));
+    zst_sanity(&v);
+
+    v.reserve(100, usize::MAX - 100);
+    //v.reserve(101, usize::MAX - 100); // panics, in `zst_reserve_panic` below
+    zst_sanity(&v);
+
+    v.reserve_exact(100, usize::MAX - 100);
+    //v.reserve_exact(101, usize::MAX - 100); // panics, in `zst_reserve_exact_panic` below
+    zst_sanity(&v);
+
+    assert_eq!(v.try_reserve(100, usize::MAX - 100), Ok(()));
+    assert_eq!(v.try_reserve(101, usize::MAX - 100), cap_err);
+    zst_sanity(&v);
+
+    assert_eq!(v.try_reserve_exact(100, usize::MAX - 100), Ok(()));
+    assert_eq!(v.try_reserve_exact(101, usize::MAX - 100), cap_err);
+    zst_sanity(&v);
+
+    assert_eq!(v.grow_amortized(100, usize::MAX - 100), cap_err);
+    assert_eq!(v.grow_amortized(101, usize::MAX - 100), cap_err);
+    zst_sanity(&v);
+
+    assert_eq!(v.grow_exact(100, usize::MAX - 100), cap_err);
+    assert_eq!(v.grow_exact(101, usize::MAX - 100), cap_err);
+    zst_sanity(&v);
+}
+
+#[test]
+#[should_panic(expected = "capacity overflow")]
+fn zst_reserve_panic() {
+    let mut v: RawVec<ZST> = RawVec::new();
+    zst_sanity(&v);
+
+    v.reserve(101, usize::MAX - 100);
+}
+
+#[test]
+#[should_panic(expected = "capacity overflow")]
+fn zst_reserve_exact_panic() {
+    let mut v: RawVec<ZST> = RawVec::new();
+    zst_sanity(&v);
+
+    v.reserve_exact(101, usize::MAX - 100);
+}
index 906b0187f7babf540932b2cd408f71b88b308782..4f926d99c6dbc46e992aa73d4b89b6cd82852a11 100644 (file)
@@ -558,13 +558,13 @@ pub fn from_utf8(vec: Vec<u8>) -> Result<String, FromUtf8Error> {
     pub fn from_utf8_lossy(v: &[u8]) -> Cow<'_, str> {
         let mut iter = lossy::Utf8Lossy::from_bytes(v).chunks();
 
-        let (first_valid, first_broken) = if let Some(chunk) = iter.next() {
+        let first_valid = if let Some(chunk) = iter.next() {
             let lossy::Utf8LossyChunk { valid, broken } = chunk;
-            if valid.len() == v.len() {
-                debug_assert!(broken.is_empty());
+            if broken.is_empty() {
+                debug_assert_eq!(valid.len(), v.len());
                 return Cow::Borrowed(valid);
             }
-            (valid, broken)
+            valid
         } else {
             return Cow::Borrowed("");
         };
@@ -573,9 +573,7 @@ pub fn from_utf8_lossy(v: &[u8]) -> Cow<'_, str> {
 
         let mut res = String::with_capacity(v.len());
         res.push_str(first_valid);
-        if !first_broken.is_empty() {
-            res.push_str(REPLACEMENT);
-        }
+        res.push_str(REPLACEMENT);
 
         for lossy::Utf8LossyChunk { valid, broken } in iter {
             res.push_str(valid);
index 85759917765fa6e3d91afa9fd468956c83afdc70..88bde6e8ce48152f1aad625911bc91e2578663e8 100644 (file)
@@ -1726,7 +1726,7 @@ pub fn push(&mut self, value: T) {
         // This will panic or abort if we would allocate > isize::MAX bytes
         // or if the length increment would overflow for zero-sized types.
         if self.len == self.buf.capacity() {
-            self.reserve(1);
+            self.buf.reserve_for_push(self.len);
         }
         unsafe {
             let end = self.as_mut_ptr().add(self.len);
index 00a878c079480b0e1a50f140d82b7ce9df157ec8..773142825329b7dd4130ad8111ff7c226c11f76d 100644 (file)
@@ -985,6 +985,9 @@ fn test_into_iter_advance_by() {
 
     assert_eq!(i.advance_by(usize::MAX), Err(0));
 
+    i.advance_by(0).unwrap();
+    i.advance_back_by(0).unwrap();
+
     assert_eq!(i.len(), 0);
 }
 
index cc32d5223b49f655f691017d675c0d363b5de444..9df0b5c55191591de62b572cedb21cb866eaf85a 100644 (file)
@@ -281,7 +281,9 @@ pub fn pad_to_align(&self) -> Layout {
         // > `usize::MAX`)
         let new_size = self.size() + pad;
 
-        Layout::from_size_align(new_size, self.align()).unwrap()
+        // SAFETY: self.align is already known to be valid and new_size has been
+        // padded already.
+        unsafe { Layout::from_size_align_unchecked(new_size, self.align()) }
     }
 
     /// Creates a layout describing the record for `n` instances of
@@ -403,9 +405,17 @@ pub fn extend_packed(&self, next: Self) -> Result<Self, LayoutError> {
     #[stable(feature = "alloc_layout_manipulation", since = "1.44.0")]
     #[inline]
     pub fn array<T>(n: usize) -> Result<Self, LayoutError> {
-        let (layout, offset) = Layout::new::<T>().repeat(n)?;
-        debug_assert_eq!(offset, mem::size_of::<T>());
-        Ok(layout.pad_to_align())
+        let array_size = mem::size_of::<T>().checked_mul(n).ok_or(LayoutError)?;
+
+        // SAFETY:
+        // - Size: `array_size` cannot be too big because `size_of::<T>()` must
+        //   be a multiple of `align_of::<T>()`. Therefore, `array_size`
+        //   rounded up to the nearest multiple of `align_of::<T>()` is just
+        //   `array_size`. And `array_size` cannot be too big because it was
+        //   just checked by the `checked_mul()`.
+        // - Alignment: `align_of::<T>()` will always give an acceptable
+        //   (non-zero, power of two) alignment.
+        Ok(unsafe { Layout::from_size_align_unchecked(array_size, mem::align_of::<T>()) })
     }
 }
 
index 80d3270d73cc824a80759b328ac5dd3eb4fecfe3..6fc3cd0b7c4adcf2abe72f363c745c08a02b1c92 100644 (file)
@@ -2186,28 +2186,34 @@ fn fmt(&self, f: &mut Formatter<'_>) -> Result {
 #[stable(feature = "rust1", since = "1.0.0")]
 impl<T: ?Sized> Pointer for *const T {
     fn fmt(&self, f: &mut Formatter<'_>) -> Result {
-        let old_width = f.width;
-        let old_flags = f.flags;
-
-        // The alternate flag is already treated by LowerHex as being special-
-        // it denotes whether to prefix with 0x. We use it to work out whether
-        // or not to zero extend, and then unconditionally set it to get the
-        // prefix.
-        if f.alternate() {
-            f.flags |= 1 << (FlagV1::SignAwareZeroPad as u32);
-
-            if f.width.is_none() {
-                f.width = Some((usize::BITS / 4) as usize + 2);
+        /// Since the formatting will be identical for all pointer types, use a non-monomorphized
+        /// implementation for the actual formatting to reduce the amount of codegen work needed
+        fn inner(ptr: *const (), f: &mut Formatter<'_>) -> Result {
+            let old_width = f.width;
+            let old_flags = f.flags;
+
+            // The alternate flag is already treated by LowerHex as being special-
+            // it denotes whether to prefix with 0x. We use it to work out whether
+            // or not to zero extend, and then unconditionally set it to get the
+            // prefix.
+            if f.alternate() {
+                f.flags |= 1 << (FlagV1::SignAwareZeroPad as u32);
+
+                if f.width.is_none() {
+                    f.width = Some((usize::BITS / 4) as usize + 2);
+                }
             }
-        }
-        f.flags |= 1 << (FlagV1::Alternate as u32);
+            f.flags |= 1 << (FlagV1::Alternate as u32);
+
+            let ret = LowerHex::fmt(&(ptr as usize), f);
 
-        let ret = LowerHex::fmt(&(*self as *const () as usize), f);
+            f.width = old_width;
+            f.flags = old_flags;
 
-        f.width = old_width;
-        f.flags = old_flags;
+            ret
+        }
 
-        ret
+        inner(*self as *const (), f)
     }
 }
 
index 540160bc4c2a4daadc4d040c58dc529b3d758fe4..3ff84cc9672eb757a3e85d74f2e30d82ce43d617 100644 (file)
 /// `0xFF` byte to the `Hasher` so that the values `("ab", "c")` and `("a",
 /// "bc")` hash differently.
 ///
+/// ## Portability
+///
+/// Due to differences in endianness and type sizes, data fed by `Hash` to a `Hasher`
+/// should not be considered portable across platforms. Additionally the data passed by most
+/// standard library types should not be considered stable between compiler versions.
+///
+/// This means tests shouldn't probe hard-coded hash values or data fed to a `Hasher` and
+/// instead should check consistency with `Eq`.
+///
+/// Serialization formats intended to be portable between platforms or compiler versions should
+/// either avoid encoding hashes or only rely on `Hash` and `Hasher` implementations that
+/// provide additional guarantees.
+///
 /// [`HashMap`]: ../../std/collections/struct.HashMap.html
 /// [`HashSet`]: ../../std/collections/struct.HashSet.html
 /// [`hash`]: Hash::hash
index 0f57fb5b14180432c3481a91c94b66b74495673f..edbc250eb0d0c2a243da0244046d1cfad5c82c48 100644 (file)
@@ -853,19 +853,21 @@ pub unsafe fn drop_in_place<T: ?Sized>(to_drop: *mut T) {
     /// This will statically either panic, or do nothing.
     ///
     /// This intrinsic does not have a stable counterpart.
-    #[rustc_const_unstable(feature = "const_assert_type", issue = "none")]
+    #[rustc_const_stable(feature = "const_assert_type", since = "1.59.0")]
     pub fn assert_inhabited<T>();
 
     /// A guard for unsafe functions that cannot ever be executed if `T` does not permit
     /// zero-initialization: This will statically either panic, or do nothing.
     ///
     /// This intrinsic does not have a stable counterpart.
+    #[rustc_const_unstable(feature = "const_assert_type2", issue = "none")]
     pub fn assert_zero_valid<T>();
 
     /// A guard for unsafe functions that cannot ever be executed if `T` has invalid
     /// bit patterns: This will statically either panic, or do nothing.
     ///
     /// This intrinsic does not have a stable counterpart.
+    #[rustc_const_unstable(feature = "const_assert_type2", issue = "none")]
     pub fn assert_uninit_valid<T>();
 
     /// Gets a reference to a static `Location` indicating where it was called.
index 565fc224f53ca06bafd5bf2f73790fd794dbc06f..ea1da8ba434edc54e21b15f73c5a7a4d8cf184b6 100644 (file)
@@ -119,8 +119,8 @@ fn fold<Acc, Fold>(mut self, init: Acc, fold: Fold) -> Acc
     #[rustc_inherit_overflow_checks]
     fn advance_by(&mut self, n: usize) -> Result<(), usize> {
         let mut rem = n;
-
         let step_one = self.n.saturating_add(rem);
+
         match self.iter.advance_by(step_one) {
             Ok(_) => {
                 rem -= step_one - self.n;
@@ -129,7 +129,7 @@ fn advance_by(&mut self, n: usize) -> Result<(), usize> {
             Err(advanced) => {
                 let advanced_without_skip = advanced.saturating_sub(self.n);
                 self.n = self.n.saturating_sub(advanced);
-                return Err(advanced_without_skip);
+                return if n == 0 { Ok(()) } else { Err(advanced_without_skip) };
             }
         }
 
index 81f6c294fac13f8f70e8f1528ed32640a7e52ad3..2962e0104d11d0f7cb2bd2568d582eb7f490849e 100644 (file)
@@ -215,21 +215,22 @@ fn rfold<Acc, Fold>(mut self, init: Acc, fold: Fold) -> Acc
     }
 
     #[inline]
+    #[rustc_inherit_overflow_checks]
     fn advance_back_by(&mut self, n: usize) -> Result<(), usize> {
-        let inner_len = self.iter.len();
-        let len = self.n;
-        let remainder = len.saturating_sub(n);
-        let to_advance = inner_len - remainder;
-        match self.iter.advance_back_by(to_advance) {
-            Ok(_) => {
-                self.n = remainder;
-                if n > len {
-                    return Err(len);
-                }
-                return Ok(());
-            }
-            _ => panic!("ExactSizeIterator contract violation"),
-        }
+        // The amount by which the inner iterator needs to be shortened for it to be
+        // at most as long as the take() amount.
+        let trim_inner = self.iter.len().saturating_sub(self.n);
+        // The amount we need to advance inner to fulfill the caller's request.
+        // take(), advance_by() and len() all can be at most usize, so we don't have to worry
+        // about having to advance more than usize::MAX here.
+        let advance_by = trim_inner.saturating_add(n);
+
+        let advanced = match self.iter.advance_back_by(advance_by) {
+            Ok(_) => advance_by - trim_inner,
+            Err(advanced) => advanced - trim_inner,
+        };
+        self.n -= advanced;
+        return if advanced < n { Err(advanced) } else { Ok(()) };
     }
 }
 
index 9a589c1f3b55c3fac8911291c5b8427a813b4fc1..a6aed6d210beb9ea50a34caef132f809246b5895 100644 (file)
@@ -106,9 +106,6 @@ pub trait DoubleEndedIterator: Iterator {
     /// Calling `advance_back_by(0)` can do meaningful work, for example [`Flatten`] can advance its
     /// outer iterator until it finds an inner iterator that is not empty, which then often
     /// allows it to return a more accurate `size_hint()` than in its initial state.
-    /// `advance_back_by(0)` may either return `Ok()` or `Err(0)`. The former conveys no information
-    /// whether the iterator is or is not exhausted, the latter can be treated as if [`next_back`]
-    /// had returned `None`. Replacing a `Err(0)` with `Ok` is only correct for `n = 0`.
     ///
     /// [`advance_by`]: Iterator::advance_by
     /// [`Flatten`]: crate::iter::Flatten
index d957a7527cf58d7902bed1da9465935277de49d4..35ce9400f8f4d4ab1496ad87f9ca96c8cf54b8ad 100644 (file)
@@ -249,9 +249,6 @@ fn some<T>(_: Option<T>, x: T) -> Option<T> {
     /// Calling `advance_by(0)` can do meaningful work, for example [`Flatten`]
     /// can advance its outer iterator until it finds an inner iterator that is not empty, which
     /// then often allows it to return a more accurate `size_hint()` than in its initial state.
-    /// `advance_by(0)` may either return `Ok()` or `Err(0)`. The former conveys no information
-    /// whether the iterator is or is not exhausted, the latter can be treated as if [`next`]
-    /// had returned `None`. Replacing a `Err(0)` with `Ok` is only correct for `n = 0`.
     ///
     /// [`Flatten`]: crate::iter::Flatten
     /// [`next`]: Iterator::next
@@ -461,8 +458,10 @@ fn chain<U>(self, other: U) -> Chain<Self, U::IntoIter>
     /// In other words, it zips two iterators together, into a single one.
     ///
     /// If either iterator returns [`None`], [`next`] from the zipped iterator
-    /// will return [`None`]. If the first iterator returns [`None`], `zip` will
-    /// short-circuit and `next` will not be called on the second iterator.
+    /// will return [`None`].
+    /// If the zipped iterator has no more elements to return then each further attempt to advance
+    /// it will first try to advance the first iterator at most one time and if it still yielded an item
+    /// try to advance the second iterator at most one time.
     ///
     /// # Examples
     ///
@@ -1024,6 +1023,7 @@ fn peekable(self) -> Peekable<Self>
     /// assert_eq!(iter.next(), None);
     /// ```
     #[inline]
+    #[doc(alias = "drop_while")]
     #[stable(feature = "rust1", since = "1.0.0")]
     fn skip_while<P>(self, predicate: P) -> SkipWhile<Self, P>
     where
index fdb23529599c890aa6a9aeed9bff1ca85dd4a15c..102e6f89eb82a52db3d87322e1754db978433c61 100644 (file)
 #![feature(const_align_of_val)]
 #![feature(const_alloc_layout)]
 #![feature(const_arguments_as_str)]
-#![feature(const_assert_type)]
 #![feature(const_bigint_helper_methods)]
 #![feature(const_caller_location)]
 #![feature(const_cell_into_inner)]
 #![feature(const_intrinsic_copy)]
 #![feature(const_intrinsic_forget)]
 #![feature(const_likely)]
-#![feature(const_maybe_uninit_as_ptr)]
+#![feature(const_maybe_uninit_as_mut_ptr)]
 #![feature(const_maybe_uninit_assume_init)]
 #![feature(const_num_from_num)]
 #![feature(const_ops)]
index 624e87955022f50177c025ee425c87c64055ac45..a6e31452edcfcc04840919f325bb18cf1b33bce9 100644 (file)
@@ -528,7 +528,7 @@ pub const fn write(&mut self, val: T) -> &mut T {
     /// (Notice that the rules around references to uninitialized data are not finalized yet, but
     /// until they are, it is advisable to avoid them.)
     #[stable(feature = "maybe_uninit", since = "1.36.0")]
-    #[rustc_const_unstable(feature = "const_maybe_uninit_as_ptr", issue = "75251")]
+    #[rustc_const_stable(feature = "const_maybe_uninit_as_ptr", since = "1.59.0")]
     #[inline(always)]
     pub const fn as_ptr(&self) -> *const T {
         // `MaybeUninit` and `ManuallyDrop` are both `repr(transparent)` so we can cast the pointer.
@@ -567,7 +567,7 @@ pub const fn as_ptr(&self) -> *const T {
     /// (Notice that the rules around references to uninitialized data are not finalized yet, but
     /// until they are, it is advisable to avoid them.)
     #[stable(feature = "maybe_uninit", since = "1.36.0")]
-    #[rustc_const_unstable(feature = "const_maybe_uninit_as_ptr", issue = "75251")]
+    #[rustc_const_unstable(feature = "const_maybe_uninit_as_mut_ptr", issue = "75251")]
     #[inline(always)]
     pub const fn as_mut_ptr(&mut self) -> *mut T {
         // `MaybeUninit` and `ManuallyDrop` are both `repr(transparent)` so we can cast the pointer.
@@ -620,7 +620,7 @@ pub const fn as_mut_ptr(&mut self) -> *mut T {
     /// // `x` had not been initialized yet, so this last line caused undefined behavior. ⚠️
     /// ```
     #[stable(feature = "maybe_uninit", since = "1.36.0")]
-    #[rustc_const_unstable(feature = "const_maybe_uninit_assume_init", issue = "none")]
+    #[rustc_const_stable(feature = "const_maybe_uninit_assume_init", since = "1.59.0")]
     #[inline(always)]
     #[rustc_diagnostic_item = "assume_init"]
     #[track_caller]
@@ -788,7 +788,8 @@ pub unsafe fn assume_init_drop(&mut self) {
     /// }
     /// ```
     #[stable(feature = "maybe_uninit_ref", since = "1.55.0")]
-    #[rustc_const_unstable(feature = "const_maybe_uninit_assume_init", issue = "none")]
+    #[rustc_const_stable(feature = "const_maybe_uninit_assume_init", since = "1.59.0")]
+    #[cfg_attr(bootstrap, rustc_allow_const_fn_unstable(const_raw_ptr_deref))]
     #[inline(always)]
     pub const unsafe fn assume_init_ref(&self) -> &T {
         // SAFETY: the caller must guarantee that `self` is initialized.
@@ -968,7 +969,7 @@ pub unsafe fn assume_init_drop(&mut self) {
     ///
     /// [`assume_init_ref`]: MaybeUninit::assume_init_ref
     #[unstable(feature = "maybe_uninit_slice", issue = "63569")]
-    #[rustc_const_unstable(feature = "const_maybe_uninit_assume_init", issue = "none")]
+    #[rustc_const_unstable(feature = "maybe_uninit_slice", issue = "63569")]
     #[inline(always)]
     pub const unsafe fn slice_assume_init_ref(slice: &[Self]) -> &[T] {
         // SAFETY: casting slice to a `*const [T]` is safe since the caller guarantees that
index 7708094e1fceab656457dbd297339a35f914319e..8f895c33a63280f6e376426ae889f79ab9e7fc1d 100644 (file)
@@ -915,15 +915,13 @@ impl $Ty {
                 /// Basic usage:
                 ///
                 /// ```
-                /// #![feature(nonzero_is_power_of_two)]
-                ///
                 #[doc = concat!("let eight = std::num::", stringify!($Ty), "::new(8).unwrap();")]
                 /// assert!(eight.is_power_of_two());
                 #[doc = concat!("let ten = std::num::", stringify!($Ty), "::new(10).unwrap();")]
                 /// assert!(!ten.is_power_of_two());
                 /// ```
                 #[must_use]
-                #[unstable(feature = "nonzero_is_power_of_two", issue = "81106")]
+                #[stable(feature = "nonzero_is_power_of_two", since = "1.59.0")]
                 #[inline]
                 pub const fn is_power_of_two(self) -> bool {
                     // LLVM 11 normalizes `unchecked_sub(x, 1) & x == 0` to the implementation seen here.
index baf9948857bbe1e0c2d96eeaad6827e0727bebcd..4eeb5e43943862dd7d7f9a57d5d3dc49a3db51c6 100644 (file)
@@ -848,6 +848,31 @@ pub fn map<U, F: FnOnce(T) -> U>(self, f: F) -> Option<U> {
         }
     }
 
+    /// Calls the provided closure with a reference to the contained value (if [`Some`]).
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// #![feature(result_option_inspect)]
+    ///
+    /// let v = vec![1, 2, 3, 4, 5];
+    ///
+    /// // prints "got: 4"
+    /// let x: Option<&usize> = v.get(3).inspect(|x| println!("got: {}", x));
+    ///
+    /// // prints nothing
+    /// let x: Option<&usize> = v.get(5).inspect(|x| println!("got: {}", x));
+    /// ```
+    #[inline]
+    #[unstable(feature = "result_option_inspect", issue = "91345")]
+    pub fn inspect<F: FnOnce(&T)>(self, f: F) -> Self {
+        if let Some(ref x) = self {
+            f(x);
+        }
+
+        self
+    }
+
     /// Returns the provided default result (if none),
     /// or applies a function to the contained value (if any).
     ///
index 8fec2e928aae2505b8154d91c813dec46c5e627d..a494c089f68ba760b8796a5c926fab7df5f3e01c 100644 (file)
@@ -854,6 +854,53 @@ pub fn map_err<F, O: FnOnce(E) -> F>(self, op: O) -> Result<T, F> {
         }
     }
 
+    /// Calls the provided closure with a reference to the contained value (if [`Ok`]).
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// #![feature(result_option_inspect)]
+    ///
+    /// let x: u8 = "4"
+    ///     .parse::<u8>()
+    ///     .inspect(|x| println!("original: {}", x))
+    ///     .map(|x| x.pow(3))
+    ///     .expect("failed to parse number");
+    /// ```
+    #[inline]
+    #[unstable(feature = "result_option_inspect", issue = "91345")]
+    pub fn inspect<F: FnOnce(&T)>(self, f: F) -> Self {
+        if let Ok(ref t) = self {
+            f(t);
+        }
+
+        self
+    }
+
+    /// Calls the provided closure with a reference to the contained error (if [`Err`]).
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// #![feature(result_option_inspect)]
+    ///
+    /// use std::{fs, io};
+    ///
+    /// fn read() -> io::Result<String> {
+    ///     fs::read_to_string("address.txt")
+    ///         .inspect_err(|e| eprintln!("failed to read file: {}", e))
+    /// }
+    /// ```
+    #[inline]
+    #[unstable(feature = "result_option_inspect", issue = "91345")]
+    pub fn inspect_err<F: FnOnce(&E)>(self, f: F) -> Self {
+        if let Err(ref e) = self {
+            f(e);
+        }
+
+        self
+    }
+
     /////////////////////////////////////////////////////////////////////////
     // Iterator constructors
     /////////////////////////////////////////////////////////////////////////
index 6c21a5e802026b858073de5ebe0f2abdc27377cc..32bd22846e7dd4c7749e231c2b5692efe124aa85 100644 (file)
@@ -61,36 +61,26 @@ fn safe_get(xs: &[u8], i: usize) -> u8 {
         }
 
         let mut i = 0;
+        let mut valid_up_to = 0;
         while i < self.source.len() {
-            let i_ = i;
-
-            // SAFETY: `i` starts at `0`, is less than `self.source.len()`, and
-            // only increases, so `0 <= i < self.source.len()`.
+            // SAFETY: `i < self.source.len()` per previous line.
+            // For some reason the following are both significantly slower:
+            // while let Some(&byte) = self.source.get(i) {
+            // while let Some(byte) = self.source.get(i).copied() {
             let byte = unsafe { *self.source.get_unchecked(i) };
             i += 1;
 
             if byte < 128 {
+                // This could be a `1 => ...` case in the match below, but for
+                // the common case of all-ASCII inputs, we bypass loading the
+                // sizeable UTF8_CHAR_WIDTH table into cache.
             } else {
                 let w = utf8_char_width(byte);
 
-                macro_rules! error {
-                    () => {{
-                        // SAFETY: We have checked up to `i` that source is valid UTF-8.
-                        unsafe {
-                            let r = Utf8LossyChunk {
-                                valid: from_utf8_unchecked(&self.source[0..i_]),
-                                broken: &self.source[i_..i],
-                            };
-                            self.source = &self.source[i..];
-                            return Some(r);
-                        }
-                    }};
-                }
-
                 match w {
                     2 => {
                         if safe_get(self.source, i) & 192 != TAG_CONT_U8 {
-                            error!();
+                            break;
                         }
                         i += 1;
                     }
@@ -100,13 +90,11 @@ macro_rules! error {
                             (0xE1..=0xEC, 0x80..=0xBF) => (),
                             (0xED, 0x80..=0x9F) => (),
                             (0xEE..=0xEF, 0x80..=0xBF) => (),
-                            _ => {
-                                error!();
-                            }
+                            _ => break,
                         }
                         i += 1;
                         if safe_get(self.source, i) & 192 != TAG_CONT_U8 {
-                            error!();
+                            break;
                         }
                         i += 1;
                     }
@@ -115,34 +103,45 @@ macro_rules! error {
                             (0xF0, 0x90..=0xBF) => (),
                             (0xF1..=0xF3, 0x80..=0xBF) => (),
                             (0xF4, 0x80..=0x8F) => (),
-                            _ => {
-                                error!();
-                            }
+                            _ => break,
                         }
                         i += 1;
                         if safe_get(self.source, i) & 192 != TAG_CONT_U8 {
-                            error!();
+                            break;
                         }
                         i += 1;
                         if safe_get(self.source, i) & 192 != TAG_CONT_U8 {
-                            error!();
+                            break;
                         }
                         i += 1;
                     }
-                    _ => {
-                        error!();
-                    }
+                    _ => break,
                 }
             }
+
+            valid_up_to = i;
         }
 
-        let r = Utf8LossyChunk {
-            // SAFETY: We have checked that the entire source is valid UTF-8.
-            valid: unsafe { from_utf8_unchecked(self.source) },
-            broken: &[],
-        };
-        self.source = &[];
-        Some(r)
+        // SAFETY: `i <= self.source.len()` because it is only ever incremented
+        // via `i += 1` and in between every single one of those increments, `i`
+        // is compared against `self.source.len()`. That happens either
+        // literally by `i < self.source.len()` in the while-loop's condition,
+        // or indirectly by `safe_get(self.source, i) & 192 != TAG_CONT_U8`. The
+        // loop is terminated as soon as the latest `i += 1` has made `i` no
+        // longer less than `self.source.len()`, which means it'll be at most
+        // equal to `self.source.len()`.
+        let (inspected, remaining) = unsafe { self.source.split_at_unchecked(i) };
+        self.source = remaining;
+
+        // SAFETY: `valid_up_to <= i` because it is only ever assigned via
+        // `valid_up_to = i` and `i` only increases.
+        let (valid, broken) = unsafe { inspected.split_at_unchecked(valid_up_to) };
+
+        Some(Utf8LossyChunk {
+            // SAFETY: All bytes up to `valid_up_to` are valid UTF-8.
+            valid: unsafe { from_utf8_unchecked(valid) },
+            broken,
+        })
     }
 }
 
index be9c41a491b8e8f68b33e24c6b3a3fdc480185e7..b2ea86d699aa6bf6f88c4dce209189e830ae241e 100644 (file)
@@ -244,22 +244,23 @@ macro_rules! next {
 
 // https://tools.ietf.org/html/rfc3629
 const UTF8_CHAR_WIDTH: &[u8; 256] = &[
-    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
-    1, // 0x1F
-    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
-    1, // 0x3F
-    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
-    1, // 0x5F
-    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
-    1, // 0x7F
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    0, // 0x9F
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    0, // 0xBF
-    0, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
-    2, // 0xDF
-    3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, // 0xEF
-    4, 4, 4, 4, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 0xFF
+    // 1  2  3  4  5  6  7  8  9  A  B  C  D  E  F
+    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0
+    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 1
+    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 2
+    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 3
+    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 4
+    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 5
+    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 6
+    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 7
+    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, // 9
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // A
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // B
+    0, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, // C
+    2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, // D
+    3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, // E
+    4, 4, 4, 4, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // F
 ];
 
 /// Given a first byte, determines how many bytes are in this UTF-8 character.
index 4cd79687b53d4c372ace346ad2e67effc279ce91..f419f9cec12f8555df3281eae5019b75f4b88ea5 100644 (file)
@@ -34,6 +34,7 @@ fn test_chain(xs: &[i32], ys: &[i32]) {
             iter.advance_by(i).unwrap();
             assert_eq!(iter.next(), Some(&xs[i]));
             assert_eq!(iter.advance_by(100), Err(len - i - 1));
+            iter.advance_by(0).unwrap();
         }
 
         for i in 0..ys.len() {
@@ -41,14 +42,17 @@ fn test_chain(xs: &[i32], ys: &[i32]) {
             iter.advance_by(xs.len() + i).unwrap();
             assert_eq!(iter.next(), Some(&ys[i]));
             assert_eq!(iter.advance_by(100), Err(ys.len() - i - 1));
+            iter.advance_by(0).unwrap();
         }
 
         let mut iter = xs.iter().chain(ys);
         iter.advance_by(len).unwrap();
         assert_eq!(iter.next(), None);
+        iter.advance_by(0).unwrap();
 
         let mut iter = xs.iter().chain(ys);
         assert_eq!(iter.advance_by(len + 1), Err(len));
+        iter.advance_by(0).unwrap();
     }
 
     test_chain(&[], &[]);
@@ -67,6 +71,7 @@ fn test_chain(xs: &[i32], ys: &[i32]) {
             iter.advance_back_by(i).unwrap();
             assert_eq!(iter.next_back(), Some(&ys[ys.len() - i - 1]));
             assert_eq!(iter.advance_back_by(100), Err(len - i - 1));
+            iter.advance_back_by(0).unwrap();
         }
 
         for i in 0..xs.len() {
@@ -74,14 +79,17 @@ fn test_chain(xs: &[i32], ys: &[i32]) {
             iter.advance_back_by(ys.len() + i).unwrap();
             assert_eq!(iter.next_back(), Some(&xs[xs.len() - i - 1]));
             assert_eq!(iter.advance_back_by(100), Err(xs.len() - i - 1));
+            iter.advance_back_by(0).unwrap();
         }
 
         let mut iter = xs.iter().chain(ys);
         iter.advance_back_by(len).unwrap();
         assert_eq!(iter.next_back(), None);
+        iter.advance_back_by(0).unwrap();
 
         let mut iter = xs.iter().chain(ys);
         assert_eq!(iter.advance_back_by(len + 1), Err(len));
+        iter.advance_back_by(0).unwrap();
     }
 
     test_chain(&[], &[]);
index 4ae50a2f06681582046d0add9cc74c250e9b6ec1..cd6513327f00e242728906e3b99dae2c7f534cc5 100644 (file)
@@ -61,6 +61,7 @@ fn test_flatten_try_folds() {
 #[test]
 fn test_flatten_advance_by() {
     let mut it = once(0..10).chain(once(10..30)).chain(once(30..40)).flatten();
+
     it.advance_by(5).unwrap();
     assert_eq!(it.next(), Some(5));
     it.advance_by(9).unwrap();
@@ -72,6 +73,8 @@ fn test_flatten_advance_by() {
 
     assert_eq!(it.advance_by(usize::MAX), Err(9));
     assert_eq!(it.advance_back_by(usize::MAX), Err(0));
+    it.advance_by(0).unwrap();
+    it.advance_back_by(0).unwrap();
     assert_eq!(it.size_hint(), (0, Some(0)));
 }
 
index cf60057a1644ad1977b85771367239f298ce3f18..0c464bdd03a2202224d6692e464e24f66eb8709b 100644 (file)
@@ -69,6 +69,17 @@ fn test_iterator_skip_nth() {
     assert_eq!(it.nth(0), None);
 }
 
+#[test]
+fn test_skip_advance_by() {
+    assert_eq!((0..0).skip(10).advance_by(0), Ok(()));
+    assert_eq!((0..0).skip(10).advance_by(1), Err(0));
+    assert_eq!((0u128..(usize::MAX as u128) + 1).skip(usize::MAX).advance_by(usize::MAX), Err(1));
+    assert_eq!((0u128..u128::MAX).skip(usize::MAX).advance_by(1), Ok(()));
+
+    assert_eq!((0..2).skip(1).advance_back_by(10), Err(1));
+    assert_eq!((0..0).skip(1).advance_back_by(0), Ok(()));
+}
+
 #[test]
 fn test_iterator_skip_count() {
     let xs = [0, 1, 2, 3, 5, 13, 15, 16, 17, 19, 20, 30];
index 89f9cb1e2ed1bd6af4597e3f8e4aa4ace0d6598a..bfb659f0a83780cab58bedecc1bc9c0dd68890ae 100644 (file)
@@ -73,6 +73,28 @@ fn test_iterator_take_nth_back() {
     assert_eq!(it.nth_back(1), None);
 }
 
+#[test]
+fn test_take_advance_by() {
+    let mut take = (0..10).take(3);
+    assert_eq!(take.advance_by(2), Ok(()));
+    assert_eq!(take.next(), Some(2));
+    assert_eq!(take.advance_by(1), Err(0));
+
+    assert_eq!((0..0).take(10).advance_by(0), Ok(()));
+    assert_eq!((0..0).take(10).advance_by(1), Err(0));
+    assert_eq!((0..10).take(4).advance_by(5), Err(4));
+
+    let mut take = (0..10).take(3);
+    assert_eq!(take.advance_back_by(2), Ok(()));
+    assert_eq!(take.next(), Some(0));
+    assert_eq!(take.advance_back_by(1), Err(0));
+
+    assert_eq!((0..2).take(1).advance_back_by(10), Err(1));
+    assert_eq!((0..0).take(1).advance_back_by(1), Err(0));
+    assert_eq!((0..0).take(1).advance_back_by(0), Ok(()));
+    assert_eq!((0..usize::MAX).take(100).advance_back_by(usize::MAX), Err(100));
+}
+
 #[test]
 fn test_iterator_take_short() {
     let xs = [0, 1, 2, 3];
index 6b4cf33efe1ff4574e6c9a3d376d3594da71caad..84498a8eae52eb425feb786904c4509b243fb6f7 100644 (file)
@@ -300,6 +300,9 @@ fn test_range_advance_by() {
 
     assert_eq!(r.advance_by(usize::MAX), Err(usize::MAX - 2));
 
+    r.advance_by(0).unwrap();
+    r.advance_back_by(0).unwrap();
+
     let mut r = 0u128..u128::MAX;
 
     r.advance_by(usize::MAX).unwrap();
index 4563c2085c1290a91ac2c54eac284ba291b64875..00d0259321d13da0b5158bec8f8de17600235ced 100644 (file)
@@ -10,6 +10,7 @@
 #![feature(const_assume)]
 #![feature(const_cell_into_inner)]
 #![feature(const_convert)]
+#![feature(const_maybe_uninit_as_mut_ptr)]
 #![feature(const_maybe_uninit_assume_init)]
 #![feature(const_ptr_read)]
 #![feature(const_ptr_write)]
index c780bb32ca96d89d818ead5eec654d592aedc00a..3b13dc0832fa4963905bc842c8518376c4744ed6 100644 (file)
@@ -269,3 +269,35 @@ fn uninit_const_assume_init_read() {
     const FOO: u32 = unsafe { MaybeUninit::new(42).assume_init_read() };
     assert_eq!(FOO, 42);
 }
+
+#[test]
+fn const_maybe_uninit() {
+    use std::ptr;
+
+    #[derive(Debug, PartialEq)]
+    struct Foo {
+        x: u8,
+        y: u8,
+    }
+
+    const FIELD_BY_FIELD: Foo = unsafe {
+        let mut val = MaybeUninit::uninit();
+        init_y(&mut val); // order shouldn't matter
+        init_x(&mut val);
+        val.assume_init()
+    };
+
+    const fn init_x(foo: &mut MaybeUninit<Foo>) {
+        unsafe {
+            *ptr::addr_of_mut!((*foo.as_mut_ptr()).x) = 1;
+        }
+    }
+
+    const fn init_y(foo: &mut MaybeUninit<Foo>) {
+        unsafe {
+            *ptr::addr_of_mut!((*foo.as_mut_ptr()).y) = 2;
+        }
+    }
+
+    assert_eq!(FIELD_BY_FIELD, Foo { x: 1, y: 2 });
+}
index 8d05e47edf489f7add51dcf9d43514177166a607..66f03c68cbe017de7bb7e40a73a0c55d63a41db2 100644 (file)
@@ -154,6 +154,7 @@ fn test_iterator_advance_by() {
     assert_eq!(iter.as_slice(), &v[3..]);
     iter.advance_by(2).unwrap();
     assert_eq!(iter.as_slice(), &[]);
+    iter.advance_by(0).unwrap();
 }
 
 #[test]
@@ -175,6 +176,7 @@ fn test_iterator_advance_back_by() {
     assert_eq!(iter.as_slice(), &v[..v.len() - 3]);
     iter.advance_back_by(2).unwrap();
     assert_eq!(iter.as_slice(), &[]);
+    iter.advance_back_by(0).unwrap();
 }
 
 #[test]
index 8f43e902a87ed3b33057dbf39caeb4b613eeef95..f71117483214297ba4c5cc4d8300a2cb14673845 100644 (file)
@@ -15,8 +15,8 @@ cfg-if = { version = "0.1.8", features = ['rustc-dep-of-std'] }
 panic_unwind = { path = "../panic_unwind", optional = true }
 panic_abort = { path = "../panic_abort" }
 core = { path = "../core" }
-libc = { version = "0.2.106", default-features = false, features = ['rustc-dep-of-std'] }
-compiler_builtins = { version = "0.1.52" }
+libc = { version = "0.2.108", default-features = false, features = ['rustc-dep-of-std'] }
+compiler_builtins = { version = "0.1.55" }
 profiler_builtins = { path = "../profiler_builtins", optional = true }
 unwind = { path = "../unwind" }
 hashbrown = { version = "0.11", default-features = false, features = ['rustc-dep-of-std'] }
index be35ab0ca1e66cf62a34cedf54d90a7c99085a2d..31d1e3c1e42ee5b3af37470867aea9f20087fa89 100644 (file)
@@ -543,6 +543,16 @@ fn is_symlink_file(&self) -> bool {
 ///     Ok(())
 /// }
 /// ```
+///
+/// # Limitations
+///
+/// Windows treats symlink creation as a [privileged action][symlink-security],
+/// therefore this function is likely to fail unless the user makes changes to
+/// their system to permit symlink creation. Users can try enabling Developer
+/// Mode, granting the `SeCreateSymbolicLinkPrivilege` privilege, or running
+/// the process as an administrator.
+///
+/// [symlink-security]: https://docs.microsoft.com/en-us/windows/security/threat-protection/security-policy-settings/create-symbolic-links
 #[stable(feature = "symlink", since = "1.1.0")]
 pub fn symlink_file<P: AsRef<Path>, Q: AsRef<Path>>(original: P, link: Q) -> io::Result<()> {
     sys::fs::symlink_inner(original.as_ref(), link.as_ref(), false)
@@ -572,6 +582,16 @@ pub fn symlink_file<P: AsRef<Path>, Q: AsRef<Path>>(original: P, link: Q) -> io:
 ///     Ok(())
 /// }
 /// ```
+///
+/// # Limitations
+///
+/// Windows treats symlink creation as a [privileged action][symlink-security],
+/// therefore this function is likely to fail unless the user makes changes to
+/// their system to permit symlink creation. Users can try enabling Developer
+/// Mode, granting the `SeCreateSymbolicLinkPrivilege` privilege, or running
+/// the process as an administrator.
+///
+/// [symlink-security]: https://docs.microsoft.com/en-us/windows/security/threat-protection/security-policy-settings/create-symbolic-links
 #[stable(feature = "symlink", since = "1.1.0")]
 pub fn symlink_dir<P: AsRef<Path>, Q: AsRef<Path>>(original: P, link: Q) -> io::Result<()> {
     sys::fs::symlink_inner(original.as_ref(), link.as_ref(), true)
index 6a46525f682c4a69860c8f1232112519e291e708..73ff10ab8a221ccad212d9f231caa13fbc5b333d 100644 (file)
 
 #![cfg(target_os = "android")]
 
-use libc::{c_int, c_void, sighandler_t, size_t, ssize_t};
-use libc::{ftruncate, pread, pwrite};
+use libc::{c_int, sighandler_t};
 
-use super::{cvt, cvt_r, weak::weak};
-use crate::io;
+use super::weak::weak;
 
 // The `log2` and `log2f` functions apparently appeared in android-18, or at
 // least you can see they're not present in the android-17 header [1] and they
@@ -81,87 +79,3 @@ pub unsafe fn signal(signum: c_int, handler: sighandler_t) -> sighandler_t {
     let f = f.expect("neither `signal` nor `bsd_signal` symbols found");
     f(signum, handler)
 }
-
-// The `ftruncate64` symbol apparently appeared in android-12, so we do some
-// dynamic detection to see if we can figure out whether `ftruncate64` exists.
-//
-// If it doesn't we just fall back to `ftruncate`, generating an error for
-// too-large values.
-#[cfg(target_pointer_width = "32")]
-pub fn ftruncate64(fd: c_int, size: u64) -> io::Result<()> {
-    weak!(fn ftruncate64(c_int, i64) -> c_int);
-
-    unsafe {
-        match ftruncate64.get() {
-            Some(f) => cvt_r(|| f(fd, size as i64)).map(drop),
-            None => {
-                if size > i32::MAX as u64 {
-                    Err(io::Error::new_const(io::ErrorKind::InvalidInput, &"cannot truncate >2GB"))
-                } else {
-                    cvt_r(|| ftruncate(fd, size as i32)).map(drop)
-                }
-            }
-        }
-    }
-}
-
-#[cfg(target_pointer_width = "64")]
-pub fn ftruncate64(fd: c_int, size: u64) -> io::Result<()> {
-    unsafe { cvt_r(|| ftruncate(fd, size as i64)).map(drop) }
-}
-
-#[cfg(target_pointer_width = "32")]
-pub unsafe fn cvt_pread64(
-    fd: c_int,
-    buf: *mut c_void,
-    count: size_t,
-    offset: i64,
-) -> io::Result<ssize_t> {
-    use crate::convert::TryInto;
-    weak!(fn pread64(c_int, *mut c_void, size_t, i64) -> ssize_t);
-    pread64.get().map(|f| cvt(f(fd, buf, count, offset))).unwrap_or_else(|| {
-        if let Ok(o) = offset.try_into() {
-            cvt(pread(fd, buf, count, o))
-        } else {
-            Err(io::Error::new_const(io::ErrorKind::InvalidInput, &"cannot pread >2GB"))
-        }
-    })
-}
-
-#[cfg(target_pointer_width = "32")]
-pub unsafe fn cvt_pwrite64(
-    fd: c_int,
-    buf: *const c_void,
-    count: size_t,
-    offset: i64,
-) -> io::Result<ssize_t> {
-    use crate::convert::TryInto;
-    weak!(fn pwrite64(c_int, *const c_void, size_t, i64) -> ssize_t);
-    pwrite64.get().map(|f| cvt(f(fd, buf, count, offset))).unwrap_or_else(|| {
-        if let Ok(o) = offset.try_into() {
-            cvt(pwrite(fd, buf, count, o))
-        } else {
-            Err(io::Error::new_const(io::ErrorKind::InvalidInput, &"cannot pwrite >2GB"))
-        }
-    })
-}
-
-#[cfg(target_pointer_width = "64")]
-pub unsafe fn cvt_pread64(
-    fd: c_int,
-    buf: *mut c_void,
-    count: size_t,
-    offset: i64,
-) -> io::Result<ssize_t> {
-    cvt(pread(fd, buf, count, offset))
-}
-
-#[cfg(target_pointer_width = "64")]
-pub unsafe fn cvt_pwrite64(
-    fd: c_int,
-    buf: *const c_void,
-    count: size_t,
-    offset: i64,
-) -> io::Result<ssize_t> {
-    cvt(pwrite(fd, buf, count, offset))
-}
index 0956726084e02a21f7783841e7ec17bea3faa973..ea688571a9891ff907fc96b2351ae217d936a660 100644 (file)
@@ -99,30 +99,18 @@ pub fn read_to_end(&self, buf: &mut Vec<u8>) -> io::Result<usize> {
     }
 
     pub fn read_at(&self, buf: &mut [u8], offset: u64) -> io::Result<usize> {
-        #[cfg(target_os = "android")]
-        use super::android::cvt_pread64;
-
-        #[cfg(not(target_os = "android"))]
-        unsafe fn cvt_pread64(
-            fd: c_int,
-            buf: *mut c_void,
-            count: usize,
-            offset: i64,
-        ) -> io::Result<isize> {
-            #[cfg(not(target_os = "linux"))]
-            use libc::pread as pread64;
-            #[cfg(target_os = "linux")]
-            use libc::pread64;
-            cvt(pread64(fd, buf, count, offset))
-        }
+        #[cfg(not(any(target_os = "linux", target_os = "android")))]
+        use libc::pread as pread64;
+        #[cfg(any(target_os = "linux", target_os = "android"))]
+        use libc::pread64;
 
         unsafe {
-            cvt_pread64(
+            cvt(pread64(
                 self.as_raw_fd(),
                 buf.as_mut_ptr() as *mut c_void,
                 cmp::min(buf.len(), READ_LIMIT),
                 offset as i64,
-            )
+            ))
             .map(|n| n as usize)
         }
     }
@@ -161,30 +149,18 @@ pub fn is_write_vectored(&self) -> bool {
     }
 
     pub fn write_at(&self, buf: &[u8], offset: u64) -> io::Result<usize> {
-        #[cfg(target_os = "android")]
-        use super::android::cvt_pwrite64;
-
-        #[cfg(not(target_os = "android"))]
-        unsafe fn cvt_pwrite64(
-            fd: c_int,
-            buf: *const c_void,
-            count: usize,
-            offset: i64,
-        ) -> io::Result<isize> {
-            #[cfg(not(target_os = "linux"))]
-            use libc::pwrite as pwrite64;
-            #[cfg(target_os = "linux")]
-            use libc::pwrite64;
-            cvt(pwrite64(fd, buf, count, offset))
-        }
+        #[cfg(not(any(target_os = "linux", target_os = "android")))]
+        use libc::pwrite as pwrite64;
+        #[cfg(any(target_os = "linux", target_os = "android"))]
+        use libc::pwrite64;
 
         unsafe {
-            cvt_pwrite64(
+            cvt(pwrite64(
                 self.as_raw_fd(),
                 buf.as_ptr() as *const c_void,
                 cmp::min(buf.len(), READ_LIMIT),
                 offset as i64,
-            )
+            ))
             .map(|n| n as usize)
         }
     }
index a4fff9b2e64731c7f775fcff82075bbf3b2c3784..d77e5cae3ad7366964f9e51738580cf8e8879c89 100644 (file)
@@ -46,8 +46,8 @@
 use libc::readdir_r as readdir64_r;
 #[cfg(target_os = "android")]
 use libc::{
-    dirent as dirent64, fstat as fstat64, fstatat as fstatat64, lseek64, lstat as lstat64,
-    open as open64, stat as stat64,
+    dirent as dirent64, fstat as fstat64, fstatat as fstatat64, ftruncate64, lseek64,
+    lstat as lstat64, off64_t, open as open64, stat as stat64,
 };
 #[cfg(not(any(
     target_os = "linux",
@@ -835,16 +835,10 @@ unsafe fn os_datasync(fd: c_int) -> c_int {
     }
 
     pub fn truncate(&self, size: u64) -> io::Result<()> {
-        #[cfg(target_os = "android")]
-        return crate::sys::android::ftruncate64(self.as_raw_fd(), size);
-
-        #[cfg(not(target_os = "android"))]
-        {
-            use crate::convert::TryInto;
-            let size: off64_t =
-                size.try_into().map_err(|e| io::Error::new(io::ErrorKind::InvalidInput, e))?;
-            cvt_r(|| unsafe { ftruncate64(self.as_raw_fd(), size) }).map(drop)
-        }
+        use crate::convert::TryInto;
+        let size: off64_t =
+            size.try_into().map_err(|e| io::Error::new(io::ErrorKind::InvalidInput, e))?;
+        cvt_r(|| unsafe { ftruncate64(self.as_raw_fd(), size) }).map(drop)
     }
 
     pub fn read(&self, buf: &mut [u8]) -> io::Result<usize> {
@@ -1154,7 +1148,7 @@ pub fn link(original: &Path, link: &Path) -> io::Result<()> {
         } else if #[cfg(target_os = "macos")] {
             // On MacOS, older versions (<=10.9) lack support for linkat while newer
             // versions have it. We want to use linkat if it is available, so we use weak!
-            // to check. `linkat` is preferable to `link` ecause it gives us a flag to
+            // to check. `linkat` is preferable to `link` because it gives us a flag to
             // specify how symlinks should be handled. We pass 0 as the flags argument,
             // meaning it shouldn't follow symlinks.
             weak!(fn linkat(c_int, *const c_char, c_int, *const c_char, c_int) -> c_int);
index f3155fbc0620f1ad8dbd634fb24d3be328d4cbb1..241cf89d3145c6cfcd20dac0b125b31d14cd64b9 100644 (file)
@@ -614,6 +614,9 @@ fn sendfile_splice(mode: SpliceMode, reader: RawFd, writer: RawFd, len: u64) ->
     static HAS_SENDFILE: AtomicBool = AtomicBool::new(true);
     static HAS_SPLICE: AtomicBool = AtomicBool::new(true);
 
+    // Android builds use feature level 14, but the libc wrapper for splice is
+    // gated on feature level 21+, so we have to invoke the syscall directly.
+    #[cfg(target_os = "android")]
     syscall! {
         fn splice(
             srcfd: libc::c_int,
@@ -625,6 +628,9 @@ fn splice(
         ) -> libc::ssize_t
     }
 
+    #[cfg(target_os = "linux")]
+    use libc::splice;
+
     match mode {
         SpliceMode::Sendfile if !HAS_SENDFILE.load(Ordering::Relaxed) => {
             return CopyResult::Fallback(0);
index 9ae6d12dcb95cfc9a30256f3185db31f74ee7004..a82a0172126d4fa51066b4b5313712cb61ffe812 100644 (file)
@@ -501,7 +501,7 @@ unsafe fn from_raw_fd(raw_fd: RawFd) -> Self {
 // res_init unconditionally, we call it only when we detect we're linking
 // against glibc version < 2.26. (That is, when we both know its needed and
 // believe it's thread-safe).
-#[cfg(all(target_env = "gnu", not(target_os = "vxworks")))]
+#[cfg(all(target_os = "linux", target_env = "gnu"))]
 fn on_resolver_failure() {
     use crate::sys;
 
@@ -513,5 +513,5 @@ fn on_resolver_failure() {
     }
 }
 
-#[cfg(any(not(target_env = "gnu"), target_os = "vxworks"))]
+#[cfg(not(all(target_os = "linux", target_env = "gnu")))]
 fn on_resolver_failure() {}
index 87893d269120bb0eb09adcbb253b9c5aa441c4c6..7686b61b67a892de9ae9bfa7d25ada0448c0efde 100644 (file)
@@ -2,7 +2,7 @@
 
 #![allow(unused_imports)] // lots of cfg code here
 
-#[cfg(all(test, target_env = "gnu"))]
+#[cfg(test)]
 mod tests;
 
 use crate::os::unix::prelude::*;
@@ -636,22 +636,14 @@ pub fn getppid() -> u32 {
     unsafe { libc::getppid() as u32 }
 }
 
-#[cfg(all(target_env = "gnu", not(target_os = "vxworks")))]
+#[cfg(all(target_os = "linux", target_env = "gnu"))]
 pub fn glibc_version() -> Option<(usize, usize)> {
-    if let Some(Ok(version_str)) = glibc_version_cstr().map(CStr::to_str) {
-        parse_glibc_version(version_str)
-    } else {
-        None
-    }
-}
-
-#[cfg(all(target_env = "gnu", not(target_os = "vxworks")))]
-fn glibc_version_cstr() -> Option<&'static CStr> {
-    weak! {
-        fn gnu_get_libc_version() -> *const libc::c_char
+    extern "C" {
+        fn gnu_get_libc_version() -> *const libc::c_char;
     }
-    if let Some(f) = gnu_get_libc_version.get() {
-        unsafe { Some(CStr::from_ptr(f())) }
+    let version_cstr = unsafe { CStr::from_ptr(gnu_get_libc_version()) };
+    if let Ok(version_str) = version_cstr.to_str() {
+        parse_glibc_version(version_str)
     } else {
         None
     }
@@ -659,7 +651,7 @@ fn gnu_get_libc_version() -> *const libc::c_char
 
 // Returns Some((major, minor)) if the string is a valid "x.y" version,
 // ignoring any extra dot-separated parts. Otherwise return None.
-#[cfg(all(target_env = "gnu", not(target_os = "vxworks")))]
+#[cfg(all(target_os = "linux", target_env = "gnu"))]
 fn parse_glibc_version(version: &str) -> Option<(usize, usize)> {
     let mut parsed_ints = version.split('.').map(str::parse::<usize>).fuse();
     match (parsed_ints.next(), parsed_ints.next()) {
index c445acf2722c0dc2fc5d1ea63bc31dbf789f4084..efc29955b05fea7eac7ebe2c41a4ef6c796bc120 100644 (file)
@@ -1,14 +1,12 @@
-use super::*;
-
 #[test]
-#[cfg(not(target_os = "vxworks"))]
+#[cfg(all(target_os = "linux", target_env = "gnu"))]
 fn test_glibc_version() {
     // This mostly just tests that the weak linkage doesn't panic wildly...
-    glibc_version();
+    super::glibc_version();
 }
 
 #[test]
-#[cfg(not(target_os = "vxworks"))]
+#[cfg(all(target_os = "linux", target_env = "gnu"))]
 fn test_parse_glibc_version() {
     let cases = [
         ("0.0", Some((0, 0))),
@@ -20,6 +18,6 @@ fn test_parse_glibc_version() {
         ("foo.1", None),
     ];
     for &(version_str, parsed) in cases.iter() {
-        assert_eq!(parsed, parse_glibc_version(version_str));
+        assert_eq!(parsed, super::parse_glibc_version(version_str));
     }
 }
index 3bf1493f3b8cbd6860cadddd0f7f44789b47d95d..bce35b380e677075da4f2f2a43024787b5d6b378 100644 (file)
@@ -13,7 +13,7 @@
 use crate::os::linux::process::PidFd;
 
 #[cfg(target_os = "linux")]
-use crate::sys::weak::syscall;
+use crate::sys::weak::raw_syscall;
 
 #[cfg(any(
     target_os = "macos",
@@ -162,7 +162,7 @@ struct clone_args {
             cgroup: u64,
         }
 
-        syscall! {
+        raw_syscall! {
             fn clone3(cl_args: *mut clone_args, len: libc::size_t) -> libc::c_long
         }
 
index b99eb2e553f08908effdf7385961767f75b30c88..9e02966b57c0d1066486eca3c1fadd507055a364 100644 (file)
@@ -7,7 +7,9 @@
 use crate::sys::{os, stack_overflow};
 use crate::time::Duration;
 
-#[cfg(any(target_os = "linux", target_os = "solaris", target_os = "illumos"))]
+#[cfg(all(target_os = "linux", target_env = "gnu"))]
+use crate::sys::weak::dlsym;
+#[cfg(any(target_os = "solaris", target_os = "illumos"))]
 use crate::sys::weak::weak;
 #[cfg(not(any(target_os = "l4re", target_os = "vxworks", target_os = "espidf")))]
 pub const DEFAULT_MIN_STACK_SIZE: usize = 2 * 1024 * 1024;
@@ -627,10 +629,12 @@ pub unsafe fn current() -> Option<Guard> {
 // We need that information to avoid blowing up when a small stack
 // is created in an application with big thread-local storage requirements.
 // See #6233 for rationale and details.
-#[cfg(target_os = "linux")]
-#[allow(deprecated)]
+#[cfg(all(target_os = "linux", target_env = "gnu"))]
 fn min_stack_size(attr: *const libc::pthread_attr_t) -> usize {
-    weak!(fn __pthread_get_minstack(*const libc::pthread_attr_t) -> libc::size_t);
+    // We use dlsym to avoid an ELF version dependency on GLIBC_PRIVATE. (#23628)
+    // We shouldn't really be using such an internal symbol, but there's currently
+    // no other way to account for the TLS size.
+    dlsym!(fn __pthread_get_minstack(*const libc::pthread_attr_t) -> libc::size_t);
 
     match __pthread_get_minstack.get() {
         None => libc::PTHREAD_STACK_MIN,
@@ -638,9 +642,8 @@ fn min_stack_size(attr: *const libc::pthread_attr_t) -> usize {
     }
 }
 
-// No point in looking up __pthread_get_minstack() on non-glibc
-// platforms.
-#[cfg(all(not(target_os = "linux"), not(target_os = "netbsd")))]
+// No point in looking up __pthread_get_minstack() on non-glibc platforms.
+#[cfg(all(not(all(target_os = "linux", target_env = "gnu")), not(target_os = "netbsd")))]
 fn min_stack_size(_: *const libc::pthread_attr_t) -> usize {
     libc::PTHREAD_STACK_MIN
 }
index ba432ec54941ce3140c3a2b58e50418ea6e8280a..32072affe8af45f20c8862e23f73fe7fa059b5a2 100644 (file)
@@ -6,7 +6,7 @@
 //! detection.
 //!
 //! One option to use here is weak linkage, but that is unfortunately only
-//! really workable on Linux. Hence, use dlsym to get the symbol value at
+//! really workable with ELF. Otherwise, use dlsym to get the symbol value at
 //! runtime. This is also done for compatibility with older versions of glibc,
 //! and to avoid creating dependencies on GLIBC_PRIVATE symbols. It assumes that
 //! we've been dynamically linked to the library the symbol comes from, but that
@@ -14,7 +14,8 @@
 //!
 //! A long time ago this used weak linkage for the __pthread_get_minstack
 //! symbol, but that caused Debian to detect an unnecessarily strict versioned
-//! dependency on libc6 (#23628).
+//! dependency on libc6 (#23628) because it is GLIBC_PRIVATE. We now use `dlsym`
+//! for a runtime lookup of that symbol to avoid the ELF versioned dependency.
 
 // There are a variety of `#[cfg]`s controlling which targets are involved in
 // each instance of `weak!` and `syscall!`. Rather than trying to unify all of
 #![allow(dead_code, unused_macros)]
 
 use crate::ffi::CStr;
-use crate::marker;
+use crate::marker::PhantomData;
 use crate::mem;
 use crate::sync::atomic::{self, AtomicUsize, Ordering};
 
+// We can use true weak linkage on ELF targets.
+#[cfg(not(any(target_os = "macos", target_os = "ios")))]
 pub(crate) macro weak {
     (fn $name:ident($($t:ty),*) -> $ret:ty) => (
-        #[allow(non_upper_case_globals)]
-        static $name: crate::sys::weak::Weak<unsafe extern "C" fn($($t),*) -> $ret> =
-            crate::sys::weak::Weak::new(concat!(stringify!($name), '\0'));
+        let ref $name: ExternWeak<unsafe extern "C" fn($($t),*) -> $ret> = {
+            extern "C" {
+                #[linkage = "extern_weak"]
+                static $name: *const libc::c_void;
+            }
+            #[allow(unused_unsafe)]
+            ExternWeak::new(unsafe { $name })
+        };
     )
 }
 
-pub struct Weak<F> {
+// On non-ELF targets, use the dlsym approximation of weak linkage.
+#[cfg(any(target_os = "macos", target_os = "ios"))]
+pub(crate) use self::dlsym as weak;
+
+pub(crate) struct ExternWeak<F> {
+    weak_ptr: *const libc::c_void,
+    _marker: PhantomData<F>,
+}
+
+impl<F> ExternWeak<F> {
+    #[inline]
+    pub(crate) fn new(weak_ptr: *const libc::c_void) -> Self {
+        ExternWeak { weak_ptr, _marker: PhantomData }
+    }
+}
+
+impl<F> ExternWeak<F> {
+    #[inline]
+    pub(crate) fn get(&self) -> Option<F> {
+        unsafe {
+            if self.weak_ptr.is_null() {
+                None
+            } else {
+                Some(mem::transmute_copy::<*const libc::c_void, F>(&self.weak_ptr))
+            }
+        }
+    }
+}
+
+pub(crate) macro dlsym {
+    (fn $name:ident($($t:ty),*) -> $ret:ty) => (
+        static DLSYM: DlsymWeak<unsafe extern "C" fn($($t),*) -> $ret> =
+            DlsymWeak::new(concat!(stringify!($name), '\0'));
+        let $name = &DLSYM;
+    )
+}
+
+pub(crate) struct DlsymWeak<F> {
     name: &'static str,
     addr: AtomicUsize,
-    _marker: marker::PhantomData<F>,
+    _marker: PhantomData<F>,
 }
 
-impl<F> Weak<F> {
-    pub const fn new(name: &'static str) -> Weak<F> {
-        Weak { name, addr: AtomicUsize::new(1), _marker: marker::PhantomData }
+impl<F> DlsymWeak<F> {
+    pub(crate) const fn new(name: &'static str) -> Self {
+        DlsymWeak { name, addr: AtomicUsize::new(1), _marker: PhantomData }
     }
 
-    pub fn get(&self) -> Option<F> {
-        assert_eq!(mem::size_of::<F>(), mem::size_of::<usize>());
+    #[inline]
+    pub(crate) fn get(&self) -> Option<F> {
         unsafe {
             // Relaxed is fine here because we fence before reading through the
             // pointer (see the comment below).
@@ -82,6 +127,8 @@ pub fn get(&self) -> Option<F> {
     // Cold because it should only happen during first-time initalization.
     #[cold]
     unsafe fn initialize(&self) -> Option<F> {
+        assert_eq!(mem::size_of::<F>(), mem::size_of::<usize>());
+
         let val = fetch(self.name);
         // This synchronizes with the acquire fence in `get`.
         self.addr.store(val, Ordering::Release);
@@ -105,14 +152,12 @@ unsafe fn fetch(name: &str) -> usize {
 pub(crate) macro syscall {
     (fn $name:ident($($arg_name:ident: $t:ty),*) -> $ret:ty) => (
         unsafe fn $name($($arg_name: $t),*) -> $ret {
-            use super::os;
-
             weak! { fn $name($($t),*) -> $ret }
 
             if let Some(fun) = $name.get() {
                 fun($($arg_name),*)
             } else {
-                os::set_errno(libc::ENOSYS);
+                super::os::set_errno(libc::ENOSYS);
                 -1
             }
         }
@@ -123,11 +168,6 @@ unsafe fn $name($($arg_name: $t),*) -> $ret {
 pub(crate) macro syscall {
     (fn $name:ident($($arg_name:ident: $t:ty),*) -> $ret:ty) => (
         unsafe fn $name($($arg_name:$t),*) -> $ret {
-            use weak;
-            // This looks like a hack, but concat_idents only accepts idents
-            // (not paths).
-            use libc::*;
-
             weak! { fn $name($($t),*) -> $ret }
 
             // Use a weak symbol from libc when possible, allowing `LD_PRELOAD`
@@ -135,6 +175,10 @@ unsafe fn $name($($arg_name:$t),*) -> $ret {
             if let Some(fun) = $name.get() {
                 fun($($arg_name),*)
             } else {
+                // This looks like a hack, but concat_idents only accepts idents
+                // (not paths).
+                use libc::*;
+
                 syscall(
                     concat_idents!(SYS_, $name),
                     $($arg_name),*
@@ -143,3 +187,19 @@ unsafe fn $name($($arg_name:$t),*) -> $ret {
         }
     )
 }
+
+#[cfg(any(target_os = "linux", target_os = "android"))]
+pub(crate) macro raw_syscall {
+    (fn $name:ident($($arg_name:ident: $t:ty),*) -> $ret:ty) => (
+        unsafe fn $name($($arg_name:$t),*) -> $ret {
+            // This looks like a hack, but concat_idents only accepts idents
+            // (not paths).
+            use libc::*;
+
+            syscall(
+                concat_idents!(SYS_, $name),
+                $($arg_name),*
+            ) as $ret
+        }
+    )
+}
index 39b53b51bfa637468b7ca6147b4a2ec7b8a91f1e..343d3ef8dc5388bf0a2a304b8bf2afe5404ffa93 100644 (file)
@@ -1460,9 +1460,12 @@ fn _assert_both<T: Send + Sync>() {}
 /// The purpose of this API is to provide an easy and portable way to query
 /// the default amount of parallelism the program should use. Among other things it
 /// does not expose information on NUMA regions, does not account for
-/// differences in (co)processor capabilities, and will not modify the program's
-/// global state in order to more accurately query the amount of available
-/// parallelism.
+/// differences in (co)processor capabilities or current system load,
+/// and will not modify the program's global state in order to more accurately
+/// query the amount of available parallelism.
+///
+/// Where both fixed steady-state and burst limits are available the steady-state
+/// capacity will be used to ensure more predictable latencies.
 ///
 /// Resource limits can be changed during the runtime of a program, therefore the value is
 /// not cached and instead recomputed every time this function is called. It should not be
index 3b3c8a9227d95f4c98f76ddf150867eeff761d75..1667dfc3f8544ad3f2ac2bb0519d055a914e956d 100644 (file)
@@ -493,7 +493,7 @@ fn dir_is_empty(dir: &Path) -> bool {
 
         // NOTE: The check for the empty directory is here because when running x.py the first time,
         // the submodule won't be checked out. Check it out now so we can build it.
-        if !channel::GitInfo::new(false, relative_path).is_git() && !dir_is_empty(&absolute_path) {
+        if !channel::GitInfo::new(false, &absolute_path).is_git() && !dir_is_empty(&absolute_path) {
             return;
         }
 
index 70900a0bab942fa514533aec0fc3f884c8ab89e2..6be53fb4cfed4c53fd5eca1f7fdf74d5f4eb9593 100644 (file)
@@ -261,6 +261,16 @@ conversion, so type inference fails because the type is not unique. Please note
 that you must write the `(())` in one sequence without intermediate whitespace
 so that `rustdoc` understands you want an implicit `Result`-returning function.
 
+## Showing warnings in doctests
+
+You can show warnings in doctests by running `rustdoc --test --test-args=--show-output`
+(or, if you're using cargo, `cargo test --doc -- --show-output`).
+By default, this will still hide `unused` warnings, since so many examples use private functions;
+you can add `#![warn(unused)]` to the top of your example if you want to see unused variables or dead code warnings.
+You can also use [`#![doc(test(attr(warn(unused))))]`][test-attr] in the crate root to enable warnings globally.
+
+[test-attr]: ./the-doc-attribute.md#testattr
+
 ## Documenting macros
 
 Here’s an example of documenting a macro:
index 6e52127591c76c66388d63a6abf817778ddae434..021040215437e0015697c4fd3554292193a3f08e 100644 (file)
@@ -257,22 +257,6 @@ all these files are linked from every page, changing where they are can be cumbe
 specially cache them. This flag will rename all these files in the output to include the suffix in
 the filename. For example, `light.css` would become `light-suf.css` with the above command.
 
-### `--display-doctest-warnings`: display warnings when documenting or running documentation tests
-
-Using this flag looks like this:
-
-```bash
-$ rustdoc src/lib.rs -Z unstable-options --display-doctest-warnings
-$ rustdoc --test src/lib.rs -Z unstable-options --display-doctest-warnings
-```
-
-The intent behind this flag is to allow the user to see warnings that occur within their library or
-their documentation tests, which are usually suppressed. However, [due to a
-bug][issue-display-warnings], this flag doesn't 100% work as intended. See the linked issue for
-details.
-
-[issue-display-warnings]: https://github.com/rust-lang/rust/issues/41574
-
 ### `--extern-html-root-url`: control how rustdoc links to non-local crates
 
 Using this flag looks like this:
index f7c2a26f01817016048f95d961878a64eb50effa..f4d1ca0ec691130ffe2bcd74006655ae213d1012 100644 (file)
@@ -20,7 +20,7 @@ This document describes how to enable and use the LLVM instrumentation-based cov
 When `-Z instrument-coverage` is enabled, the Rust compiler enhances rust-based libraries and binaries by:
 
 -   Automatically injecting calls to an LLVM intrinsic ([`llvm.instrprof.increment`]), at functions and branches in compiled code, to increment counters when conditional sections of code are executed.
--   Embedding additional information in the data section of each library and binary (using the [LLVM Code Coverage Mapping Format] _Version 4_, supported _only_ in LLVM 11 and up), to define the code regions (start and end positions in the source code) being counted.
+-   Embedding additional information in the data section of each library and binary (using the [LLVM Code Coverage Mapping Format] _Version 5_, if compiling with LLVM 12, or _Version 6_, if compiling with LLVM 13 or higher), to define the code regions (start and end positions in the source code) being counted.
 
 When running a coverage-instrumented program, the counter values are written to a `profraw` file at program termination. LLVM bundles tools that read the counter results, combine those results with the coverage map (embedded in the program binary), and generate coverage reports in multiple formats.
 
@@ -123,7 +123,7 @@ If `LLVM_PROFILE_FILE` contains a path to a non-existent directory, the missing
 
 ## Installing LLVM coverage tools
 
-LLVM's supplies two tools—`llvm-profdata` and `llvm-cov`—that process coverage data and generate reports. There are several ways to find and/or install these tools, but note that the coverage mapping data generated by the Rust compiler requires LLVM version 11 or higher. (`llvm-cov --version` typically shows the tool's LLVM version number.):
+LLVM's supplies two tools—`llvm-profdata` and `llvm-cov`—that process coverage data and generate reports. There are several ways to find and/or install these tools, but note that the coverage mapping data generated by the Rust compiler requires LLVM version 12 or higher. (`llvm-cov --version` typically shows the tool's LLVM version number.):
 
 -   The LLVM tools may be installed (or installable) directly to your OS (such as via `apt-get`, for Linux).
 -   If you are building the Rust compiler from source, you can optionally use the bundled LLVM tools, built from source. Those tool binaries can typically be found in your build platform directory at something like: `rust/build/x86_64-unknown-linux-gnu/llvm/bin/llvm-*`.
index 2ccf17387d1c701febec22a676ea264bd07bb845..04fe1dccce44bfa8ce56da0cb9e4c4916f187ed8 100644 (file)
@@ -449,7 +449,7 @@ fn param_env_to_generics(
                         _ => false,
                     }
             })
-            .map(|p| p.fold_with(&mut replacer));
+            .map(|p| p.fold_with(&mut replacer).into_ok());
 
         let mut generic_params =
             (tcx.generics_of(item_def_id), tcx.explicit_predicates_of(item_def_id))
@@ -714,11 +714,11 @@ fn tcx<'b>(&'b self) -> TyCtxt<'tcx> {
         self.tcx
     }
 
-    fn fold_region(&mut self, r: ty::Region<'tcx>) -> ty::Region<'tcx> {
-        (match *r {
+    fn fold_region(&mut self, r: ty::Region<'tcx>) -> Result<ty::Region<'tcx>, Self::Error> {
+        Ok((match *r {
             ty::ReVar(vid) => self.vid_to_region.get(&vid).cloned(),
             _ => None,
         })
-        .unwrap_or_else(|| r.super_fold_with(self))
+        .unwrap_or_else(|| r.super_fold_with(self).into_ok()))
     }
 }
index d4bf93bb40931178d5236796ed61fdefefa3d316..ba67030d59fb0c999226ba998faeff69eb146dd3 100644 (file)
@@ -359,13 +359,10 @@ fn merge_attrs(
     }
 
     let impl_item = match did.as_local() {
-        Some(did) => {
-            let hir_id = tcx.hir().local_def_id_to_hir_id(did);
-            match &tcx.hir().expect_item(hir_id).kind {
-                hir::ItemKind::Impl(impl_) => Some(impl_),
-                _ => panic!("`DefID` passed to `build_impl` is not an `impl"),
-            }
-        }
+        Some(did) => match &tcx.hir().expect_item(did).kind {
+            hir::ItemKind::Impl(impl_) => Some(impl_),
+            _ => panic!("`DefID` passed to `build_impl` is not an `impl"),
+        },
         None => None,
     };
 
index 5c893e44a9fc3bc28ab040ba62309a40843e1ede..9b05716a67bc28a3b322a6319414a33c3852b5a6 100644 (file)
 
 use utils::*;
 
-crate use utils::{get_auto_trait_and_blanket_impls, krate, register_res};
-
-crate use self::types::FnRetTy::*;
-crate use self::types::ItemKind::*;
-crate use self::types::SelfTy::*;
-crate use self::types::Type::*;
-crate use self::types::Visibility::{Inherited, Public};
 crate use self::types::*;
+crate use self::utils::{get_auto_trait_and_blanket_impls, krate, register_res};
 
 crate trait Clean<T> {
     fn clean(&self, cx: &mut DocContext<'_>) -> T;
@@ -956,7 +950,7 @@ fn clean(&self, cx: &mut DocContext<'_>) -> Item {
 
             let what_rustc_thinks =
                 Item::from_def_id_and_parts(local_did, Some(self.ident.name), inner, cx);
-            let parent_item = cx.tcx.hir().expect_item(cx.tcx.hir().get_parent_item(self.hir_id()));
+            let parent_item = cx.tcx.hir().expect_item(cx.tcx.hir().get_parent_did(self.hir_id()));
             if let hir::ItemKind::Impl(impl_) = &parent_item.kind {
                 if impl_.of_trait.is_some() {
                     // Trait impl items always inherit the impl's visibility --
@@ -1195,9 +1189,8 @@ fn maybe_expand_private_type_alias(cx: &mut DocContext<'_>, path: &hir::Path<'_>
     let Res::Def(DefKind::TyAlias, def_id) = path.res else { return None };
     // Substitute private type aliases
     let Some(def_id) = def_id.as_local() else { return None };
-    let hir_id = cx.tcx.hir().local_def_id_to_hir_id(def_id);
     let alias = if !cx.cache.access_levels.is_exported(def_id.to_def_id()) {
-        &cx.tcx.hir().expect_item(hir_id).kind
+        &cx.tcx.hir().expect_item(def_id).kind
     } else {
         return None;
     };
@@ -1411,12 +1404,12 @@ fn clean(&self, cx: &mut DocContext<'_>) -> Type {
                 };
                 inline::record_extern_fqn(cx, did, kind);
                 let path = external_path(cx, did, false, vec![], substs);
-                ResolvedPath { path }
+                Type::Path { path }
             }
             ty::Foreign(did) => {
                 inline::record_extern_fqn(cx, did, ItemType::ForeignType);
                 let path = external_path(cx, did, false, vec![], InternalSubsts::empty());
-                ResolvedPath { path }
+                Type::Path { path }
             }
             ty::Dynamic(obj, ref reg) => {
                 // HACK: pick the first `did` as the `did` of the trait object. Someone
index 9e088ac72ad2fbf13731e5b17fb78ddac5dbbe05..11dd140504ae381e7c3f6295827b5f9fc3a569f8 100644 (file)
@@ -34,7 +34,6 @@
 use crate::clean::cfg::Cfg;
 use crate::clean::external_path;
 use crate::clean::inline::{self, print_inlined_const};
-use crate::clean::types::Type::{QPath, ResolvedPath};
 use crate::clean::utils::{is_literal_expr, print_const_expr, print_evaluated_const};
 use crate::clean::Clean;
 use crate::core::DocContext;
 use crate::html::render::cache::ExternalLocation;
 use crate::html::render::Context;
 
-use self::FnRetTy::*;
-use self::ItemKind::*;
-use self::SelfTy::*;
-use self::Type::*;
+crate use self::FnRetTy::*;
+crate use self::ItemKind::*;
+crate use self::SelfTy::*;
+crate use self::Type::{
+    Array, BareFunction, BorrowedRef, DynTrait, Generic, ImplTrait, Infer, Primitive, QPath,
+    RawPointer, Slice, Tuple,
+};
+crate use self::Visibility::{Inherited, Public};
 
 crate type ItemIdSet = FxHashSet<ItemId>;
 
@@ -1418,8 +1421,9 @@ impl FnRetTy {
 crate enum Type {
     /// A named type, which could be a trait.
     ///
-    /// This is mostly Rustdoc's version of [`hir::Path`]. It has to be different because Rustdoc's [`PathSegment`] can contain cleaned generics.
-    ResolvedPath { path: Path },
+    /// This is mostly Rustdoc's version of [`hir::Path`].
+    /// It has to be different because Rustdoc's [`PathSegment`] can contain cleaned generics.
+    Path { path: Path },
     /// A `dyn Trait` object: `dyn for<'a> Trait<'a> + Send + 'static`
     DynTrait(Vec<PolyTrait>, Option<Lifetime>),
     /// A type parameter.
@@ -1464,6 +1468,45 @@ impl FnRetTy {
 rustc_data_structures::static_assert_size!(Type, 72);
 
 impl Type {
+    /// When comparing types for equality, it can help to ignore `&` wrapping.
+    crate fn without_borrowed_ref(&self) -> &Type {
+        let mut result = self;
+        while let Type::BorrowedRef { type_, .. } = result {
+            result = &*type_;
+        }
+        result
+    }
+
+    /// Check if two types are "potentially the same".
+    /// This is different from `Eq`, because it knows that things like
+    /// `Placeholder` are possible matches for everything.
+    crate fn is_same(&self, other: &Self, cache: &Cache) -> bool {
+        match (self, other) {
+            // Recursive cases.
+            (Type::Tuple(a), Type::Tuple(b)) => {
+                a.len() == b.len() && a.iter().zip(b).all(|(a, b)| a.is_same(&b, cache))
+            }
+            (Type::Slice(a), Type::Slice(b)) => a.is_same(&b, cache),
+            (Type::Array(a, al), Type::Array(b, bl)) => al == bl && a.is_same(&b, cache),
+            (Type::RawPointer(mutability, type_), Type::RawPointer(b_mutability, b_type_)) => {
+                mutability == b_mutability && type_.is_same(&b_type_, cache)
+            }
+            (
+                Type::BorrowedRef { mutability, type_, .. },
+                Type::BorrowedRef { mutability: b_mutability, type_: b_type_, .. },
+            ) => mutability == b_mutability && type_.is_same(&b_type_, cache),
+            // Placeholders and generics are equal to all other types.
+            (Type::Infer, _) | (_, Type::Infer) => true,
+            (Type::Generic(_), _) | (_, Type::Generic(_)) => true,
+            // Other cases, such as primitives, just use recursion.
+            (a, b) => a
+                .def_id(cache)
+                .and_then(|a| Some((a, b.def_id(cache)?)))
+                .map(|(a, b)| a == b)
+                .unwrap_or(false),
+        }
+    }
+
     crate fn primitive_type(&self) -> Option<PrimitiveType> {
         match *self {
             Primitive(p) | BorrowedRef { type_: box Primitive(p), .. } => Some(p),
@@ -1485,7 +1528,7 @@ impl Type {
     /// Checks if this is a `T::Name` path for an associated type.
     crate fn is_assoc_ty(&self) -> bool {
         match self {
-            ResolvedPath { path, .. } => path.is_assoc_ty(),
+            Type::Path { path, .. } => path.is_assoc_ty(),
             _ => false,
         }
     }
@@ -1499,7 +1542,7 @@ impl Type {
 
     crate fn generics(&self) -> Option<Vec<&Type>> {
         match self {
-            ResolvedPath { path, .. } => path.generics(),
+            Type::Path { path, .. } => path.generics(),
             _ => None,
         }
     }
@@ -1522,7 +1565,7 @@ impl Type {
 
     fn inner_def_id(&self, cache: Option<&Cache>) -> Option<DefId> {
         let t: PrimitiveType = match *self {
-            ResolvedPath { ref path } => return Some(path.def_id()),
+            Type::Path { ref path } => return Some(path.def_id()),
             DynTrait(ref bounds, _) => return Some(bounds[0].trait_.def_id()),
             Primitive(p) => return cache.and_then(|c| c.primitive_locations.get(&p).cloned()),
             BorrowedRef { type_: box Generic(..), .. } => PrimitiveType::Reference,
index 1141aff41f2da46abecfcf02e03216272dfc20ef..38f53d7e0b28656b6f0deb3df34f3809823f5bed 100644 (file)
@@ -2,8 +2,7 @@
 use crate::clean::blanket_impl::BlanketImplFinder;
 use crate::clean::{
     inline, Clean, Crate, ExternalCrate, Generic, GenericArg, GenericArgs, ImportSource, Item,
-    ItemKind, Lifetime, Path, PathSegment, Primitive, PrimitiveType, ResolvedPath, Type,
-    TypeBinding, Visibility,
+    ItemKind, Lifetime, Path, PathSegment, Primitive, PrimitiveType, Type, TypeBinding, Visibility,
 };
 use crate::core::DocContext;
 use crate::formats::item_type::ItemType;
@@ -187,7 +186,7 @@ pub(super) fn external_path(
             for &did in prim.impls(tcx).iter().filter(|did| !did.is_local()) {
                 inline::build_impl(cx, None, did, None, ret);
             }
-        } else if let ResolvedPath { path } = target {
+        } else if let Type::Path { path } = target {
             let did = path.def_id();
             if !did.is_local() {
                 inline::build_impls(cx, None, did, None, ret);
@@ -362,7 +361,7 @@ fn print_const_with_custom_print_scalar(tcx: TyCtxt<'_>, ct: &'tcx ty::Const<'tc
         Res::Def(DefKind::TyParam, _) if path.segments.len() == 1 => Generic(path.segments[0].name),
         _ => {
             let _ = register_res(cx, path.res);
-            ResolvedPath { path }
+            Type::Path { path }
         }
     }
 }
index 493aa56fce6efe061a2b12ba673628625ba88731..04bcade156a9d33f8f4fdbb822ec7050a463c694 100644 (file)
@@ -136,9 +136,6 @@ fn try_from(value: &str) -> Result<Self, Self::Error> {
     ///
     /// Be aware: This option can come both from the CLI and from crate attributes!
     crate manual_passes: Vec<String>,
-    /// Whether to display warnings during doc generation or while gathering doctests. By default,
-    /// all non-rustdoc-specific lints are allowed when generating docs.
-    crate display_doctest_warnings: bool,
     /// Whether to run the `calculate-doc-coverage` pass, which counts the number of public items
     /// with and without documentation.
     crate show_coverage: bool,
@@ -197,7 +194,6 @@ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
             .field("persist_doctests", &self.persist_doctests)
             .field("default_passes", &self.default_passes)
             .field("manual_passes", &self.manual_passes)
-            .field("display_doctest_warnings", &self.display_doctest_warnings)
             .field("show_coverage", &self.show_coverage)
             .field("crate_version", &self.crate_version)
             .field("render_options", &self.render_options)
@@ -556,7 +552,7 @@ fn println_condition(condition: Condition) {
                     ))
                     .emit();
                 }
-                themes.push(StylePath { path: theme_file, disabled: true });
+                themes.push(StylePath { path: theme_file });
             }
         }
 
@@ -639,7 +635,6 @@ fn println_condition(condition: Condition) {
         let proc_macro_crate = crate_types.contains(&CrateType::ProcMacro);
         let playground_url = matches.opt_str("playground-url");
         let maybe_sysroot = matches.opt_str("sysroot").map(PathBuf::from);
-        let display_doctest_warnings = matches.opt_present("display-doctest-warnings");
         let sort_modules_alphabetically = !matches.opt_present("sort-modules-by-appearance");
         let resource_suffix = matches.opt_str("resource-suffix").unwrap_or_default();
         let enable_minification = !matches.opt_present("disable-minification");
@@ -707,7 +702,6 @@ fn println_condition(condition: Condition) {
             test_args,
             default_passes,
             manual_passes,
-            display_doctest_warnings,
             show_coverage,
             crate_version,
             test_run_directory,
index de4a3732e736bbcc68b89fadb052d71d375a56f4..56ccdfae1d8bc1bb2b62ff4254decc8aca379051 100644 (file)
@@ -38,9 +38,6 @@
 crate struct TestOptions {
     /// Whether to disable the default `extern crate my_crate;` when creating doctests.
     crate no_crate_inject: bool,
-    /// Whether to emit compilation warnings when compiling doctests. Setting this will suppress
-    /// the default `#![allow(unused)]`.
-    crate display_doctest_warnings: bool,
     /// Additional crate-level attributes to add to doctests.
     crate attrs: Vec<String>,
 }
@@ -65,6 +62,8 @@
         }
     });
 
+    debug!(?lint_opts);
+
     let crate_types =
         if options.proc_macro_crate { vec![CrateType::ProcMacro] } else { vec![CrateType::Rlib] };
 
@@ -72,7 +71,7 @@
         maybe_sysroot: options.maybe_sysroot.clone(),
         search_paths: options.libs.clone(),
         crate_types,
-        lint_opts: if !options.display_doctest_warnings { lint_opts } else { vec![] },
+        lint_opts,
         lint_cap: Some(options.lint_cap.unwrap_or(lint::Forbid)),
         cg: options.codegen_options.clone(),
         externs: options.externs.clone(),
     };
 
     let test_args = options.test_args.clone();
-    let display_doctest_warnings = options.display_doctest_warnings;
     let nocapture = options.nocapture;
     let externs = options.externs.clone();
     let json_unused_externs = options.json_unused_externs;
             let collector = global_ctxt.enter(|tcx| {
                 let crate_attrs = tcx.hir().attrs(CRATE_HIR_ID);
 
-                let mut opts = scrape_test_config(crate_attrs);
-                opts.display_doctest_warnings |= options.display_doctest_warnings;
+                let opts = scrape_test_config(crate_attrs);
                 let enable_per_target_ignores = options.enable_per_target_ignores;
                 let mut collector = Collector::new(
                     tcx.crate_name(LOCAL_CRATE),
         Err(ErrorReported) => return Err(ErrorReported),
     };
 
-    run_tests(test_args, nocapture, display_doctest_warnings, tests);
+    run_tests(test_args, nocapture, tests);
 
     // Collect and warn about unused externs, but only if we've gotten
     // reports for each doctest
     Ok(())
 }
 
-crate fn run_tests(
-    mut test_args: Vec<String>,
-    nocapture: bool,
-    display_doctest_warnings: bool,
-    tests: Vec<test::TestDescAndFn>,
-) {
+crate fn run_tests(mut test_args: Vec<String>, nocapture: bool, tests: Vec<test::TestDescAndFn>) {
     test_args.insert(0, "rustdoctest".to_string());
     if nocapture {
         test_args.push("--nocapture".to_string());
     }
-    test::test_main(
-        &test_args,
-        tests,
-        Some(test::Options::new().display_output(display_doctest_warnings)),
-    );
+    test::test_main(&test_args, tests, None);
 }
 
 // Look for `#![doc(test(no_crate_inject))]`, used by crates in the std facade.
 fn scrape_test_config(attrs: &[ast::Attribute]) -> TestOptions {
     use rustc_ast_pretty::pprust;
 
-    let mut opts =
-        TestOptions { no_crate_inject: false, display_doctest_warnings: false, attrs: Vec::new() };
+    let mut opts = TestOptions { no_crate_inject: false, attrs: Vec::new() };
 
     let test_attrs: Vec<_> = attrs
         .iter()
@@ -510,7 +497,7 @@ fn drop(&mut self) {
     let mut prog = String::new();
     let mut supports_color = false;
 
-    if opts.attrs.is_empty() && !opts.display_doctest_warnings {
+    if opts.attrs.is_empty() {
         // If there aren't any attributes supplied by #![doc(test(attr(...)))], then allow some
         // lints that are commonly triggered in doctests. The crate-level test attributes are
         // commonly used to make tests fail in case they trigger warnings, so having this there in
index 1851708096564380e3fab75ca8a3c1617e33ae59..099609d0f912e50b10a9c5a418d11ccdc4fa010e 100644 (file)
@@ -52,8 +52,7 @@ fn main() {
 fn make_test_no_crate_inject() {
     // Even if you do use the crate within the test, setting `opts.no_crate_inject` will skip
     // adding it anyway.
-    let opts =
-        TestOptions { no_crate_inject: true, display_doctest_warnings: false, attrs: vec![] };
+    let opts = TestOptions { no_crate_inject: true, attrs: vec![] };
     let input = "use asdf::qwop;
 assert_eq!(2+2, 4);";
     let expected = "#![allow(unused)]
@@ -215,20 +214,6 @@ fn make_test_dont_insert_main() {
     assert_eq!((output, len), (expected, 1));
 }
 
-#[test]
-fn make_test_display_doctest_warnings() {
-    // If the user is asking to display doctest warnings, suppress the default `allow(unused)`.
-    let mut opts = TestOptions::default();
-    opts.display_doctest_warnings = true;
-    let input = "assert_eq!(2+2, 4);";
-    let expected = "fn main() {
-assert_eq!(2+2, 4);
-}"
-    .to_string();
-    let (output, len, _) = make_test(input, None, false, &opts, DEFAULT_EDITION, None);
-    assert_eq!((output, len), (expected, 1));
-}
-
 #[test]
 fn make_test_issues_21299_33731() {
     let opts = TestOptions::default();
index 82d0002b98b180d2ae514314740d8d6fd714d4a6..8eadbf63f33d91e02cf683b857676049a1e4b90c 100644 (file)
@@ -39,7 +39,10 @@ macro_rules! try_none {
         match $e {
             Some(e) => e,
             None => {
-                return Err(Error::new(io::Error::new(io::ErrorKind::Other, "not found"), $file));
+                return Err(<crate::error::Error as crate::docfs::PathError>::new(
+                    io::Error::new(io::ErrorKind::Other, "not found"),
+                    $file,
+                ));
             }
         }
     }};
index dd13c4809bbce94bc511c4af9144f01f71f25b01..d3831450e1d87d8122a7ec2319bed199b769bbe4 100644 (file)
@@ -27,7 +27,7 @@
 #[derive(Default)]
 crate struct Cache {
     /// Maps a type ID to all known implementations for that type. This is only
-    /// recognized for intra-crate `ResolvedPath` types, and is used to print
+    /// recognized for intra-crate [`clean::Type::Path`]s, and is used to print
     /// out extra documentation on the page of an enum/struct.
     ///
     /// The values of the map are a list of implementations and documentation
@@ -401,7 +401,7 @@ fn fold_item(&mut self, item: clean::Item) -> Option<clean::Item> {
             clean::ImplItem(ref i) => {
                 self.cache.parent_is_trait_impl = i.trait_.is_some();
                 match i.for_ {
-                    clean::ResolvedPath { ref path } => {
+                    clean::Type::Path { ref path } => {
                         self.cache.parent_stack.push(path.def_id());
                         true
                     }
@@ -436,8 +436,8 @@ fn fold_item(&mut self, item: clean::Item) -> Option<clean::Item> {
             // Note: matching twice to restrict the lifetime of the `i` borrow.
             let mut dids = FxHashSet::default();
             match i.for_ {
-                clean::ResolvedPath { ref path }
-                | clean::BorrowedRef { type_: box clean::ResolvedPath { ref path }, .. } => {
+                clean::Type::Path { ref path }
+                | clean::BorrowedRef { type_: box clean::Type::Path { ref path }, .. } => {
                     dids.insert(path.def_id());
                 }
                 clean::DynTrait(ref bounds, _)
index 1ed3ba7ece05638b5fb26f972843df3f5f08fdc3..34742fac0e4b7f1155a3290dc92c4eaf96873004 100644 (file)
@@ -607,8 +607,7 @@ fn to_module_fqp(shortty: ItemType, fqp: &[String]) -> &[String] {
     }
 }
 
-/// Used when rendering a `ResolvedPath` structure. This invokes the `path`
-/// rendering function with the necessary arguments for linking to a local path.
+/// Used to render a [`clean::Path`].
 fn resolved_path<'cx>(
     w: &mut fmt::Formatter<'_>,
     did: DefId,
@@ -762,7 +761,7 @@ fn fmt_type<'cx>(
 
     match *t {
         clean::Generic(name) => write!(f, "{}", name),
-        clean::ResolvedPath { ref path } => {
+        clean::Type::Path { ref path } => {
             // Paths like `T::Output` and `Self::Output` should be rendered with all segments.
             let did = path.def_id();
             resolved_path(f, did, path, path.is_assoc_ty(), use_absolute, cx)
index 71d7cc1a09dce5b9656d6e3c9556b5db38fd6776..3d3fa3aaeaa519f803fac82b7377d1fb6fa030d5 100644 (file)
@@ -2,8 +2,8 @@
 
 use rustc_data_structures::fx::FxHashMap;
 
+use crate::error::Error;
 use crate::externalfiles::ExternalHtml;
-use crate::html::escape::Escape;
 use crate::html::format::{Buffer, Print};
 use crate::html::render::{ensure_trailing_slash, StylePath};
 
@@ -50,10 +50,11 @@ struct PageLayout<'a> {
     static_root_path: &'a str,
     page: &'a Page<'a>,
     layout: &'a Layout,
-    style_files: String,
+    themes: Vec<String>,
     sidebar: String,
     content: String,
     krate_with_trailing_slash: String,
+    crate rustdoc_version: &'a str,
 }
 
 crate fn render<T: Print, S: Print>(
@@ -66,29 +67,24 @@ struct PageLayout<'a> {
 ) -> String {
     let static_root_path = page.get_static_root_path();
     let krate_with_trailing_slash = ensure_trailing_slash(&layout.krate).to_string();
-    let style_files = style_files
+    let mut themes: Vec<String> = style_files
         .iter()
-        .filter_map(|t| t.path.file_stem().map(|stem| (stem, t.disabled)))
-        .filter_map(|t| t.0.to_str().map(|path| (path, t.1)))
-        .map(|t| {
-            format!(
-                r#"<link rel="stylesheet" type="text/css" href="{}.css" {} {}>"#,
-                Escape(&format!("{}{}{}", static_root_path, t.0, page.resource_suffix)),
-                if t.1 { "disabled" } else { "" },
-                if t.0 == "light" { "id=\"themeStyle\"" } else { "" }
-            )
-        })
-        .collect::<String>();
+        .map(StylePath::basename)
+        .collect::<Result<_, Error>>()
+        .unwrap_or_default();
+    themes.sort();
+    let rustdoc_version = rustc_interface::util::version_str().unwrap_or("unknown version");
     let content = Buffer::html().to_display(t); // Note: This must happen before making the sidebar.
     let sidebar = Buffer::html().to_display(sidebar);
     let teractx = tera::Context::from_serialize(PageLayout {
         static_root_path,
         page,
         layout,
-        style_files,
+        themes,
         sidebar,
         content,
         krate_with_trailing_slash,
+        rustdoc_version,
     })
     .unwrap();
     templates.render("page.html", &teractx).unwrap()
index c114edf1e704c17564127dcb0f9d9a697a606d79..d12667c9e5c777c205c8f690ab4c212450fc5754 100644 (file)
@@ -218,7 +218,7 @@ fn get_index_type(clean_type: &clean::Type, generics: Vec<TypeWithKind>) -> Rend
 
 fn get_index_type_name(clean_type: &clean::Type, accept_generic: bool) -> Option<Symbol> {
     match *clean_type {
-        clean::ResolvedPath { ref path, .. } => {
+        clean::Type::Path { ref path, .. } => {
             let path_segment = path.segments.last().unwrap();
             Some(path_segment.name)
         }
@@ -371,7 +371,7 @@ fn insert_ty(
             let mut ty_generics = Vec::new();
             for bound in bound.get_bounds().unwrap_or(&[]) {
                 if let Some(path) = bound.get_trait_path() {
-                    let ty = Type::ResolvedPath { path };
+                    let ty = Type::Path { path };
                     get_real_types(generics, &ty, tcx, recurse + 1, &mut ty_generics, cache);
                 }
             }
index 069862efde6409a0a49891cd32263b08b836a5c7..365d959ad9f3b3dd962f4e962e1062f8a473559b 100644 (file)
@@ -504,9 +504,9 @@ fn init(
         // by the browser as the theme stylesheet. The theme system (hackily) works by
         // changing the href to this stylesheet. All other themes are disabled to
         // prevent rule conflicts
-        scx.style_files.push(StylePath { path: PathBuf::from("light.css"), disabled: false });
-        scx.style_files.push(StylePath { path: PathBuf::from("dark.css"), disabled: true });
-        scx.style_files.push(StylePath { path: PathBuf::from("ayu.css"), disabled: true });
+        scx.style_files.push(StylePath { path: PathBuf::from("light.css") });
+        scx.style_files.push(StylePath { path: PathBuf::from("dark.css") });
+        scx.style_files.push(StylePath { path: PathBuf::from("ayu.css") });
 
         let dst = output;
         scx.ensure_dir(&dst)?;
@@ -596,9 +596,13 @@ fn after_krate(&mut self) -> Result<(), Error> {
         page.description = "Settings of Rustdoc";
         page.root_path = "./";
 
-        let mut style_files = self.shared.style_files.clone();
         let sidebar = "<h2 class=\"location\">Settings</h2><div class=\"sidebar-elems\"></div>";
-        style_files.push(StylePath { path: PathBuf::from("settings.css"), disabled: false });
+        let theme_names: Vec<String> = self
+            .shared
+            .style_files
+            .iter()
+            .map(StylePath::basename)
+            .collect::<Result<_, Error>>()?;
         let v = layout::render(
             &self.shared.templates,
             &self.shared.layout,
@@ -607,9 +611,9 @@ fn after_krate(&mut self) -> Result<(), Error> {
             settings(
                 self.shared.static_root_path.as_deref().unwrap_or("./"),
                 &self.shared.resource_suffix,
-                &self.shared.style_files,
+                theme_names,
             )?,
-            &style_files,
+            &self.shared.style_files,
         );
         self.shared.fs.write(settings_file, v)?;
         if let Some(ref redirections) = self.shared.redirections {
index 7d231a0d64922ea87003b88767087c66d2fdcfd3..8bf7d0416dd0a2594ab2452cb04e1d82b5b381fb 100644 (file)
@@ -64,7 +64,6 @@
 use serde::{Serialize, Serializer};
 
 use crate::clean::{self, ItemId, RenderedLink, SelfTy};
-use crate::docfs::PathError;
 use crate::error::Error;
 use crate::formats::cache::Cache;
 use crate::formats::item_type::ItemType;
@@ -173,8 +172,12 @@ fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
 crate struct StylePath {
     /// The path to the theme
     crate path: PathBuf,
-    /// What the `disabled` attribute should be set to in the HTML tag
-    crate disabled: bool,
+}
+
+impl StylePath {
+    pub fn basename(&self) -> Result<String, Error> {
+        Ok(try_none!(try_none!(self.path.file_stem(), &self.path).to_str(), &self.path).to_string())
+    }
 }
 
 fn write_srclink(cx: &Context<'_>, item: &clean::Item, buf: &mut Buffer) {
@@ -353,7 +356,7 @@ enum Setting {
         js_data_name: &'static str,
         description: &'static str,
         default_value: &'static str,
-        options: Vec<(String, String)>,
+        options: Vec<String>,
     },
 }
 
@@ -393,10 +396,9 @@ fn display(&self, root_path: &str, suffix: &str) -> String {
                 options
                     .iter()
                     .map(|opt| format!(
-                        "<option value=\"{}\" {}>{}</option>",
-                        opt.0,
-                        if opt.0 == default_value { "selected" } else { "" },
-                        opt.1,
+                        "<option value=\"{name}\" {}>{name}</option>",
+                        if opt == default_value { "selected" } else { "" },
+                        name = opt,
                     ))
                     .collect::<String>(),
                 root_path,
@@ -421,18 +423,7 @@ fn from(values: (&'static str, Vec<T>)) -> Setting {
     }
 }
 
-fn settings(root_path: &str, suffix: &str, themes: &[StylePath]) -> Result<String, Error> {
-    let theme_names: Vec<(String, String)> = themes
-        .iter()
-        .map(|entry| {
-            let theme =
-                try_none!(try_none!(entry.path.file_stem(), &entry.path).to_str(), &entry.path)
-                    .to_string();
-
-            Ok((theme.clone(), theme))
-        })
-        .collect::<Result<_, Error>>()?;
-
+fn settings(root_path: &str, suffix: &str, theme_names: Vec<String>) -> Result<String, Error> {
     // (id, explanation, default value)
     let settings: &[Setting] = &[
         (
@@ -469,10 +460,11 @@ fn settings(root_path: &str, suffix: &str, themes: &[StylePath]) -> Result<Strin
             <span class=\"in-band\">Rustdoc settings</span>\
         </h1>\
         <div class=\"settings\">{}</div>\
-        <script src=\"{}settings{}.js\"></script>",
+        <link rel=\"stylesheet\" href=\"{root_path}settings{suffix}.css\">\
+        <script src=\"{root_path}settings{suffix}.js\"></script>",
         settings.iter().map(|s| s.display(root_path, suffix)).collect::<String>(),
-        root_path,
-        suffix
+        root_path = root_path,
+        suffix = suffix
     ))
 }
 
@@ -1227,7 +1219,7 @@ fn should_render_item(item: &clean::Item, deref_mut_: bool, tcx: TyCtxt<'_>) ->
             | SelfTy::SelfExplicit(clean::BorrowedRef { mutability, .. }) => {
                 (mutability == Mutability::Mut, false, false)
             }
-            SelfTy::SelfExplicit(clean::ResolvedPath { path }) => {
+            SelfTy::SelfExplicit(clean::Type::Path { path }) => {
                 (false, Some(path.def_id()) == tcx.lang_items().owned_box(), false)
             }
             SelfTy::SelfValue => (false, false, true),
@@ -1243,10 +1235,17 @@ fn should_render_item(item: &clean::Item, deref_mut_: bool, tcx: TyCtxt<'_>) ->
 fn notable_traits_decl(decl: &clean::FnDecl, cx: &Context<'_>) -> String {
     let mut out = Buffer::html();
 
-    if let Some(did) = decl.output.as_return().and_then(|t| t.def_id(cx.cache())) {
+    if let Some((did, ty)) = decl.output.as_return().and_then(|t| Some((t.def_id(cx.cache())?, t)))
+    {
         if let Some(impls) = cx.cache().impls.get(&did) {
             for i in impls {
                 let impl_ = i.inner_impl();
+                if !impl_.for_.without_borrowed_ref().is_same(ty.without_borrowed_ref(), cx.cache())
+                {
+                    // Two different types might have the same did,
+                    // without actually being the same.
+                    continue;
+                }
                 if let Some(trait_) = &impl_.trait_ {
                     let trait_did = trait_.def_id();
 
@@ -2520,7 +2519,7 @@ fn collect_paths_for_type(first_ty: clean::Type, cache: &Cache) -> Vec<String> {
         }
 
         match ty {
-            clean::Type::ResolvedPath { path } => process_path(path.def_id()),
+            clean::Type::Path { path } => process_path(path.def_id()),
             clean::Type::Tuple(tys) => {
                 work.extend(tys.into_iter());
             }
index e59b94f6b7d3d09bcf351a92b2253a342e226573..62fdec15af42091bf4db8381f2d815bf84b09140 100644 (file)
@@ -727,8 +727,8 @@ fn trait_item(w: &mut Buffer, cx: &Context<'_>, m: &clean::Item, t: &clean::Item
         let mut implementor_dups: FxHashMap<Symbol, (DefId, bool)> = FxHashMap::default();
         for implementor in implementors {
             match implementor.inner_impl().for_ {
-                clean::ResolvedPath { ref path }
-                | clean::BorrowedRef { type_: box clean::ResolvedPath { ref path }, .. }
+                clean::Type::Path { ref path }
+                | clean::BorrowedRef { type_: box clean::Type::Path { ref path }, .. }
                     if !path.is_assoc_ty() =>
                 {
                     let did = path.def_id();
@@ -1453,8 +1453,8 @@ fn render_implementor(
     // If there's already another implementor that has the same abridged name, use the
     // full path, for example in `std::iter::ExactSizeIterator`
     let use_absolute = match implementor.inner_impl().for_ {
-        clean::ResolvedPath { ref path, .. }
-        | clean::BorrowedRef { type_: box clean::ResolvedPath { ref path, .. }, .. }
+        clean::Type::Path { ref path, .. }
+        | clean::BorrowedRef { type_: box clean::Type::Path { ref path, .. }, .. }
             if !path.is_assoc_ty() =>
         {
             implementor_dups[&path.last()].1
@@ -1769,6 +1769,13 @@ fn write_size_of_layout(w: &mut Buffer, layout: &Layout, tag_size: u64) {
                  the type was too big.</p>"
             );
         }
+        Err(LayoutError::NormalizationFailure(_, _)) => {
+            writeln!(
+                w,
+                "<p><strong>Note:</strong> Encountered an error during type layout; \
+                the type failed to be normalized.</p>"
+            )
+        }
     }
 
     writeln!(w, "</div>");
index 2d3b2490677e9b3e029cbad752a3a58368f6a965..0d5ba8e80d2429464ca2a1e842b8cc38de524558 100644 (file)
@@ -181,42 +181,34 @@ fn write_minify(
         cx.write_shared(SharedResource::InvocationSpecific { basename: p }, content, &options.emit)
     };
 
-    fn add_background_image_to_css(
-        cx: &Context<'_>,
-        css: &mut String,
-        rule: &str,
-        file: &'static str,
-    ) {
-        css.push_str(&format!(
-            "{} {{ background-image: url({}); }}",
-            rule,
-            SharedResource::ToolchainSpecific { basename: file }
+    // Given "foo.svg", return e.g. "url(\"foo1.58.0.svg\")"
+    fn ver_url(cx: &Context<'_>, basename: &'static str) -> String {
+        format!(
+            "url(\"{}\")",
+            SharedResource::ToolchainSpecific { basename }
                 .path(cx)
                 .file_name()
                 .unwrap()
                 .to_str()
                 .unwrap()
-        ))
+        )
     }
 
-    // Add all the static files. These may already exist, but we just
-    // overwrite them anyway to make sure that they're fresh and up-to-date.
-    let mut rustdoc_css = static_files::RUSTDOC_CSS.to_owned();
-    add_background_image_to_css(
-        cx,
-        &mut rustdoc_css,
-        "details.undocumented[open] > summary::before, \
-         details.rustdoc-toggle[open] > summary::before, \
-         details.rustdoc-toggle[open] > summary.hideme::before",
-        "toggle-minus.svg",
-    );
-    add_background_image_to_css(
+    // We use the AUTOREPLACE mechanism to inject into our static JS and CSS certain
+    // values that are only known at doc build time. Since this mechanism is somewhat
+    // surprising when reading the code, please limit it to rustdoc.css.
+    write_minify(
+        "rustdoc.css",
+        static_files::RUSTDOC_CSS
+            .replace(
+                "/* AUTOREPLACE: */url(\"toggle-minus.svg\")",
+                &ver_url(cx, "toggle-minus.svg"),
+            )
+            .replace("/* AUTOREPLACE: */url(\"toggle-plus.svg\")", &ver_url(cx, "toggle-plus.svg"))
+            .replace("/* AUTOREPLACE: */url(\"down-arrow.svg\")", &ver_url(cx, "down-arrow.svg")),
         cx,
-        &mut rustdoc_css,
-        "details.undocumented > summary::before, details.rustdoc-toggle > summary::before",
-        "toggle-plus.svg",
-    );
-    write_minify("rustdoc.css", rustdoc_css, cx, options)?;
+        options,
+    )?;
 
     // Add all the static files. These may already exist, but we just
     // overwrite them anyway to make sure that they're fresh and up-to-date.
@@ -228,12 +220,12 @@ fn add_background_image_to_css(
     let mut themes: FxHashSet<String> = FxHashSet::default();
 
     for entry in &cx.shared.style_files {
-        let theme = try_none!(try_none!(entry.path.file_stem(), &entry.path).to_str(), &entry.path);
+        let theme = entry.basename()?;
         let extension =
             try_none!(try_none!(entry.path.extension(), &entry.path).to_str(), &entry.path);
 
         // Handle the official themes
-        match theme {
+        match theme.as_str() {
             "light" => write_minify("light.css", static_files::themes::LIGHT, cx, options)?,
             "dark" => write_minify("dark.css", static_files::themes::DARK, cx, options)?,
             "ayu" => write_minify("ayu.css", static_files::themes::AYU, cx, options)?,
@@ -265,26 +257,7 @@ fn add_background_image_to_css(
     let mut themes: Vec<&String> = themes.iter().collect();
     themes.sort();
 
-    // FIXME: this should probably not be a toolchain file since it depends on `--theme`.
-    // But it seems a shame to copy it over and over when it's almost always the same.
-    // Maybe we can change the representation to move this out of main.js?
-    write_minify(
-        "main.js",
-        static_files::MAIN_JS
-            .replace(
-                "/* INSERT THEMES HERE */",
-                &format!(" = {}", serde_json::to_string(&themes).unwrap()),
-            )
-            .replace(
-                "/* INSERT RUSTDOC_VERSION HERE */",
-                &format!(
-                    "rustdoc {}",
-                    rustc_interface::util::version_str().unwrap_or("unknown version")
-                ),
-            ),
-        cx,
-        options,
-    )?;
+    write_minify("main.js", static_files::MAIN_JS, cx, options)?;
     write_minify("search.js", static_files::SEARCH_JS, cx, options)?;
     write_minify("settings.js", static_files::SETTINGS_JS, cx, options)?;
 
@@ -292,18 +265,7 @@ fn add_background_image_to_css(
         write_minify("source-script.js", static_files::sidebar::SOURCE_SCRIPT, cx, options)?;
     }
 
-    {
-        write_minify(
-            "storage.js",
-            format!(
-                "var resourcesSuffix = \"{}\";{}",
-                cx.shared.resource_suffix,
-                static_files::STORAGE_JS
-            ),
-            cx,
-            options,
-        )?;
-    }
+    write_minify("storage.js", static_files::STORAGE_JS, cx, options)?;
 
     if cx.shared.layout.scrape_examples_extension {
         cx.write_minify(
index bfad51069513149b0b24dcfdadc4bdeb86b9b66b..fceb508bc4ff5e41461d6398fc073ecb126fd93a 100644 (file)
@@ -828,6 +828,7 @@ h2.small-section-header > .anchor {
        background-color: transparent;
        background-size: 20px;
        background-position: calc(100% - 1px) 56%;
+       background-image: /* AUTOREPLACE: */url("down-arrow.svg");
 }
 .search-container > .top-button {
        position: absolute;
@@ -1129,15 +1130,17 @@ h3.variant {
        margin-top: 3px;
 }
 
-.docblock > .section-header:first-child {
+.top-doc .docblock > .section-header:first-child {
        margin-left: 15px;
-       margin-top: 0;
 }
-
-.docblock > .section-header:first-child:hover > a:before {
+.top-doc .docblock > .section-header:first-child:hover > a:before {
        left: -10px;
 }
 
+.docblock > .section-header:first-child {
+       margin-top: 0;
+}
+
 :target > code, :target > .code-header {
        opacity: 1;
 }
@@ -1608,6 +1611,16 @@ details.rustdoc-toggle[open] > summary.hideme > span {
        display: none;
 }
 
+details.undocumented[open] > summary::before,
+details.rustdoc-toggle[open] > summary::before,
+details.rustdoc-toggle[open] > summary.hideme::before {
+       background-image: /* AUTOREPLACE: */url("toggle-minus.svg");
+}
+
+details.undocumented > summary::before, details.rustdoc-toggle > summary::before {
+       background-image: /* AUTOREPLACE: */url("toggle-plus.svg");
+}
+
 details.rustdoc-toggle[open] > summary::before,
 details.rustdoc-toggle[open] > summary.hideme::before {
        width: 17px;
index c9fa72cbaab01bfc8c9d514c8c677d3467402fde..5661d4973342f034c207b2b9beb725b934fdd80e 100644 (file)
@@ -37,14 +37,29 @@ if (!DOMTokenList.prototype.remove) {
     };
 }
 
-(function () {
-    var rustdocVars = document.getElementById("rustdoc-vars");
-    if (rustdocVars) {
-        window.rootPath = rustdocVars.attributes["data-root-path"].value;
-        window.currentCrate = rustdocVars.attributes["data-current-crate"].value;
-        window.searchJS = rustdocVars.attributes["data-search-js"].value;
-        window.searchIndexJS = rustdocVars.attributes["data-search-index-js"].value;
+// Get a value from the rustdoc-vars div, which is used to convey data from
+// Rust to the JS. If there is no such element, return null.
+function getVar(name) {
+    var el = document.getElementById("rustdoc-vars");
+    if (el) {
+        return el.attributes["data-" + name].value;
+    } else {
+        return null;
     }
+}
+
+// Given a basename (e.g. "storage") and an extension (e.g. ".js"), return a URL
+// for a resource under the root-path, with the resource-suffix.
+function resourcePath(basename, extension) {
+    return getVar("root-path") + basename + getVar("resource-suffix") + extension;
+}
+
+
+(function () {
+    window.rootPath = getVar("root-path");
+    window.currentCrate = getVar("current-crate");
+    window.searchJS =  resourcePath("search", ".js");
+    window.searchIndexJS = resourcePath("search-index", ".js");
     var sidebarVars = document.getElementById("sidebar-vars");
     if (sidebarVars) {
         window.sidebarCurrent = {
@@ -115,7 +130,7 @@ function hideThemeButtonState() {
 (function () {
     var themeChoices = getThemesElement();
     var themePicker = getThemePickerElement();
-    var availableThemes/* INSERT THEMES HERE */;
+    var availableThemes = getVar("themes").split(",");
 
     function switchThemeButtonState() {
         if (themeChoices.style.display === "block") {
@@ -980,7 +995,7 @@ function hideThemeButtonState() {
         var rustdoc_version = document.createElement("span");
         rustdoc_version.className = "bottom";
         var rustdoc_version_code = document.createElement("code");
-        rustdoc_version_code.innerText = "/* INSERT RUSTDOC_VERSION HERE */";
+        rustdoc_version_code.innerText = "rustdoc " + getVar("rustdoc-version");
         rustdoc_version.appendChild(rustdoc_version_code);
 
         container.appendChild(rustdoc_version);
index 78ed17e6899e9aa17c0d526b7f93ba64cf3d51a2..606c237aea7d01bd5d5c728720043d0f3285d33c 100644 (file)
@@ -1,5 +1,3 @@
-// From rust:
-/* global resourcesSuffix */
 var darkThemes = ["dark", "ayu"];
 window.currentTheme = document.getElementById("themeStyle");
 window.mainTheme = document.getElementById("mainThemeStyle");
@@ -107,9 +105,8 @@ function getCurrentValue(name) {
 }
 
 function switchTheme(styleElem, mainStyleElem, newTheme, saveTheme) {
-    var fullBasicCss = "rustdoc" + resourcesSuffix + ".css";
-    var fullNewTheme = newTheme + resourcesSuffix + ".css";
-    var newHref = mainStyleElem.href.replace(fullBasicCss, fullNewTheme);
+    var newHref = mainStyleElem.href.replace(
+        /\/rustdoc([^/]*)\.css/, "/" + newTheme + "$1" + ".css");
 
     // If this new value comes from a system setting or from the previously
     // saved theme, no need to save it.
index cf57d4cf3aa43929ef937bfe1d9c7801af699e56..2a783c6da57e4f67713d58b01a78cb1bf4f1a28a 100644 (file)
     <link rel="stylesheet" type="text/css" {# -#}
           href="{{static_root_path | safe}}rustdoc{{page.resource_suffix}}.css" {# -#}
           id="mainThemeStyle"> {#- -#}
-    {{- style_files | safe -}}
+    {%- for theme in themes -%}
+        <link rel="stylesheet" type="text/css" {# -#}
+            href="{{static_root_path | safe}}{{theme}}{{page.resource_suffix}}.css" {#- -#}
+        {%- if theme == "light" -%}
+            id="themeStyle"
+        {%- else -%}
+            disabled
+        {%- endif -%}
+        >
+    {%- endfor -%}
     <script id="default-settings" {# -#}
       {% for k, v in layout.default_settings %}
         data-{{k}}="{{v}}"
             href="{{static_root_path | safe}}favicon{{page.resource_suffix}}.svg"> {#- -#}
     {%- endif -%}
     {{- layout.external_html.in_header | safe -}}
-    <style type="text/css"> {#- -#}
-    #crate-search{ {#- -#}
-        background-image:url("{{static_root_path | safe}}down-arrow{{page.resource_suffix}}.svg"); {#- -#}
-    } {#- -#}
-    </style> {#- -#}
 </head> {#- -#}
 <body class="rustdoc {{page.css_class}}"> {#- -#}
     <!--[if lte IE 11]> {#- -#}
     <div id="rustdoc-vars" {# -#}
          data-root-path="{{page.root_path | safe}}" {# -#}
          data-current-crate="{{layout.krate}}" {# -#}
-         data-search-index-js="{{page.root_path | safe}}search-index{{page.resource_suffix}}.js" {# -#}
-         data-search-js="{{static_root_path | safe}}search{{page.resource_suffix}}.js"> {#- -#}
+         data-themes="{{themes | join(sep=",") }}" {# -#}
+         data-resource-suffix="{{page.resource_suffix}}" {# -#}
+         data-rustdoc-version="{{rustdoc_version}}" {# -#}
+    > {#- -#}
     </div>
 </body> {#- -#}
 </html> {#- -#}
index a5c1eb1241096212722d02ca7fcdc8d591039366..7fc295747f41a5657419d11707034609dee05f1f 100644 (file)
@@ -365,7 +365,7 @@ fn from_tcx(bound: clean::GenericBound, tcx: TyCtxt<'_>) -> Self {
         match bound {
             TraitBound(clean::PolyTrait { trait_, generic_params }, modifier) => {
                 // FIXME: should `trait_` be a clean::Path equivalent in JSON?
-                let trait_ = clean::ResolvedPath { path: trait_ }.into_tcx(tcx);
+                let trait_ = clean::Type::Path { path: trait_ }.into_tcx(tcx);
                 GenericBound::TraitBound {
                     trait_,
                     generic_params: generic_params.into_iter().map(|x| x.into_tcx(tcx)).collect(),
@@ -388,9 +388,13 @@ fn from_tcx(bound: clean::GenericBound, tcx: TyCtxt<'_>) -> Self {
 
 impl FromWithTcx<clean::Type> for Type {
     fn from_tcx(ty: clean::Type, tcx: TyCtxt<'_>) -> Self {
-        use clean::Type::*;
+        use clean::Type::{
+            Array, BareFunction, BorrowedRef, DynTrait, Generic, ImplTrait, Infer, Primitive,
+            QPath, RawPointer, Slice, Tuple,
+        };
+
         match ty {
-            ResolvedPath { path } => Type::ResolvedPath {
+            clean::Type::Path { path } => Type::ResolvedPath {
                 name: path.whole_name(),
                 id: from_item_id(path.def_id().into()),
                 args: path.segments.last().map(|args| Box::new(args.clone().args.into_tcx(tcx))),
@@ -435,7 +439,7 @@ fn from_tcx(ty: clean::Type, tcx: TyCtxt<'_>) -> Self {
             },
             QPath { name, self_type, trait_, .. } => {
                 // FIXME: should `trait_` be a clean::Path equivalent in JSON?
-                let trait_ = ResolvedPath { path: trait_ }.into_tcx(tcx);
+                let trait_ = clean::Type::Path { path: trait_ }.into_tcx(tcx);
                 Type::QualifiedPath {
                     name: name.to_string(),
                     self_type: Box::new((*self_type).into_tcx(tcx)),
@@ -501,7 +505,7 @@ fn from_tcx(impl_: clean::Impl, tcx: TyCtxt<'_>) -> Self {
         let provided_trait_methods = impl_.provided_trait_methods(tcx);
         let clean::Impl { unsafety, generics, trait_, for_, items, polarity, kind } = impl_;
         // FIXME: should `trait_` be a clean::Path equivalent in JSON?
-        let trait_ = trait_.map(|path| clean::ResolvedPath { path }.into_tcx(tcx));
+        let trait_ = trait_.map(|path| clean::Type::Path { path }.into_tcx(tcx));
         // FIXME: use something like ImplKind in JSON?
         let (synthetic, blanket_impl) = match kind {
             clean::ImplKind::Normal => (false, None),
index b6311abb5c3e821f053aa79b1832fa3012bf716e..6ba56fe01a93505a7306cf628a98c89ad27cbdb9 100644 (file)
@@ -18,6 +18,7 @@
 #![feature(type_ascription)]
 #![feature(iter_intersperse)]
 #![recursion_limit = "256"]
+#![feature(unwrap_infallible)]
 #![warn(rustc::internal)]
 
 #[macro_use]
index 47b24d40edc27ccaac299bfe59f804cd9ca4675d..abb4bec5ca133c69366949290ac3c8a2bbaf58bc 100644 (file)
@@ -131,7 +131,6 @@ fn extract_leading_metadata(s: &str) -> (Vec<&str>, &str) {
         .map_err(|err| format!("{}: {}", options.input.display(), err))?;
     let mut opts = TestOptions::default();
     opts.no_crate_inject = true;
-    opts.display_doctest_warnings = options.display_doctest_warnings;
     let mut collector = Collector::new(
         Symbol::intern(&options.input.display().to_string()),
         options.clone(),
@@ -146,11 +145,6 @@ fn extract_leading_metadata(s: &str) -> (Vec<&str>, &str) {
 
     find_testable_code(&input_str, &mut collector, codes, options.enable_per_target_ignores, None);
 
-    crate::doctest::run_tests(
-        options.test_args,
-        options.nocapture,
-        options.display_doctest_warnings,
-        collector.tests,
-    );
+    crate::doctest::run_tests(options.test_args, options.nocapture, collector.tests);
     Ok(())
 }
index 3b39e3576e69a39d22f577b29dd3ab4c173feebf..10b6fdf87f41972c414708bfa452b91b8c9fe61e 100644 (file)
@@ -142,16 +142,21 @@ fn visit_expr(&mut self, ex: &'tcx hir::Expr<'tcx>) {
             hir::ExprKind::Call(f, _) => {
                 let types = tcx.typeck(ex.hir_id.owner);
 
-                match types.node_type_opt(f.hir_id) {
-                    Some(ty) => (ty, ex.span),
-                    None => {
-                        return;
-                    }
+                if let Some(ty) = types.node_type_opt(f.hir_id) {
+                    (ty, ex.span)
+                } else {
+                    trace!("node_type_opt({}) = None", f.hir_id);
+                    return;
                 }
             }
             hir::ExprKind::MethodCall(_, _, _, span) => {
                 let types = tcx.typeck(ex.hir_id.owner);
-                let def_id = types.type_dependent_def_id(ex.hir_id).unwrap();
+                let def_id = if let Some(def_id) = types.type_dependent_def_id(ex.hir_id) {
+                    def_id
+                } else {
+                    trace!("type_dependent_def_id({}) = None", ex.hir_id);
+                    return;
+                };
                 (tcx.type_of(def_id), span)
             }
             _ => {
index 379de080ffd4d8833fe14b80a3857d3d35a7bda6..a18bd48d72bc426a27f276f99425b0fcc9468480 100644 (file)
@@ -117,8 +117,7 @@ fn store_path(&mut self, did: DefId) {
                 if let Some(local_def_id) = def_id.as_local() {
                     if self.cx.tcx.has_attr(def_id, sym::macro_export) {
                         if inserted.insert(def_id) {
-                            let hir_id = self.cx.tcx.hir().local_def_id_to_hir_id(local_def_id);
-                            let item = self.cx.tcx.hir().expect_item(hir_id);
+                            let item = self.cx.tcx.hir().expect_item(local_def_id);
                             top_level_module.items.push((item, None));
                         }
                     }
index 144a746062daaa74f29b328870a06a0c0cd56290..8470ace24b845beef405b8330b11968ca76e76aa 100644 (file)
@@ -1,4 +1,4 @@
-// pretty-printers are not loaded
+// ignore-windows-gnu: pretty-printers are not loaded
 // compile-flags:-g
 
 // min-gdb-version: 8.1
index 8722d9e10d91d204fa457b5afc93eb1b3f1f7e42..3c4df3533e147f512a481954d373fdd95e20214a 100644 (file)
@@ -1,5 +1,11 @@
 # needs-profiler-support
 
+# Rust coverage maps support LLVM Coverage Mapping Format versions 5 and 6,
+# corresponding with LLVM versions 12 and 13, respectively.
+# When upgrading LLVM versions, consider whether to enforce a minimum LLVM
+# version during testing, with an additional directive at the top of this file
+# that sets, for example: `min-llvm-version: 12.0`
+
 -include ../coverage/coverage_tools.mk
 
 BASEDIR=../coverage-llvmir
index 4adf02bee0af47eaf85a133e0871c87f6746695a..9122e0406c2efc49ce6d7131de87b01d3b5264b5 100644 (file)
@@ -1,6 +1,12 @@
 # needs-profiler-support
 # ignore-windows-gnu
 
+# Rust coverage maps support LLVM Coverage Mapping Format versions 5 and 6,
+# corresponding with LLVM versions 12 and 13, respectively.
+# When upgrading LLVM versions, consider whether to enforce a minimum LLVM
+# version during testing, with an additional directive at the top of this file
+# that sets, for example: `min-llvm-version: 12.0`
+
 # FIXME(mati865): MinGW GCC miscompiles compiler-rt profiling library but with Clang it works
 # properly. Since we only have GCC on the CI ignore the test for now.
 
@@ -115,6 +121,7 @@ endif
        "$(LLVM_BIN_DIR)"/llvm-cov show \
                        $(DEBUG_FLAG) \
                        $(LLVM_COV_IGNORE_FILES) \
+                       --compilation-dir=. \
                        --Xdemangler="$(RUST_DEMANGLER)" \
                        --show-line-counts-or-regions \
                        --instr-profile="$(TMPDIR)"/$@.profdata \
index 5f809f9aa4ed4b033b2d3bd54a7954bfe3846b8e..8910cbbbb256c7c14cccd904c548591919a52576 100644 (file)
@@ -1,4 +1,4 @@
-// This test is to ensure that the anchors (`§`) have the expected color.
+// This test is to ensure that the anchors (`§`) have the expected color and position.
 goto: file://|DOC_PATH|/test_docs/struct.HeavilyDocumentedStruct.html
 show-text: true
 
@@ -28,3 +28,47 @@ assert-css: ("h2#implementations a.anchor", {"color": "rgb(0, 0, 0)"})
 // Same thing with the impl block title.
 move-cursor-to: "#impl"
 assert-css: ("#impl a.anchor", {"color": "rgb(0, 0, 0)"})
+
+// Now we check the positions: only the first heading of the top doc comment should
+// have a different position.
+move-cursor-to: ".top-doc .docblock .section-header:first-child"
+assert-css: (
+    ".top-doc .docblock .section-header:first-child > a::before",
+    {"left": "-10px", "padding-right": "10px"}
+)
+// We also check that the heading itself has a different indent.
+assert-css: (".top-doc .docblock .section-header:first-child", {"margin-left": "15px"})
+
+move-cursor-to: ".top-doc .docblock .section-header:not(:first-child)"
+assert-css: (
+    ".top-doc .docblock .section-header:not(:first-child) > a::before",
+    {"left": "-25px", "padding-right": "10px"}
+)
+assert-css: (".top-doc .docblock .section-header:not(:first-child)", {"margin-left": "0px"})
+
+// Now let's check some other docblock headings...
+// First the impl block docs.
+move-cursor-to: "#title-for-struct-impl-doc"
+assert-css: (
+    "#title-for-struct-impl-doc > a::before",
+    {"left": "-25px", "padding-right": "10px"}
+)
+assert-css: ("#title-for-struct-impl-doc", {"margin-left": "0px"})
+// Now a method docs.
+move-cursor-to: "#title-for-struct-impl-item-doc"
+assert-css: (
+    "#title-for-struct-impl-item-doc > a::before",
+    {"left": "-25px", "padding-right": "10px"}
+)
+assert-css: ("#title-for-struct-impl-item-doc", {"margin-left": "0px"})
+
+// Finally, we want to ensure that if the first element of the doc block isn't a heading,
+// if there is a heading afterwards, it won't have the indent.
+goto: file://|DOC_PATH|/test_docs/enum.WhoLetTheDogOut.html
+
+move-cursor-to: ".top-doc .docblock .section-header"
+assert-css: (
+    ".top-doc .docblock .section-header > a::before",
+    {"left": "-25px", "padding-right": "10px"}
+)
+assert-css: (".top-doc .docblock .section-header", {"margin-left": "0px"})
index 458bcc4780c6c5abfa909b611982fd7439e8b85b..9b37703dded4b7acf9e494019ecc200c512ad997 100644 (file)
@@ -47,6 +47,8 @@ fn as_ref(&self) -> &str {
 }
 
 /// Just a normal enum.
+///
+/// # title!
 #[doc(alias = "ThisIsAnAlias")]
 pub enum WhoLetTheDogOut {
     /// Woof!
index 5e390029dca33028ea7a0190bff3601e8f903142..30b32c511b5fa715c3099be9d530d9ee7d33b694 100644 (file)
@@ -1,9 +1,15 @@
+// Test that `--show-output` has an effect and `allow(unused)` can be overriden.
+
 // check-pass
-// compile-flags:-Zunstable-options --display-doctest-warnings --test
+// edition:2018
+// compile-flags:--test --test-args=--show-output
 // normalize-stdout-test: "src/test/rustdoc-ui" -> "$$DIR"
 // normalize-stdout-test "finished in \d+\.\d+s" -> "finished in $$TIME"
 
 /// ```
+/// #![warn(unused)]
 /// let x = 12;
+///
+/// fn foo(x: &std::fmt::Display) {}
 /// ```
 pub fn foo() {}
index 00467b9359eb231348834817ea423436f3a03ad3..f76dec1c85008b306be771406c2827d36686da8b 100644 (file)
@@ -1,24 +1,58 @@
 
 running 1 test
-test $DIR/display-output.rs - foo (line 6) ... ok
+test $DIR/display-output.rs - foo (line 9) ... ok
 
 successes:
 
----- $DIR/display-output.rs - foo (line 6) stdout ----
+---- $DIR/display-output.rs - foo (line 9) stdout ----
+warning: trait objects without an explicit `dyn` are deprecated
+  --> $DIR/display-output.rs:13:12
+   |
+LL | fn foo(x: &std::fmt::Display) {}
+   |            ^^^^^^^^^^^^^^^^^ help: use `dyn`: `dyn std::fmt::Display`
+   |
+   = note: `#[warn(bare_trait_objects)]` on by default
+   = warning: this is accepted in the current edition (Rust 2018) but is a hard error in Rust 2021!
+   = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/warnings-promoted-to-error.html>
+
 warning: unused variable: `x`
-  --> $DIR/display-output.rs:7:5
+  --> $DIR/display-output.rs:11:5
    |
 LL | let x = 12;
    |     ^ help: if this is intentional, prefix it with an underscore: `_x`
    |
-   = note: `#[warn(unused_variables)]` on by default
+note: the lint level is defined here
+  --> $DIR/display-output.rs:9:9
+   |
+LL | #![warn(unused)]
+   |         ^^^^^^
+   = note: `#[warn(unused_variables)]` implied by `#[warn(unused)]`
+
+warning: unused variable: `x`
+  --> $DIR/display-output.rs:13:8
+   |
+LL | fn foo(x: &std::fmt::Display) {}
+   |        ^ help: if this is intentional, prefix it with an underscore: `_x`
+
+warning: function is never used: `foo`
+  --> $DIR/display-output.rs:13:4
+   |
+LL | fn foo(x: &std::fmt::Display) {}
+   |    ^^^
+   |
+note: the lint level is defined here
+  --> $DIR/display-output.rs:9:9
+   |
+LL | #![warn(unused)]
+   |         ^^^^^^
+   = note: `#[warn(dead_code)]` implied by `#[warn(unused)]`
 
-warning: 1 warning emitted
+warning: 4 warnings emitted
 
 
 
 successes:
-    $DIR/display-output.rs - foo (line 6)
+    $DIR/display-output.rs - foo (line 9)
 
 test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in $TIME
 
diff --git a/src/test/rustdoc-ui/scrape-examples-ice.rs b/src/test/rustdoc-ui/scrape-examples-ice.rs
new file mode 100644 (file)
index 0000000..d629b62
--- /dev/null
@@ -0,0 +1,4 @@
+// compile-flags: -Z unstable-options --scrape-examples-output-path {{build-base}}/t.calls --scrape-examples-target-crate foobar
+// check-pass
+#![no_std]
+use core as _;
diff --git a/src/test/rustdoc/doc-notable_trait-slice.rs b/src/test/rustdoc/doc-notable_trait-slice.rs
new file mode 100644 (file)
index 0000000..b0d4140
--- /dev/null
@@ -0,0 +1,20 @@
+#![feature(doc_notable_trait)]
+
+#[doc(notable_trait)]
+pub trait SomeTrait {}
+
+pub struct SomeStruct;
+pub struct OtherStruct;
+impl SomeTrait for &[SomeStruct] {}
+
+// @has doc_notable_trait_slice/fn.bare_fn_matches.html
+// @has - '//code[@class="content"]' 'impl SomeTrait for &[SomeStruct]'
+pub fn bare_fn_matches() -> &'static [SomeStruct] {
+    &[]
+}
+
+// @has doc_notable_trait_slice/fn.bare_fn_no_matches.html
+// @!has - '//code[@class="content"]' 'impl SomeTrait for &[SomeStruct]'
+pub fn bare_fn_no_matches() -> &'static [OtherStruct] {
+    &[]
+}
index 2f7c89c5f1e6b7376d277d22165b9131eb5189fc..f1d49b9fcb20ae98d5eea6d56731d4cc870dd1f0 100644 (file)
@@ -3,7 +3,7 @@
 // @has static_root_path/struct.SomeStruct.html
 // @matches - '"/cache/main\.js"'
 // @!matches - '"\.\./main\.js"'
-// @matches - '"\.\./search-index\.js"'
+// @matches - 'data-root-path="\.\./"'
 // @!matches - '"/cache/search-index\.js"'
 pub struct SomeStruct;
 
index 8051c58898e499241a41ead3775deea95e4b85e4..de0df0aae82d7aa5c997a30a24337f909d6e6488 100644 (file)
@@ -7,8 +7,8 @@
 extern crate rustc_lint;
 #[macro_use]
 extern crate rustc_session;
-extern crate rustc_span;
 extern crate rustc_ast;
+extern crate rustc_span;
 
 use rustc_ast_pretty::pprust;
 use rustc_driver::plugin::Registry;
@@ -44,7 +44,7 @@ fn check_fn(
     ) {
         let item = match cx.tcx.hir().get(id) {
             Node::Item(item) => item,
-            _ => cx.tcx.hir().expect_item(cx.tcx.hir().get_parent_item(id)),
+            _ => cx.tcx.hir().expect_item(cx.tcx.hir().get_parent_item(id).expect_owner()),
         };
 
         let allowed = |attr| pprust::attribute_to_string(attr).contains("allowed_attr");
diff --git a/src/test/ui/associated-types/issue-59324.rs b/src/test/ui/associated-types/issue-59324.rs
new file mode 100644 (file)
index 0000000..9e68e9e
--- /dev/null
@@ -0,0 +1,26 @@
+trait NotFoo {}
+
+pub trait Foo: NotFoo {
+    type OnlyFoo;
+}
+
+pub trait Service {
+    type AssocType;
+}
+
+pub trait ThriftService<Bug: NotFoo>:
+//~^ ERROR the trait bound `Bug: Foo` is not satisfied
+//~| ERROR the trait bound `Bug: Foo` is not satisfied
+    Service<AssocType = <Bug as Foo>::OnlyFoo>
+{
+    fn get_service(
+    //~^ ERROR the trait bound `Bug: Foo` is not satisfied
+    //~| ERROR the trait bound `Bug: Foo` is not satisfied
+        &self,
+    ) -> Self::AssocType;
+}
+
+fn with_factory<H>(factory: dyn ThriftService<()>) {}
+//~^ ERROR the trait bound `(): Foo` is not satisfied
+
+fn main() {}
diff --git a/src/test/ui/associated-types/issue-59324.stderr b/src/test/ui/associated-types/issue-59324.stderr
new file mode 100644 (file)
index 0000000..2f430d3
--- /dev/null
@@ -0,0 +1,69 @@
+error[E0277]: the trait bound `Bug: Foo` is not satisfied
+  --> $DIR/issue-59324.rs:11:1
+   |
+LL | / pub trait ThriftService<Bug: NotFoo>:
+LL | |
+LL | |
+LL | |     Service<AssocType = <Bug as Foo>::OnlyFoo>
+...  |
+LL | |     ) -> Self::AssocType;
+LL | | }
+   | |_^ the trait `Foo` is not implemented for `Bug`
+   |
+help: consider further restricting this bound
+   |
+LL | pub trait ThriftService<Bug: NotFoo + Foo>:
+   |                                     +++++
+
+error[E0277]: the trait bound `Bug: Foo` is not satisfied
+  --> $DIR/issue-59324.rs:11:1
+   |
+LL | / pub trait ThriftService<Bug: NotFoo>:
+LL | |
+LL | |
+LL | |     Service<AssocType = <Bug as Foo>::OnlyFoo>
+...  |
+LL | |     ) -> Self::AssocType;
+LL | | }
+   | |_^ the trait `Foo` is not implemented for `Bug`
+   |
+help: consider further restricting this bound
+   |
+LL | pub trait ThriftService<Bug: NotFoo + Foo>:
+   |                                     +++++
+
+error[E0277]: the trait bound `Bug: Foo` is not satisfied
+  --> $DIR/issue-59324.rs:16:5
+   |
+LL | /     fn get_service(
+LL | |
+LL | |
+LL | |         &self,
+LL | |     ) -> Self::AssocType;
+   | |_________________________^ the trait `Foo` is not implemented for `Bug`
+   |
+help: consider further restricting this bound
+   |
+LL | pub trait ThriftService<Bug: NotFoo + Foo>:
+   |                                     +++++
+
+error[E0277]: the trait bound `Bug: Foo` is not satisfied
+  --> $DIR/issue-59324.rs:16:8
+   |
+LL |     fn get_service(
+   |        ^^^^^^^^^^^ the trait `Foo` is not implemented for `Bug`
+   |
+help: consider further restricting this bound
+   |
+LL | pub trait ThriftService<Bug: NotFoo + Foo>:
+   |                                     +++++
+
+error[E0277]: the trait bound `(): Foo` is not satisfied
+  --> $DIR/issue-59324.rs:23:29
+   |
+LL | fn with_factory<H>(factory: dyn ThriftService<()>) {}
+   |                             ^^^^^^^^^^^^^^^^^^^^^ the trait `Foo` is not implemented for `()`
+
+error: aborting due to 5 previous errors
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/associated-types/issue-67684.rs b/src/test/ui/associated-types/issue-67684.rs
new file mode 100644 (file)
index 0000000..49efe8a
--- /dev/null
@@ -0,0 +1,62 @@
+// check-pass
+
+#![allow(dead_code)]
+
+trait ParseError {
+    type StreamError;
+}
+
+impl<T> ParseError for T {
+    type StreamError = ();
+}
+
+trait Stream {
+    type Item;
+    type Error: ParseError;
+}
+
+trait Parser
+where
+    <Self as Parser>::PartialState: Default,
+{
+    type PartialState;
+    fn parse_mode(_: &Self, _: Self::PartialState) {
+        loop {}
+    }
+}
+
+impl Stream for () {
+    type Item = ();
+    type Error = ();
+}
+
+impl Parser for () {
+    type PartialState = ();
+}
+
+struct AndThen<A, B>(core::marker::PhantomData<(A, B)>);
+
+impl<A, B> Parser for AndThen<A, B>
+where
+    A: Stream,
+    B: Into<<A::Error as ParseError>::StreamError>,
+{
+    type PartialState = ();
+}
+
+fn expr<A>() -> impl Parser
+where
+    A: Stream<Error = <A as Stream>::Item>,
+{
+    AndThen::<A, ()>(core::marker::PhantomData)
+}
+
+fn parse_mode_impl<A>()
+where
+    <A as Stream>::Error: ParseError,
+    A: Stream<Error = <A as Stream>::Item>,
+{
+    Parser::parse_mode(&expr::<A>(), Default::default())
+}
+
+fn main() {}
diff --git a/src/test/ui/associated-types/issue-69398.rs b/src/test/ui/associated-types/issue-69398.rs
new file mode 100644 (file)
index 0000000..ca3d66b
--- /dev/null
@@ -0,0 +1,21 @@
+// check-pass
+
+pub trait Foo {
+    type Bar;
+}
+
+pub trait Broken {
+    type Assoc;
+    fn broken(&self) where Self::Assoc: Foo;
+}
+
+impl<T> Broken for T {
+    type Assoc = ();
+    fn broken(&self) where Self::Assoc: Foo {
+        let _x: <Self::Assoc as Foo>::Bar;
+    }
+}
+
+fn main() {
+    let _m: &dyn Broken<Assoc=()> = &();
+}
diff --git a/src/test/ui/associated-types/issue-71113.rs b/src/test/ui/associated-types/issue-71113.rs
new file mode 100644 (file)
index 0000000..48de891
--- /dev/null
@@ -0,0 +1,16 @@
+// check-pass
+
+use std::borrow::Cow;
+
+enum _Recursive<'a>
+where
+    Self: ToOwned<Owned=Box<Self>>
+{
+    Variant(MyCow<'a, _Recursive<'a>>),
+}
+
+pub struct Wrapper<T>(T);
+
+pub struct MyCow<'a, T: ToOwned<Owned=Box<T>> + 'a>(Wrapper<Cow<'a, T>>);
+
+fn main() {}
diff --git a/src/test/ui/associated-types/issue-82079.rs b/src/test/ui/associated-types/issue-82079.rs
new file mode 100644 (file)
index 0000000..590c799
--- /dev/null
@@ -0,0 +1,121 @@
+// check-pass
+
+mod convenience_operators {
+    use crate::{Op, Relation};
+    use std::ops::AddAssign;
+    use std::ops::Mul;
+
+    impl<C: Op> Relation<C> {
+        pub fn map<F: Fn(C::D) -> D2 + 'static, D2: 'static>(
+            self,
+            f: F,
+        ) -> Relation<impl Op<D = D2, R = C::R>> {
+            self.map_dr(move |x, r| (f(x), r))
+        }
+    }
+
+    impl<K: 'static, V: 'static, C: Op<D = (K, V)>> Relation<C> {
+        pub fn semijoin<C2: Op<D = K, R = R2>, R2, R3: AddAssign<R3>>(
+            self,
+            other: Relation<C2>,
+        ) -> Relation<impl Op<D = C::D, R = R3>>
+        where
+            C::R: Mul<R2, Output = R3>,
+        {
+            self.join(other.map(|x| (x, ()))).map(|(k, x, ())| (k, x))
+        }
+    }
+}
+
+mod core {
+    mod operator {
+        mod join {
+            use super::Op;
+            use crate::core::Relation;
+            use std::ops::{AddAssign, Mul};
+            struct Join<LC, RC> {
+                _left: LC,
+                _right: RC,
+            }
+            impl<
+                    LC: Op<D = (K, LD), R = LR>,
+                    RC: Op<D = (K, RD), R = RR>,
+                    K: 'static,
+                    LD: 'static,
+                    LR: AddAssign<LR> + Mul<RR, Output = OR>,
+                    RD: 'static,
+                    RR: AddAssign<RR>,
+                    OR: AddAssign<OR>,
+                > Op for Join<LC, RC>
+            {
+                type D = (K, LD, RD);
+                type R = OR;
+            }
+            impl<K: 'static, D: 'static, C: Op<D = (K, D)>> Relation<C> {
+                pub fn join<C2: Op<D = (K, D2)>, D2: 'static, OR: AddAssign<OR>>(
+                    self,
+                    other: Relation<C2>,
+                ) -> Relation<impl Op<D = (K, D, D2), R = OR>>
+                where
+                    C::R: Mul<C2::R, Output = OR>,
+                {
+                    Relation {
+                        inner: Join {
+                            _left: self.inner,
+                            _right: other.inner,
+                        },
+                    }
+                }
+            }
+        }
+        mod map {
+            use super::Op;
+            use crate::core::Relation;
+            use std::ops::AddAssign;
+            struct Map<C, MF> {
+                _inner: C,
+                _op: MF,
+            }
+            impl<
+                    D1,
+                    R1,
+                    D2: 'static,
+                    R2: AddAssign<R2>,
+                    C: Op<D = D1, R = R1>,
+                    MF: Fn(D1, R1) -> (D2, R2),
+                > Op for Map<C, MF>
+            {
+                type D = D2;
+                type R = R2;
+            }
+            impl<C: Op> Relation<C> {
+                pub fn map_dr<F: Fn(C::D, C::R) -> (D2, R2), D2: 'static, R2: AddAssign<R2>>(
+                    self,
+                    f: F,
+                ) -> Relation<impl Op<D = D2, R = R2>> {
+                    Relation {
+                        inner: Map {
+                            _inner: self.inner,
+                            _op: f,
+                        },
+                    }
+                }
+            }
+        }
+        use std::ops::AddAssign;
+        pub trait Op {
+            type D: 'static;
+            type R: AddAssign<Self::R>;
+        }
+    }
+    pub use self::operator::Op;
+    #[derive(Clone)]
+    pub struct Relation<C> {
+        inner: C,
+    }
+}
+
+use self::core::Op;
+pub use self::core::Relation;
+
+fn main() {}
diff --git a/src/test/ui/associated-types/issue-85103.rs b/src/test/ui/associated-types/issue-85103.rs
new file mode 100644 (file)
index 0000000..c5e1385
--- /dev/null
@@ -0,0 +1,9 @@
+#![feature(rustc_attrs)]
+
+use std::borrow::Cow;
+
+#[rustc_layout(debug)]
+type Edges<'a, E> = Cow<'a, [E]>;
+//~^ ERROR layout error: NormalizationFailure
+
+fn main() {}
diff --git a/src/test/ui/associated-types/issue-85103.stderr b/src/test/ui/associated-types/issue-85103.stderr
new file mode 100644 (file)
index 0000000..142f3c4
--- /dev/null
@@ -0,0 +1,8 @@
+error: layout error: NormalizationFailure(<[E] as std::borrow::ToOwned>::Owned, Type(<[E] as std::borrow::ToOwned>::Owned))
+  --> $DIR/issue-85103.rs:6:1
+   |
+LL | type Edges<'a, E> = Cow<'a, [E]>;
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/associated-types/issue-88856.rs b/src/test/ui/associated-types/issue-88856.rs
new file mode 100644 (file)
index 0000000..7cae7c7
--- /dev/null
@@ -0,0 +1,32 @@
+// check-pass
+
+#![feature(generic_const_exprs)]
+#![allow(incomplete_features)]
+
+pub trait Trait{
+    type R;
+    fn func(self)->Self::R;
+}
+
+pub struct TraitImpl<const N:usize>(pub i32);
+
+impl<const N:usize> Trait for TraitImpl<N>
+where [();N/2]:,
+{
+    type R = Self;
+    fn func(self)->Self::R {
+        self
+    }
+}
+
+fn sample<P,Convert>(p:P,f:Convert) -> i32
+where
+    P:Trait,Convert:Fn(P::R)->i32
+{
+    f(p.func())
+}
+
+fn main() {
+    let t = TraitImpl::<10>(4);
+    sample(t,|x|x.0);
+}
diff --git a/src/test/ui/associated-types/issue-91231.rs b/src/test/ui/associated-types/issue-91231.rs
new file mode 100644 (file)
index 0000000..3c1cb81
--- /dev/null
@@ -0,0 +1,17 @@
+// check-pass
+
+#![feature(extern_types)]
+#![allow(dead_code)]
+
+extern {
+    type Extern;
+}
+
+trait Trait {
+    type Type;
+}
+
+#[inline]
+fn f<'a>(_: <&'a Extern as Trait>::Type) where &'a Extern: Trait {}
+
+fn main() {}
diff --git a/src/test/ui/associated-types/issue-91234.rs b/src/test/ui/associated-types/issue-91234.rs
new file mode 100644 (file)
index 0000000..2f6c2d3
--- /dev/null
@@ -0,0 +1,13 @@
+// check-pass
+
+struct Struct;
+
+trait Trait {
+    type Type;
+}
+
+enum Enum<'a> where &'a Struct: Trait {
+    Variant(<&'a Struct as Trait>::Type)
+}
+
+fn main() {}
index c7e357d4604f71a61139add1a416b3c8dae93dc2..d2c7473c036b8769fbcfacccf3792b38cc637cef 100644 (file)
@@ -3,6 +3,8 @@ error[E0381]: borrow of possibly-uninitialized variable: `i`
    |
 LL |     println!("{}", i);
    |                    ^ use of possibly-uninitialized `i`
+   |
+   = note: this error originates in the macro `$crate::format_args_nl` (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error: aborting due to previous error
 
index bc9b25c0221fcc59dad651a328f2ebe5575956dc..b134f5cc2d8e3d950e53c3ee966ae0d5aa458eeb 100644 (file)
@@ -3,6 +3,8 @@ error[E0381]: borrow of possibly-uninitialized variable: `x`
    |
 LL |     println!("{}", x);
    |                    ^ use of possibly-uninitialized `x`
+   |
+   = note: this error originates in the macro `$crate::format_args_nl` (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error: aborting due to previous error
 
index 766d5cfd6348cd60dc373367100434e827d81ee7..652d7d3076fbda4494248b7573e58784e2ad3d8c 100644 (file)
@@ -3,6 +3,8 @@ error[E0381]: borrow of possibly-uninitialized variable: `x`
    |
 LL |     println!("{}", x);
    |                    ^ use of possibly-uninitialized `x`
+   |
+   = note: this error originates in the macro `$crate::format_args_nl` (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error: aborting due to previous error
 
index 3fe8d9eededc5373b3d5c2868803333d846456f8..6c757759f71344514af75d2a2b486bcc0324978f 100644 (file)
@@ -3,6 +3,8 @@ error[E0381]: borrow of possibly-uninitialized variable: `i`
    |
 LL |     println!("{}", i);
    |                    ^ use of possibly-uninitialized `i`
+   |
+   = note: this error originates in the macro `$crate::format_args_nl` (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error: aborting due to previous error
 
index 3eaaf8d7df08d30acab3a83f31bf59cf60612efd..fc144a066bb2777fe14784b24128c3d880fef2b0 100644 (file)
@@ -3,6 +3,8 @@ error[E0381]: borrow of possibly-uninitialized variable: `v`
    |
 LL |     println!("{}", v);
    |                    ^ use of possibly-uninitialized `v`
+   |
+   = note: this error originates in the macro `$crate::format_args_nl` (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error: aborting due to previous error
 
index 4eb41ca24ddfe1e72b21ae9dd2b08365fc393fe7..e29cf7a1a7519bb8abde2c717b71416354e0b235 100644 (file)
@@ -3,12 +3,16 @@ error[E0381]: borrow of possibly-uninitialized variable: `x`
    |
 LL |     println!("{}", x);
    |                    ^ use of possibly-uninitialized `x`
+   |
+   = note: this error originates in the macro `$crate::format_args_nl` (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error[E0381]: borrow of possibly-uninitialized variable: `x`
   --> $DIR/issue-24267-flow-exit.rs:18:20
    |
 LL |     println!("{}", x);
    |                    ^ use of possibly-uninitialized `x`
+   |
+   = note: this error originates in the macro `$crate::format_args_nl` (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error: aborting due to 2 previous errors
 
index 1cdcc18632c62c3193abdca0616cca1c060c089b..10400cff5e51c33396addda8af0a1930e6963b34 100644 (file)
@@ -1,5 +1,5 @@
 error[E0594]: cannot assign to `x`, as it is not declared as mutable
-  --> $DIR/issue-55492-borrowck-migrate-scans-parents.rs:19:46
+  --> $DIR/issue-55492-borrowck-migrate-scans-parents.rs:17:46
    |
 LL |     pub fn e(x: &'static mut isize) {
    |              - help: consider changing this to be mutable: `mut x`
@@ -8,7 +8,7 @@ LL |         let mut c1 = |y: &'static mut isize| x = y;
    |                                              ^^^^^ cannot assign
 
 error[E0594]: cannot assign to `x`, as it is not declared as mutable
-  --> $DIR/issue-55492-borrowck-migrate-scans-parents.rs:30:50
+  --> $DIR/issue-55492-borrowck-migrate-scans-parents.rs:28:50
    |
 LL |     pub fn ee(x: &'static mut isize) {
    |               - help: consider changing this to be mutable: `mut x`
@@ -17,7 +17,7 @@ LL |             let mut c2 = |y: &'static mut isize| x = y;
    |                                                  ^^^^^ cannot assign
 
 error[E0594]: cannot assign to `x`, as it is not declared as mutable
-  --> $DIR/issue-55492-borrowck-migrate-scans-parents.rs:42:14
+  --> $DIR/issue-55492-borrowck-migrate-scans-parents.rs:40:14
    |
 LL |     pub fn capture_assign_whole(x: (i32,)) {
    |                                 - help: consider changing this to be mutable: `mut x`
@@ -25,7 +25,7 @@ LL |         || { x = (1,); };
    |              ^^^^^^^^ cannot assign
 
 error[E0594]: cannot assign to `x.0`, as `x` is not declared as mutable
-  --> $DIR/issue-55492-borrowck-migrate-scans-parents.rs:47:14
+  --> $DIR/issue-55492-borrowck-migrate-scans-parents.rs:45:14
    |
 LL |     pub fn capture_assign_part(x: (i32,)) {
    |                                - help: consider changing this to be mutable: `mut x`
@@ -33,7 +33,7 @@ LL |         || { x.0 = 1; };
    |              ^^^^^^^ cannot assign
 
 error[E0596]: cannot borrow `x` as mutable, as it is not declared as mutable
-  --> $DIR/issue-55492-borrowck-migrate-scans-parents.rs:52:14
+  --> $DIR/issue-55492-borrowck-migrate-scans-parents.rs:50:14
    |
 LL |     pub fn capture_reborrow_whole(x: (i32,)) {
    |                                   - help: consider changing this to be mutable: `mut x`
@@ -41,7 +41,7 @@ LL |         || { &mut x; };
    |              ^^^^^^ cannot borrow as mutable
 
 error[E0596]: cannot borrow `x.0` as mutable, as `x` is not declared as mutable
-  --> $DIR/issue-55492-borrowck-migrate-scans-parents.rs:57:14
+  --> $DIR/issue-55492-borrowck-migrate-scans-parents.rs:55:14
    |
 LL |     pub fn capture_reborrow_part(x: (i32,)) {
    |                                  - help: consider changing this to be mutable: `mut x`
index 1cdcc18632c62c3193abdca0616cca1c060c089b..10400cff5e51c33396addda8af0a1930e6963b34 100644 (file)
@@ -1,5 +1,5 @@
 error[E0594]: cannot assign to `x`, as it is not declared as mutable
-  --> $DIR/issue-55492-borrowck-migrate-scans-parents.rs:19:46
+  --> $DIR/issue-55492-borrowck-migrate-scans-parents.rs:17:46
    |
 LL |     pub fn e(x: &'static mut isize) {
    |              - help: consider changing this to be mutable: `mut x`
@@ -8,7 +8,7 @@ LL |         let mut c1 = |y: &'static mut isize| x = y;
    |                                              ^^^^^ cannot assign
 
 error[E0594]: cannot assign to `x`, as it is not declared as mutable
-  --> $DIR/issue-55492-borrowck-migrate-scans-parents.rs:30:50
+  --> $DIR/issue-55492-borrowck-migrate-scans-parents.rs:28:50
    |
 LL |     pub fn ee(x: &'static mut isize) {
    |               - help: consider changing this to be mutable: `mut x`
@@ -17,7 +17,7 @@ LL |             let mut c2 = |y: &'static mut isize| x = y;
    |                                                  ^^^^^ cannot assign
 
 error[E0594]: cannot assign to `x`, as it is not declared as mutable
-  --> $DIR/issue-55492-borrowck-migrate-scans-parents.rs:42:14
+  --> $DIR/issue-55492-borrowck-migrate-scans-parents.rs:40:14
    |
 LL |     pub fn capture_assign_whole(x: (i32,)) {
    |                                 - help: consider changing this to be mutable: `mut x`
@@ -25,7 +25,7 @@ LL |         || { x = (1,); };
    |              ^^^^^^^^ cannot assign
 
 error[E0594]: cannot assign to `x.0`, as `x` is not declared as mutable
-  --> $DIR/issue-55492-borrowck-migrate-scans-parents.rs:47:14
+  --> $DIR/issue-55492-borrowck-migrate-scans-parents.rs:45:14
    |
 LL |     pub fn capture_assign_part(x: (i32,)) {
    |                                - help: consider changing this to be mutable: `mut x`
@@ -33,7 +33,7 @@ LL |         || { x.0 = 1; };
    |              ^^^^^^^ cannot assign
 
 error[E0596]: cannot borrow `x` as mutable, as it is not declared as mutable
-  --> $DIR/issue-55492-borrowck-migrate-scans-parents.rs:52:14
+  --> $DIR/issue-55492-borrowck-migrate-scans-parents.rs:50:14
    |
 LL |     pub fn capture_reborrow_whole(x: (i32,)) {
    |                                   - help: consider changing this to be mutable: `mut x`
@@ -41,7 +41,7 @@ LL |         || { &mut x; };
    |              ^^^^^^ cannot borrow as mutable
 
 error[E0596]: cannot borrow `x.0` as mutable, as `x` is not declared as mutable
-  --> $DIR/issue-55492-borrowck-migrate-scans-parents.rs:57:14
+  --> $DIR/issue-55492-borrowck-migrate-scans-parents.rs:55:14
    |
 LL |     pub fn capture_reborrow_part(x: (i32,)) {
    |                                  - help: consider changing this to be mutable: `mut x`
index 751a911a6bb862c4bb68580741941912a0d11e3d..fe7ed8ed3fa248cf2769f5c2e248430a6964daf7 100644 (file)
@@ -3,15 +3,13 @@
 // looks at some parent.
 
 // revisions: migrate nll
+//[nll]compile-flags: -Z borrowck=mir
 
 // Since we are testing nll (and migration) explicitly as a separate
 // revisions, don't worry about the --compare-mode=nll on this test.
 
 // ignore-compare-mode-nll
 
-//[nll]compile-flags: -Z borrowck=mir
-
-
 // transcribed from borrowck-closures-unique.rs
 mod borrowck_closures_unique {
     pub fn e(x: &'static mut isize) {
diff --git a/src/test/ui/borrowck/issue-58776-borrowck-scans-children.migrate.stderr b/src/test/ui/borrowck/issue-58776-borrowck-scans-children.migrate.stderr
deleted file mode 100644 (file)
index efd4e1a..0000000
+++ /dev/null
@@ -1,32 +0,0 @@
-error[E0506]: cannot assign to `greeting` because it is borrowed
-  --> $DIR/issue-58776-borrowck-scans-children.rs:11:5
-   |
-LL |     let res = (|| (|| &greeting)())();
-   |                --      -------- borrow occurs due to use in closure
-   |                |
-   |                borrow of `greeting` occurs here
-LL | 
-LL |     greeting = "DEALLOCATED".to_string();
-   |     ^^^^^^^^ assignment to borrowed `greeting` occurs here
-...
-LL |     println!("thread result: {:?}", res);
-   |                                     --- borrow later used here
-
-error[E0505]: cannot move out of `greeting` because it is borrowed
-  --> $DIR/issue-58776-borrowck-scans-children.rs:14:10
-   |
-LL |     let res = (|| (|| &greeting)())();
-   |                --      -------- borrow occurs due to use in closure
-   |                |
-   |                borrow of `greeting` occurs here
-...
-LL |     drop(greeting);
-   |          ^^^^^^^^ move out of `greeting` occurs here
-...
-LL |     println!("thread result: {:?}", res);
-   |                                     --- borrow later used here
-
-error: aborting due to 2 previous errors
-
-Some errors have detailed explanations: E0505, E0506.
-For more information about an error, try `rustc --explain E0505`.
index a3f2f25e447e1ac500cff609f5136a058678adb7..f6c219018321141366399327174683f57402511e 100644 (file)
@@ -81,6 +81,8 @@ LL |     println!("{}", arr[3]);
 ...
 LL |     c();
    |     - mutable borrow later used here
+   |
+   = note: this error originates in the macro `$crate::format_args_nl` (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error[E0502]: cannot borrow `arr` as immutable because it is also borrowed as mutable
   --> $DIR/arrays.rs:73:24
index 2badf0514187eb135ec44b6d9cf4ca04bfd0c83d..29228d85324ef3f39476fb7cd1b558786064d838 100644 (file)
@@ -25,6 +25,8 @@ LL |     println!("{}", e.0.0.m.x);
 LL |
 LL |     c();
    |     - mutable borrow later used here
+   |
+   = note: this error originates in the macro `$crate::format_args_nl` (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error[E0506]: cannot assign to `e.0.0.m.x` because it is borrowed
   --> $DIR/box.rs:55:5
index d2466681a0877a24836da8cd4ed7d180699ec12e..5acf3797ab53feb51128c32fc6248509ea116d60 100644 (file)
@@ -8,6 +8,7 @@ LL |         println!("{}", foo.x);
    = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
    = note: for more information, see issue #82523 <https://github.com/rust-lang/rust/issues/82523>
    = note: fields of packed structs are not properly aligned, and creating a misaligned reference is undefined behavior (even if that reference is never dereferenced)
+   = note: this warning originates in the macro `$crate::format_args_nl` (in Nightly builds, run with -Z macro-backtrace for more info)
 
 warning: 1 warning emitted
 
index 32705af3d016623eba451e00feba3c98ef12328c..4f9fdbd368a88e1e8e3ac2cd93f19687c00f0605 100644 (file)
@@ -13,6 +13,8 @@ LL |     println!("{:?}", p);
 LL |
 LL |     c();
    |     - mutable borrow later used here
+   |
+   = note: this error originates in the macro `$crate::format_args_nl` (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error: aborting due to previous error
 
index e067dbbf85bddbfcb03004c38991f4f29f202f5b..ceb91142ac82699eb6dc1be7aecc37a19a659acc 100644 (file)
@@ -14,6 +14,7 @@ note: this function takes ownership of the receiver `self`, which moves `some_ve
    |
 LL |     fn into_iter(self) -> Self::IntoIter;
    |                  ^^^^
+   = note: this error originates in the macro `$crate::format_args_nl` (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error: aborting due to previous error
 
index 3a7095789336c26bbd9a945a30ee1a4a7b6cc9c4..02dce4f7a97e829d1f886d0a8025a41a77d81e64 100644 (file)
@@ -1,5 +1,5 @@
 error: generic parameters may not be used in const operations
-  --> $DIR/issue-72787.rs:12:17
+  --> $DIR/issue-72787.rs:11:17
    |
 LL |     Condition<{ LHS <= RHS }>: True
    |                 ^^^ cannot perform const operation using `LHS`
@@ -8,7 +8,7 @@ LL |     Condition<{ LHS <= RHS }>: True
    = help: use `#![feature(generic_const_exprs)]` to allow generic const expressions
 
 error: generic parameters may not be used in const operations
-  --> $DIR/issue-72787.rs:12:24
+  --> $DIR/issue-72787.rs:11:24
    |
 LL |     Condition<{ LHS <= RHS }>: True
    |                        ^^^ cannot perform const operation using `RHS`
@@ -17,7 +17,7 @@ LL |     Condition<{ LHS <= RHS }>: True
    = help: use `#![feature(generic_const_exprs)]` to allow generic const expressions
 
 error: generic parameters may not be used in const operations
-  --> $DIR/issue-72787.rs:26:25
+  --> $DIR/issue-72787.rs:25:25
    |
 LL |     IsLessOrEqual<{ 8 - I }, { 8 - J }>: True,
    |                         ^ cannot perform const operation using `I`
@@ -26,7 +26,7 @@ LL |     IsLessOrEqual<{ 8 - I }, { 8 - J }>: True,
    = help: use `#![feature(generic_const_exprs)]` to allow generic const expressions
 
 error: generic parameters may not be used in const operations
-  --> $DIR/issue-72787.rs:26:36
+  --> $DIR/issue-72787.rs:25:36
    |
 LL |     IsLessOrEqual<{ 8 - I }, { 8 - J }>: True,
    |                                    ^ cannot perform const operation using `J`
@@ -35,15 +35,7 @@ LL |     IsLessOrEqual<{ 8 - I }, { 8 - J }>: True,
    = help: use `#![feature(generic_const_exprs)]` to allow generic const expressions
 
 error[E0283]: type annotations needed
-  --> $DIR/issue-72787.rs:10:38
-   |
-LL | impl<const LHS: u32, const RHS: u32> True for IsLessOrEqual<LHS, RHS> where
-   |                                      ^^^^ cannot infer type for struct `IsLessOrEqual<LHS, RHS>`
-   |
-   = note: cannot satisfy `IsLessOrEqual<LHS, RHS>: True`
-
-error[E0283]: type annotations needed
-  --> $DIR/issue-72787.rs:22:26
+  --> $DIR/issue-72787.rs:21:26
    |
 LL |     IsLessOrEqual<I, 8>: True,
    |                          ^^^^ cannot infer type for struct `IsLessOrEqual<I, 8_u32>`
@@ -51,13 +43,13 @@ LL |     IsLessOrEqual<I, 8>: True,
    = note: cannot satisfy `IsLessOrEqual<I, 8_u32>: True`
 
 error[E0283]: type annotations needed
-  --> $DIR/issue-72787.rs:22:26
+  --> $DIR/issue-72787.rs:21:26
    |
 LL |     IsLessOrEqual<I, 8>: True,
    |                          ^^^^ cannot infer type for struct `IsLessOrEqual<I, 8_u32>`
    |
    = note: cannot satisfy `IsLessOrEqual<I, 8_u32>: True`
 
-error: aborting due to 7 previous errors
+error: aborting due to 6 previous errors
 
 For more information about this error, try `rustc --explain E0283`.
index 2ea5d634f6ef3c94d98833eacd68167766be5833..77ad57f0640fa03260dec80aa3e95bc2f706493c 100644 (file)
@@ -8,7 +8,6 @@
 pub trait True {}
 
 impl<const LHS: u32, const RHS: u32> True for IsLessOrEqual<LHS, RHS> where
-//[min]~^ ERROR type annotations needed
     Condition<{ LHS <= RHS }>: True
 //[min]~^ Error generic parameters may not be used in const operations
 //[min]~| Error generic parameters may not be used in const operations
diff --git a/src/test/ui/consts/assert-type-intrinsics.rs b/src/test/ui/consts/assert-type-intrinsics.rs
new file mode 100644 (file)
index 0000000..31ff6ae
--- /dev/null
@@ -0,0 +1,22 @@
+// error-pattern: any use of this value will cause an error
+
+#![feature(never_type)]
+#![feature(const_maybe_uninit_assume_init, const_assert_type2)]
+#![feature(core_intrinsics)]
+
+use std::intrinsics;
+
+#[allow(invalid_value)]
+fn main() {
+    use std::mem::MaybeUninit;
+
+    const _BAD1: () = unsafe {
+        MaybeUninit::<!>::uninit().assume_init();
+    };
+    const _BAD2: () = unsafe {
+        intrinsics::assert_uninit_valid::<bool>();
+    };
+    const _BAD3: () = unsafe {
+        intrinsics::assert_zero_valid::<&'static i32>();
+    };
+}
diff --git a/src/test/ui/consts/assert-type-intrinsics.stderr b/src/test/ui/consts/assert-type-intrinsics.stderr
new file mode 100644 (file)
index 0000000..bb57ee8
--- /dev/null
@@ -0,0 +1,39 @@
+error: any use of this value will cause an error
+  --> $DIR/assert-type-intrinsics.rs:14:9
+   |
+LL | /     const _BAD1: () = unsafe {
+LL | |         MaybeUninit::<!>::uninit().assume_init();
+   | |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ aborted execution: attempted to instantiate uninhabited type `!`
+LL | |     };
+   | |______-
+   |
+   = note: `#[deny(const_err)]` on by default
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
+
+error: any use of this value will cause an error
+  --> $DIR/assert-type-intrinsics.rs:17:9
+   |
+LL | /     const _BAD2: () = unsafe {
+LL | |         intrinsics::assert_uninit_valid::<bool>();
+   | |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ aborted execution: attempted to leave type `bool` uninitialized, which is invalid
+LL | |     };
+   | |______-
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
+
+error: any use of this value will cause an error
+  --> $DIR/assert-type-intrinsics.rs:20:9
+   |
+LL | /     const _BAD3: () = unsafe {
+LL | |         intrinsics::assert_zero_valid::<&'static i32>();
+   | |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ aborted execution: attempted to zero-initialize type `&i32`, which is invalid
+LL | |     };
+   | |______-
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
+
+error: aborting due to 3 previous errors
+
diff --git a/src/test/ui/consts/assume-type-intrinsics.rs b/src/test/ui/consts/assume-type-intrinsics.rs
deleted file mode 100644 (file)
index 77370e1..0000000
+++ /dev/null
@@ -1,13 +0,0 @@
-// error-pattern: any use of this value will cause an error
-
-#![feature(never_type)]
-#![feature(const_maybe_uninit_assume_init)]
-
-#[allow(invalid_value)]
-fn main() {
-    use std::mem::MaybeUninit;
-
-    const _BAD: () = unsafe {
-        MaybeUninit::<!>::uninit().assume_init();
-    };
-}
diff --git a/src/test/ui/consts/assume-type-intrinsics.stderr b/src/test/ui/consts/assume-type-intrinsics.stderr
deleted file mode 100644 (file)
index e660730..0000000
+++ /dev/null
@@ -1,15 +0,0 @@
-error: any use of this value will cause an error
-  --> $DIR/assume-type-intrinsics.rs:11:9
-   |
-LL | /     const _BAD: () = unsafe {
-LL | |         MaybeUninit::<!>::uninit().assume_init();
-   | |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ aborted execution: attempted to instantiate uninhabited type `!`
-LL | |     };
-   | |______-
-   |
-   = note: `#[deny(const_err)]` on by default
-   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
-   = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
-
-error: aborting due to previous error
-
index 3bd5ed8f8c924099e2906f18c8ea735441bb3d32..5e6d7d899ec1ea87bc5c311126b980a385d17617 100644 (file)
@@ -1,6 +1,6 @@
-static a: &'static str = "foo";
-static b: *const u8 = a as *const u8; //~ ERROR casting
-static c: *const u8 = &a as *const u8; //~ ERROR casting
+const a: &str = "foo";
+const b: *const u8 = a as *const u8; //~ ERROR casting
+const c: *const u8 = &a as *const u8; //~ ERROR casting
 
 fn main() {
 }
index 9960ccb4166b5aea72447418334c81b85d444512..9e622de2eb004ecdff911c191ebf42ac80a3c24d 100644 (file)
@@ -1,14 +1,14 @@
 error[E0606]: casting `&'static str` as `*const u8` is invalid
-  --> $DIR/const-cast-different-types.rs:2:23
+  --> $DIR/const-cast-different-types.rs:2:22
    |
-LL | static b: *const u8 = a as *const u8;
-   |                       ^^^^^^^^^^^^^^
+LL | const b: *const u8 = a as *const u8;
+   |                      ^^^^^^^^^^^^^^
 
 error[E0606]: casting `&&'static str` as `*const u8` is invalid
-  --> $DIR/const-cast-different-types.rs:3:23
+  --> $DIR/const-cast-different-types.rs:3:22
    |
-LL | static c: *const u8 = &a as *const u8;
-   |                       ^^^^^^^^^^^^^^^
+LL | const c: *const u8 = &a as *const u8;
+   |                      ^^^^^^^^^^^^^^^
 
 error: aborting due to 2 previous errors
 
index c250cc53dbc2b07dd73eb7b35be00de060b90748..6e055a2bcd34029c24e55e05d4f02189be052fd7 100644 (file)
@@ -1,5 +1,5 @@
-static a: [u8; 3] = ['h' as u8, 'i' as u8, 0 as u8];
-static b: *const i8 = &a as *const i8; //~ ERROR mismatched types
+const a: [u8; 3] = ['h' as u8, 'i' as u8, 0 as u8];
+const b: *const i8 = &a as *const i8; //~ ERROR mismatched types
 
 fn main() {
 }
index 282f5ccde772fd62c511e001ec7eeaad68fbad3c..ee186636e4ebe0fe61c7127b2153a658d78505c7 100644 (file)
@@ -1,8 +1,8 @@
 error[E0308]: mismatched types
-  --> $DIR/const-cast-wrong-type.rs:2:23
+  --> $DIR/const-cast-wrong-type.rs:2:22
    |
-LL | static b: *const i8 = &a as *const i8;
-   |                       ^^^^^^^^^^^^^^^ expected `u8`, found `i8`
+LL | const b: *const i8 = &a as *const i8;
+   |                      ^^^^^^^^^^^^^^^ expected `u8`, found `i8`
 
 error: aborting due to previous error
 
index 356a7f58d8562eb36e1221c218e059ab05d70e2f..9dc40030a6ff8b1a2a3530d411c327604508145b 100644 (file)
@@ -28,6 +28,7 @@ LL |     println!("{}", FOO);
    |
    = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
    = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
+   = note: this warning originates in the macro `$crate::format_args_nl` (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error: aborting due to previous error; 2 warnings emitted
 
index d4d8cbc669a7bf3a4a970eddda29d2cbf6f2e61d..32ab7c74b891f894f708b50e0af77b4e00c733f3 100644 (file)
@@ -39,6 +39,7 @@ LL |     println!("{} {}", X, Y);
    |
    = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
    = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
+   = note: this warning originates in the macro `$crate::format_args_nl` (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error[E0080]: evaluation of constant value failed
   --> $DIR/issue-43197.rs:16:26
@@ -54,6 +55,7 @@ LL |     println!("{} {}", X, Y);
    |
    = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
    = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
+   = note: this warning originates in the macro `$crate::format_args_nl` (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error: aborting due to 2 previous errors; 4 warnings emitted
 
index 1060675cd45f4937460cc0e655163faf136354be..fb082bc1eabcf51bcd907f1e6d7e802fa2a4188f 100644 (file)
@@ -1,5 +1,5 @@
 error[E0161]: cannot move a value of type dyn Bar: the size of dyn Bar cannot be statically determined
-  --> $DIR/E0161.rs:29:5
+  --> $DIR/E0161.rs:32:5
    |
 LL |     x.f();
    |     ^^^^^
index 1060675cd45f4937460cc0e655163faf136354be..fb082bc1eabcf51bcd907f1e6d7e802fa2a4188f 100644 (file)
@@ -1,5 +1,5 @@
 error[E0161]: cannot move a value of type dyn Bar: the size of dyn Bar cannot be statically determined
-  --> $DIR/E0161.rs:29:5
+  --> $DIR/E0161.rs:32:5
    |
 LL |     x.f();
    |     ^^^^^
index 1060675cd45f4937460cc0e655163faf136354be..fb082bc1eabcf51bcd907f1e6d7e802fa2a4188f 100644 (file)
@@ -1,5 +1,5 @@
 error[E0161]: cannot move a value of type dyn Bar: the size of dyn Bar cannot be statically determined
-  --> $DIR/E0161.rs:29:5
+  --> $DIR/E0161.rs:32:5
    |
 LL |     x.f();
    |     ^^^^^
index ba74529e4b6e43f6bdf837c88333b60891bb843a..f3a7b68c7cf850eac4521ad4082321152d58e42d 100644 (file)
@@ -1,5 +1,3 @@
-// ignore-compare-mode-nll
-
 // Check that E0161 is a hard error in all possible configurations that might
 // affect it.
 
 //[zflagsul] check-pass
 //[editionul] check-pass
 
+// Since we are testing nll (and migration) explicitly as a separate
+// revisions, don't worry about the --compare-mode=nll on this test.
+
+// ignore-compare-mode-nll
+
 #![allow(incomplete_features)]
 #![cfg_attr(nll, feature(nll))]
 #![cfg_attr(nllul, feature(nll))]
index 1060675cd45f4937460cc0e655163faf136354be..fb082bc1eabcf51bcd907f1e6d7e802fa2a4188f 100644 (file)
@@ -1,5 +1,5 @@
 error[E0161]: cannot move a value of type dyn Bar: the size of dyn Bar cannot be statically determined
-  --> $DIR/E0161.rs:29:5
+  --> $DIR/E0161.rs:32:5
    |
 LL |     x.f();
    |     ^^^^^
diff --git a/src/test/ui/fn/implied-bounds-unnorm-associated-type.nll.stderr b/src/test/ui/fn/implied-bounds-unnorm-associated-type.nll.stderr
new file mode 100644 (file)
index 0000000..e37ec7f
--- /dev/null
@@ -0,0 +1,14 @@
+error: lifetime may not live long enough
+  --> $DIR/implied-bounds-unnorm-associated-type.rs:14:5
+   |
+LL | fn f<'a, 'b>(s: &'b str, _: <&'a &'b () as Trait>::Type) -> &'a str {
+   |      --  -- lifetime `'b` defined here
+   |      |
+   |      lifetime `'a` defined here
+LL |     s
+   |     ^ returning this value requires that `'b` must outlive `'a`
+   |
+   = help: consider adding the following bound: `'b: 'a`
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/fn/implied-bounds-unnorm-associated-type.rs b/src/test/ui/fn/implied-bounds-unnorm-associated-type.rs
new file mode 100644 (file)
index 0000000..2e5ac7d
--- /dev/null
@@ -0,0 +1,22 @@
+// check-fail
+// See issue #91068. Types in the substs of an associated type can't be implied
+// to be WF, since they don't actually have to be constructed.
+
+trait Trait {
+    type Type;
+}
+
+impl<T> Trait for T {
+    type Type = ();
+}
+
+fn f<'a, 'b>(s: &'b str, _: <&'a &'b () as Trait>::Type) -> &'a str {
+    s //~ ERROR lifetime mismatch [E0623]
+}
+
+fn main() {
+    let x = String::from("Hello World!");
+    let y = f(&x, ());
+    drop(x);
+    println!("{}", y);
+}
diff --git a/src/test/ui/fn/implied-bounds-unnorm-associated-type.stderr b/src/test/ui/fn/implied-bounds-unnorm-associated-type.stderr
new file mode 100644 (file)
index 0000000..93ab5dc
--- /dev/null
@@ -0,0 +1,13 @@
+error[E0623]: lifetime mismatch
+  --> $DIR/implied-bounds-unnorm-associated-type.rs:14:5
+   |
+LL | fn f<'a, 'b>(s: &'b str, _: <&'a &'b () as Trait>::Type) -> &'a str {
+   |                 -------      ----------
+   |                 |
+   |                 these two types are declared with different lifetimes...
+LL |     s
+   |     ^ ...but data from `s` flows here
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0623`.
index 68d785efcfe5d5620fa1e6c89604c92a74fd8d9f..67cd1f64d94aad1130f672fe48a3c3e320035938 100644 (file)
@@ -10,6 +10,8 @@ LL |     println!("{}", x);
    |                    ^ second borrow occurs here
 LL |     Pin::new(&mut b).resume(());
    |              ------ first borrow later used here
+   |
+   = note: this error originates in the macro `$crate::format_args_nl` (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/generic-associated-types/equality-bound.rs b/src/test/ui/generic-associated-types/equality-bound.rs
new file mode 100644 (file)
index 0000000..fcc2da8
--- /dev/null
@@ -0,0 +1,15 @@
+fn sum<I: Iterator<Item = ()>>(i: I) -> i32 where I::Item = i32 {
+//~^ ERROR equality constraints are not yet supported in `where` clauses
+    panic!()
+}
+fn sum2<I: Iterator>(i: I) -> i32 where I::Item = i32 {
+//~^ ERROR equality constraints are not yet supported in `where` clauses
+    panic!()
+}
+fn sum3<J: Iterator>(i: J) -> i32 where I::Item = i32 {
+//~^ ERROR equality constraints are not yet supported in `where` clauses
+//~| ERROR failed to resolve: use of undeclared type `I`
+    panic!()
+}
+
+fn main() {}
diff --git a/src/test/ui/generic-associated-types/equality-bound.stderr b/src/test/ui/generic-associated-types/equality-bound.stderr
new file mode 100644 (file)
index 0000000..2743264
--- /dev/null
@@ -0,0 +1,43 @@
+error: equality constraints are not yet supported in `where` clauses
+  --> $DIR/equality-bound.rs:1:51
+   |
+LL | fn sum<I: Iterator<Item = ()>>(i: I) -> i32 where I::Item = i32 {
+   |                                                   ^^^^^^^^^^^^^ not supported
+   |
+   = note: see issue #20041 <https://github.com/rust-lang/rust/issues/20041> for more information
+help: if `Iterator::Item` is an associated type you're trying to set, use the associated type binding syntax
+   |
+LL - fn sum<I: Iterator<Item = ()>>(i: I) -> i32 where I::Item = i32 {
+LL + fn sum<I: Iterator<Item = (), Item = i32>>(i: I) -> i32 where  {
+   | 
+
+error: equality constraints are not yet supported in `where` clauses
+  --> $DIR/equality-bound.rs:5:41
+   |
+LL | fn sum2<I: Iterator>(i: I) -> i32 where I::Item = i32 {
+   |                                         ^^^^^^^^^^^^^ not supported
+   |
+   = note: see issue #20041 <https://github.com/rust-lang/rust/issues/20041> for more information
+help: if `Iterator::Item` is an associated type you're trying to set, use the associated type binding syntax
+   |
+LL - fn sum2<I: Iterator>(i: I) -> i32 where I::Item = i32 {
+LL + fn sum2<I: Iterator<Item = i32>>(i: I) -> i32 where  {
+   | 
+
+error: equality constraints are not yet supported in `where` clauses
+  --> $DIR/equality-bound.rs:9:41
+   |
+LL | fn sum3<J: Iterator>(i: J) -> i32 where I::Item = i32 {
+   |                                         ^^^^^^^^^^^^^ not supported
+   |
+   = note: see issue #20041 <https://github.com/rust-lang/rust/issues/20041> for more information
+
+error[E0433]: failed to resolve: use of undeclared type `I`
+  --> $DIR/equality-bound.rs:9:41
+   |
+LL | fn sum3<J: Iterator>(i: J) -> i32 where I::Item = i32 {
+   |                                         ^ use of undeclared type `I`
+
+error: aborting due to 4 previous errors
+
+For more information about this error, try `rustc --explain E0433`.
diff --git a/src/test/ui/generic-associated-types/issue-87748.rs b/src/test/ui/generic-associated-types/issue-87748.rs
deleted file mode 100644 (file)
index 93c3b39..0000000
+++ /dev/null
@@ -1,30 +0,0 @@
-// Checks that we properly add implied bounds from unnormalized projections in
-// inputs when typechecking functions.
-
-// check-pass
-
-#![feature(generic_associated_types)]
-
-trait MyTrait {
-    type Assoc<'a, 'b> where 'b: 'a;
-    fn do_sth(arg: Self::Assoc<'_, '_>);
-}
-
-struct A;
-struct B;
-struct C;
-
-impl MyTrait for A {
-    type Assoc<'a, 'b> where 'b: 'a = u32;
-    fn do_sth(_: u32) {}
-}
-impl MyTrait for B {
-    type Assoc<'a, 'b> where 'b: 'a = u32;
-    fn do_sth(_: Self::Assoc<'_, '_>) {}
-}
-impl MyTrait for C {
-    type Assoc<'a, 'b> where 'b: 'a = u32;
-    fn do_sth(_: Self::Assoc<'static, 'static>) {}
-}
-
-fn main () {}
index 54478d16282452334dcdfd7e18a99e2d099f70ab..0e234120a51c5840a5a903c84772647bca701425 100644 (file)
@@ -34,11 +34,12 @@ impl<B: std::ops::Add<Output = B>> Add for D<B> {
 
 struct E<B>(B);
 
-impl<B: Add> Add for E<B> where B: Add<Output = B> {
+impl<B: Add> Add for E<B> where B: Add<Output = B>, B: Add<Output = B> {
+    //~^ ERROR equality constraints are not yet supported in `where` clauses
     type Output = Self;
 
     fn add(self, rhs: Self) -> Self {
-        Self(self.0 + rhs.0)
+        Self(self.0 + rhs.0) //~ ERROR mismatched types
     }
 }
 
index 962d2db9476bd73a0b690c940831ec83d567d308..ffafff5e9f586d2543061aaaa616eec501040f8a 100644 (file)
@@ -34,11 +34,12 @@ fn add(self, rhs: Self) -> Self {
 
 struct E<B>(B);
 
-impl<B: Add> Add for E<B> where B: Add<Output = B> {
+impl<B: Add> Add for E<B> where <B as Add>::Output = B {
+    //~^ ERROR equality constraints are not yet supported in `where` clauses
     type Output = Self;
 
     fn add(self, rhs: Self) -> Self {
-        Self(self.0 + rhs.0)
+        Self(self.0 + rhs.0) //~ ERROR mismatched types
     }
 }
 
index 4d33fe84829e0c6f42c25796741b61cc7f4bc570..c9603b8d1ea4a3bcebe045f1630099e1a08f51eb 100644 (file)
@@ -1,3 +1,15 @@
+error: equality constraints are not yet supported in `where` clauses
+  --> $DIR/missing-bounds.rs:37:33
+   |
+LL | impl<B: Add> Add for E<B> where <B as Add>::Output = B {
+   |                                 ^^^^^^^^^^^^^^^^^^^^^^ not supported
+   |
+   = note: see issue #20041 <https://github.com/rust-lang/rust/issues/20041> for more information
+help: if `Output` is an associated type you're trying to set, use the associated type binding syntax
+   |
+LL | impl<B: Add> Add for E<B> where B: Add<Output = B> {
+   |                                 ~~~~~~~~~~~~~~~~~~
+
 error[E0308]: mismatched types
   --> $DIR/missing-bounds.rs:11:11
    |
@@ -43,7 +55,23 @@ help: consider restricting type parameter `B`
 LL | impl<B: std::ops::Add<Output = B>> Add for D<B> {
    |       +++++++++++++++++++++++++++
 
-error: aborting due to 3 previous errors
+error[E0308]: mismatched types
+  --> $DIR/missing-bounds.rs:42:14
+   |
+LL | impl<B: Add> Add for E<B> where <B as Add>::Output = B {
+   |      - this type parameter
+...
+LL |         Self(self.0 + rhs.0)
+   |              ^^^^^^^^^^^^^^ expected type parameter `B`, found associated type
+   |
+   = note: expected type parameter `B`
+             found associated type `<B as Add>::Output`
+help: consider further restricting type parameter `B`
+   |
+LL | impl<B: Add> Add for E<B> where <B as Add>::Output = B, B: Add<Output = B> {
+   |                                                       ++++++++++++++++++++
+
+error: aborting due to 5 previous errors
 
 Some errors have detailed explanations: E0308, E0369.
 For more information about an error, try `rustc --explain E0308`.
diff --git a/src/test/ui/higher-rank-trait-bounds/issue-88586-hr-self-outlives-in-trait-def.rs b/src/test/ui/higher-rank-trait-bounds/issue-88586-hr-self-outlives-in-trait-def.rs
new file mode 100644 (file)
index 0000000..b50f56b
--- /dev/null
@@ -0,0 +1,11 @@
+// Regression test for #88586: a higher-ranked outlives bound on Self in a trait
+// definition caused an ICE when debug_assertions were enabled.
+//
+// FIXME: The error output in the absence of the ICE is unhelpful; this should be improved.
+
+trait A where for<'a> Self: 'a
+//~^ ERROR the parameter type `Self` may not live long enough
+{
+}
+
+fn main() {}
diff --git a/src/test/ui/higher-rank-trait-bounds/issue-88586-hr-self-outlives-in-trait-def.stderr b/src/test/ui/higher-rank-trait-bounds/issue-88586-hr-self-outlives-in-trait-def.stderr
new file mode 100644 (file)
index 0000000..18618ff
--- /dev/null
@@ -0,0 +1,19 @@
+error[E0311]: the parameter type `Self` may not live long enough
+  --> $DIR/issue-88586-hr-self-outlives-in-trait-def.rs:6:1
+   |
+LL | / trait A where for<'a> Self: 'a
+LL | |
+LL | | {
+LL | | }
+   | |_^
+   |
+   = help: consider adding an explicit lifetime bound `Self: 'a`...
+   = note: ...so that the type `Self` will meet its required lifetime bounds...
+note: ...that is required by this bound
+  --> $DIR/issue-88586-hr-self-outlives-in-trait-def.rs:6:29
+   |
+LL | trait A where for<'a> Self: 'a
+   |                             ^^
+
+error: aborting due to previous error
+
index 119cec1fa95bfd98b7d6475665193a9722a68f69..7da6b029c26f0f6ad6e712410fa3fe9e16a4fbf0 100644 (file)
@@ -1,5 +1,5 @@
 error: implementation of `Parser` is not general enough
-  --> $DIR/issue-71955.rs:52:5
+  --> $DIR/issue-71955.rs:57:5
    |
 LL |     foo(bar, "string", |s| s.len() == 5);
    |     ^^^ implementation of `Parser` is not general enough
@@ -8,7 +8,7 @@ LL |     foo(bar, "string", |s| s.len() == 5);
    = note: ...but it actually implements `Parser<'1>`, for some specific lifetime `'1`
 
 error: implementation of `Parser` is not general enough
-  --> $DIR/issue-71955.rs:52:5
+  --> $DIR/issue-71955.rs:57:5
    |
 LL |     foo(bar, "string", |s| s.len() == 5);
    |     ^^^ implementation of `Parser` is not general enough
@@ -17,7 +17,7 @@ LL |     foo(bar, "string", |s| s.len() == 5);
    = note: ...but it actually implements `Parser<'1>`, for some specific lifetime `'1`
 
 error: implementation of `Parser` is not general enough
-  --> $DIR/issue-71955.rs:52:5
+  --> $DIR/issue-71955.rs:57:5
    |
 LL |     foo(bar, "string", |s| s.len() == 5);
    |     ^^^ implementation of `Parser` is not general enough
@@ -26,7 +26,7 @@ LL |     foo(bar, "string", |s| s.len() == 5);
    = note: ...but it actually implements `Parser<'1>`, for some specific lifetime `'1`
 
 error: implementation of `Parser` is not general enough
-  --> $DIR/issue-71955.rs:52:5
+  --> $DIR/issue-71955.rs:57:5
    |
 LL |     foo(bar, "string", |s| s.len() == 5);
    |     ^^^ implementation of `Parser` is not general enough
@@ -35,7 +35,7 @@ LL |     foo(bar, "string", |s| s.len() == 5);
    = note: ...but it actually implements `Parser<'1>`, for some specific lifetime `'1`
 
 error: implementation of `Parser` is not general enough
-  --> $DIR/issue-71955.rs:52:5
+  --> $DIR/issue-71955.rs:57:5
    |
 LL |     foo(bar, "string", |s| s.len() == 5);
    |     ^^^ implementation of `Parser` is not general enough
@@ -44,7 +44,7 @@ LL |     foo(bar, "string", |s| s.len() == 5);
    = note: ...but it actually implements `Parser<'1>`, for some specific lifetime `'1`
 
 error: implementation of `Parser` is not general enough
-  --> $DIR/issue-71955.rs:58:5
+  --> $DIR/issue-71955.rs:63:5
    |
 LL |     foo(baz, "string", |s| s.0.len() == 5);
    |     ^^^ implementation of `Parser` is not general enough
@@ -53,7 +53,7 @@ LL |     foo(baz, "string", |s| s.0.len() == 5);
    = note: ...but it actually implements `Parser<'1>`, for some specific lifetime `'1`
 
 error: implementation of `Parser` is not general enough
-  --> $DIR/issue-71955.rs:58:5
+  --> $DIR/issue-71955.rs:63:5
    |
 LL |     foo(baz, "string", |s| s.0.len() == 5);
    |     ^^^ implementation of `Parser` is not general enough
@@ -62,7 +62,7 @@ LL |     foo(baz, "string", |s| s.0.len() == 5);
    = note: ...but it actually implements `Parser<'1>`, for some specific lifetime `'1`
 
 error: implementation of `Parser` is not general enough
-  --> $DIR/issue-71955.rs:58:5
+  --> $DIR/issue-71955.rs:63:5
    |
 LL |     foo(baz, "string", |s| s.0.len() == 5);
    |     ^^^ implementation of `Parser` is not general enough
@@ -71,7 +71,7 @@ LL |     foo(baz, "string", |s| s.0.len() == 5);
    = note: ...but it actually implements `Parser<'1>`, for some specific lifetime `'1`
 
 error: implementation of `Parser` is not general enough
-  --> $DIR/issue-71955.rs:58:5
+  --> $DIR/issue-71955.rs:63:5
    |
 LL |     foo(baz, "string", |s| s.0.len() == 5);
    |     ^^^ implementation of `Parser` is not general enough
@@ -80,7 +80,7 @@ LL |     foo(baz, "string", |s| s.0.len() == 5);
    = note: ...but it actually implements `Parser<'1>`, for some specific lifetime `'1`
 
 error: implementation of `Parser` is not general enough
-  --> $DIR/issue-71955.rs:58:5
+  --> $DIR/issue-71955.rs:63:5
    |
 LL |     foo(baz, "string", |s| s.0.len() == 5);
    |     ^^^ implementation of `Parser` is not general enough
index 69ab446bc7a34eacc72b37a770f7f1b31ad758ae..c2feaa91280557c001a6d88fe53b304e89e5905b 100644 (file)
@@ -1,5 +1,5 @@
 error: fatal error triggered by #[rustc_error]
-  --> $DIR/issue-71955.rs:42:1
+  --> $DIR/issue-71955.rs:47:1
    |
 LL | fn main() {
    | ^^^^^^^^^
index 95e3b3d4e1b886db61e612a4ef32ef7fd67dbadc..3d6778b6942c52c8213684d14fc30ae50ff1df9d 100644 (file)
@@ -3,6 +3,11 @@
 // [nll]compile-flags: -Zborrowck=mir
 // check-fail
 
+// Since we are testing nll (and migration) explicitly as a separate
+// revisions, don't worry about the --compare-mode=nll on this test.
+
+// ignore-compare-mode-nll
+
 #![feature(rustc_attrs)]
 
 trait Parser<'s> {
index a497c6257dab65226de295274c21664eabc767e6..a2ab1f1856d3ee3ea8f0f34c9e59b42dc0b23def 100644 (file)
@@ -1,5 +1,5 @@
-error[E0599]: the method `filterx` exists for struct `Map<Repeat, [closure@$DIR/issue-30786.rs:127:27: 127:36]>`, but its trait bounds were not satisfied
-  --> $DIR/issue-30786.rs:128:22
+error[E0599]: the method `filterx` exists for struct `Map<Repeat, [closure@$DIR/issue-30786.rs:126:27: 126:36]>`, but its trait bounds were not satisfied
+  --> $DIR/issue-30786.rs:127:22
    |
 LL | pub struct Map<S, F> {
    | --------------------
@@ -8,19 +8,19 @@ LL | pub struct Map<S, F> {
    | doesn't satisfy `_: StreamExt`
 ...
 LL |     let filter = map.filterx(|x: &_| true);
-   |                      ^^^^^^^ method cannot be called on `Map<Repeat, [closure@$DIR/issue-30786.rs:127:27: 127:36]>` due to unsatisfied trait bounds
+   |                      ^^^^^^^ method cannot be called on `Map<Repeat, [closure@$DIR/issue-30786.rs:126:27: 126:36]>` due to unsatisfied trait bounds
    |
 note: the following trait bounds were not satisfied because of the requirements of the implementation of `StreamExt` for `_`:
-      `&'a mut Map<Repeat, [closure@$DIR/issue-30786.rs:127:27: 127:36]>: Stream`
-      `&'a mut &Map<Repeat, [closure@$DIR/issue-30786.rs:127:27: 127:36]>: Stream`
-      `&'a mut &mut Map<Repeat, [closure@$DIR/issue-30786.rs:127:27: 127:36]>: Stream`
-  --> $DIR/issue-30786.rs:106:9
+      `&'a mut Map<Repeat, [closure@$DIR/issue-30786.rs:126:27: 126:36]>: Stream`
+      `&'a mut &Map<Repeat, [closure@$DIR/issue-30786.rs:126:27: 126:36]>: Stream`
+      `&'a mut &mut Map<Repeat, [closure@$DIR/issue-30786.rs:126:27: 126:36]>: Stream`
+  --> $DIR/issue-30786.rs:105:9
    |
 LL | impl<T> StreamExt for T where for<'a> &'a mut T: Stream {}
    |         ^^^^^^^^^     ^
 
-error[E0599]: the method `countx` exists for struct `Filter<Map<Repeat, for<'r> fn(&'r u64) -> &'r u64 {identity::<u64>}>, [closure@$DIR/issue-30786.rs:140:30: 140:42]>`, but its trait bounds were not satisfied
-  --> $DIR/issue-30786.rs:141:24
+error[E0599]: the method `countx` exists for struct `Filter<Map<Repeat, for<'r> fn(&'r u64) -> &'r u64 {identity::<u64>}>, [closure@$DIR/issue-30786.rs:139:30: 139:42]>`, but its trait bounds were not satisfied
+  --> $DIR/issue-30786.rs:140:24
    |
 LL | pub struct Filter<S, F> {
    | -----------------------
@@ -29,13 +29,13 @@ LL | pub struct Filter<S, F> {
    | doesn't satisfy `_: StreamExt`
 ...
 LL |     let count = filter.countx();
-   |                        ^^^^^^ method cannot be called on `Filter<Map<Repeat, for<'r> fn(&'r u64) -> &'r u64 {identity::<u64>}>, [closure@$DIR/issue-30786.rs:140:30: 140:42]>` due to unsatisfied trait bounds
+   |                        ^^^^^^ method cannot be called on `Filter<Map<Repeat, for<'r> fn(&'r u64) -> &'r u64 {identity::<u64>}>, [closure@$DIR/issue-30786.rs:139:30: 139:42]>` due to unsatisfied trait bounds
    |
 note: the following trait bounds were not satisfied because of the requirements of the implementation of `StreamExt` for `_`:
-      `&'a mut Filter<Map<Repeat, for<'r> fn(&'r u64) -> &'r u64 {identity::<u64>}>, [closure@$DIR/issue-30786.rs:140:30: 140:42]>: Stream`
-      `&'a mut &Filter<Map<Repeat, for<'r> fn(&'r u64) -> &'r u64 {identity::<u64>}>, [closure@$DIR/issue-30786.rs:140:30: 140:42]>: Stream`
-      `&'a mut &mut Filter<Map<Repeat, for<'r> fn(&'r u64) -> &'r u64 {identity::<u64>}>, [closure@$DIR/issue-30786.rs:140:30: 140:42]>: Stream`
-  --> $DIR/issue-30786.rs:106:9
+      `&'a mut Filter<Map<Repeat, for<'r> fn(&'r u64) -> &'r u64 {identity::<u64>}>, [closure@$DIR/issue-30786.rs:139:30: 139:42]>: Stream`
+      `&'a mut &Filter<Map<Repeat, for<'r> fn(&'r u64) -> &'r u64 {identity::<u64>}>, [closure@$DIR/issue-30786.rs:139:30: 139:42]>: Stream`
+      `&'a mut &mut Filter<Map<Repeat, for<'r> fn(&'r u64) -> &'r u64 {identity::<u64>}>, [closure@$DIR/issue-30786.rs:139:30: 139:42]>: Stream`
+  --> $DIR/issue-30786.rs:105:9
    |
 LL | impl<T> StreamExt for T where for<'a> &'a mut T: Stream {}
    |         ^^^^^^^^^     ^
index a497c6257dab65226de295274c21664eabc767e6..a2ab1f1856d3ee3ea8f0f34c9e59b42dc0b23def 100644 (file)
@@ -1,5 +1,5 @@
-error[E0599]: the method `filterx` exists for struct `Map<Repeat, [closure@$DIR/issue-30786.rs:127:27: 127:36]>`, but its trait bounds were not satisfied
-  --> $DIR/issue-30786.rs:128:22
+error[E0599]: the method `filterx` exists for struct `Map<Repeat, [closure@$DIR/issue-30786.rs:126:27: 126:36]>`, but its trait bounds were not satisfied
+  --> $DIR/issue-30786.rs:127:22
    |
 LL | pub struct Map<S, F> {
    | --------------------
@@ -8,19 +8,19 @@ LL | pub struct Map<S, F> {
    | doesn't satisfy `_: StreamExt`
 ...
 LL |     let filter = map.filterx(|x: &_| true);
-   |                      ^^^^^^^ method cannot be called on `Map<Repeat, [closure@$DIR/issue-30786.rs:127:27: 127:36]>` due to unsatisfied trait bounds
+   |                      ^^^^^^^ method cannot be called on `Map<Repeat, [closure@$DIR/issue-30786.rs:126:27: 126:36]>` due to unsatisfied trait bounds
    |
 note: the following trait bounds were not satisfied because of the requirements of the implementation of `StreamExt` for `_`:
-      `&'a mut Map<Repeat, [closure@$DIR/issue-30786.rs:127:27: 127:36]>: Stream`
-      `&'a mut &Map<Repeat, [closure@$DIR/issue-30786.rs:127:27: 127:36]>: Stream`
-      `&'a mut &mut Map<Repeat, [closure@$DIR/issue-30786.rs:127:27: 127:36]>: Stream`
-  --> $DIR/issue-30786.rs:106:9
+      `&'a mut Map<Repeat, [closure@$DIR/issue-30786.rs:126:27: 126:36]>: Stream`
+      `&'a mut &Map<Repeat, [closure@$DIR/issue-30786.rs:126:27: 126:36]>: Stream`
+      `&'a mut &mut Map<Repeat, [closure@$DIR/issue-30786.rs:126:27: 126:36]>: Stream`
+  --> $DIR/issue-30786.rs:105:9
    |
 LL | impl<T> StreamExt for T where for<'a> &'a mut T: Stream {}
    |         ^^^^^^^^^     ^
 
-error[E0599]: the method `countx` exists for struct `Filter<Map<Repeat, for<'r> fn(&'r u64) -> &'r u64 {identity::<u64>}>, [closure@$DIR/issue-30786.rs:140:30: 140:42]>`, but its trait bounds were not satisfied
-  --> $DIR/issue-30786.rs:141:24
+error[E0599]: the method `countx` exists for struct `Filter<Map<Repeat, for<'r> fn(&'r u64) -> &'r u64 {identity::<u64>}>, [closure@$DIR/issue-30786.rs:139:30: 139:42]>`, but its trait bounds were not satisfied
+  --> $DIR/issue-30786.rs:140:24
    |
 LL | pub struct Filter<S, F> {
    | -----------------------
@@ -29,13 +29,13 @@ LL | pub struct Filter<S, F> {
    | doesn't satisfy `_: StreamExt`
 ...
 LL |     let count = filter.countx();
-   |                        ^^^^^^ method cannot be called on `Filter<Map<Repeat, for<'r> fn(&'r u64) -> &'r u64 {identity::<u64>}>, [closure@$DIR/issue-30786.rs:140:30: 140:42]>` due to unsatisfied trait bounds
+   |                        ^^^^^^ method cannot be called on `Filter<Map<Repeat, for<'r> fn(&'r u64) -> &'r u64 {identity::<u64>}>, [closure@$DIR/issue-30786.rs:139:30: 139:42]>` due to unsatisfied trait bounds
    |
 note: the following trait bounds were not satisfied because of the requirements of the implementation of `StreamExt` for `_`:
-      `&'a mut Filter<Map<Repeat, for<'r> fn(&'r u64) -> &'r u64 {identity::<u64>}>, [closure@$DIR/issue-30786.rs:140:30: 140:42]>: Stream`
-      `&'a mut &Filter<Map<Repeat, for<'r> fn(&'r u64) -> &'r u64 {identity::<u64>}>, [closure@$DIR/issue-30786.rs:140:30: 140:42]>: Stream`
-      `&'a mut &mut Filter<Map<Repeat, for<'r> fn(&'r u64) -> &'r u64 {identity::<u64>}>, [closure@$DIR/issue-30786.rs:140:30: 140:42]>: Stream`
-  --> $DIR/issue-30786.rs:106:9
+      `&'a mut Filter<Map<Repeat, for<'r> fn(&'r u64) -> &'r u64 {identity::<u64>}>, [closure@$DIR/issue-30786.rs:139:30: 139:42]>: Stream`
+      `&'a mut &Filter<Map<Repeat, for<'r> fn(&'r u64) -> &'r u64 {identity::<u64>}>, [closure@$DIR/issue-30786.rs:139:30: 139:42]>: Stream`
+      `&'a mut &mut Filter<Map<Repeat, for<'r> fn(&'r u64) -> &'r u64 {identity::<u64>}>, [closure@$DIR/issue-30786.rs:139:30: 139:42]>: Stream`
+  --> $DIR/issue-30786.rs:105:9
    |
 LL | impl<T> StreamExt for T where for<'a> &'a mut T: Stream {}
    |         ^^^^^^^^^     ^
index 278c5441ecfb70caf9d96cf5b20901808ef0f4fd..540c26c358b1dfefc9f1d697fc31f361d6e41bb8 100644 (file)
@@ -7,6 +7,7 @@
 // through again.
 
 // revisions: migrate nll
+//[nll]compile-flags: -Z borrowck=mir
 
 // Since we are testing nll (and migration) explicitly as a separate
 // revisions, don't worry about the --compare-mode=nll on this test.
@@ -14,8 +15,6 @@
 // ignore-compare-mode-nll
 // ignore-compare-mode-polonius
 
-//[nll]compile-flags: -Z borrowck=mir
-
 pub trait Stream {
     type Item;
     fn next(self) -> Option<Self::Item>;
index 8cc4fef890abf8a40c3460ffa309e191203b15f3..e3386d29def02eabcb4840186426032754fc1bc0 100644 (file)
@@ -2,9 +2,9 @@
 #![feature(type_alias_impl_trait)]
 
 type FunType = impl Fn<()>;
-//~^ could not find defining uses
+//~^ ERROR could not find defining uses
 static STATIC_FN: FunType = some_fn;
-//~^ mismatched types
+//~^ ERROR mismatched types
 
 fn some_fn() {}
 
index d7e8c08bb01b245b95b651bc69f22e087c94e87a..5a276f27886d29830b85009b2ad518f162f24f5a 100644 (file)
@@ -1,27 +1,26 @@
 error[E0015]: calls in statics are limited to constant functions, tuple structs and tuple variants
-  --> $DIR/issue-16538.rs:14:27
+  --> $DIR/issue-16538.rs:15:23
    |
-LL | static foo: *const Y::X = Y::foo(Y::x as *const Y::X);
-   |                           ^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL | static foo: &Y::X = &*Y::foo(Y::x as *const Y::X);
+   |                       ^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
-error[E0277]: `*const usize` cannot be shared between threads safely
-  --> $DIR/issue-16538.rs:14:1
+error[E0133]: use of extern static is unsafe and requires unsafe function or block
+  --> $DIR/issue-16538.rs:15:30
    |
-LL | static foo: *const Y::X = Y::foo(Y::x as *const Y::X);
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `*const usize` cannot be shared between threads safely
+LL | static foo: &Y::X = &*Y::foo(Y::x as *const Y::X);
+   |                              ^^^^ use of extern static
    |
-   = help: the trait `Sync` is not implemented for `*const usize`
-   = note: shared static variables must have a type that implements `Sync`
+   = note: extern statics are not controlled by the Rust type system: invalid data, aliasing violations or data races will cause undefined behavior
 
-error[E0133]: use of extern static is unsafe and requires unsafe function or block
-  --> $DIR/issue-16538.rs:14:34
+error[E0133]: dereference of raw pointer is unsafe and requires unsafe function or block
+  --> $DIR/issue-16538.rs:15:21
    |
-LL | static foo: *const Y::X = Y::foo(Y::x as *const Y::X);
-   |                                  ^^^^ use of extern static
+LL | static foo: &Y::X = &*Y::foo(Y::x as *const Y::X);
+   |                     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ dereference of raw pointer
    |
-   = note: extern statics are not controlled by the Rust type system: invalid data, aliasing violations or data races will cause undefined behavior
+   = note: raw pointers may be null, dangling or unaligned; they can violate aliasing rules and cause data races: all of these are undefined behavior
 
 error: aborting due to 3 previous errors
 
-Some errors have detailed explanations: E0015, E0133, E0277.
+Some errors have detailed explanations: E0015, E0133.
 For more information about an error, try `rustc --explain E0015`.
index 1e8ecf015c85a8aff0950b3c99fa60b29db9f3d3..b6891deb937da0af8a10319f2255d0b81c644dcd 100644 (file)
@@ -1,6 +1,7 @@
 // revisions: mir thir
 // [thir]compile-flags: -Z thir-unsafeck
 
+#![feature(const_raw_ptr_deref)]
 mod Y {
     pub type X = usize;
     extern "C" {
@@ -11,8 +12,8 @@ pub fn foo(value: *const X) -> *const X {
     }
 }
 
-static foo: *const Y::X = Y::foo(Y::x as *const Y::X);
-//~^ ERROR `*const usize` cannot be shared between threads safely [E0277]
+static foo: &Y::X = &*Y::foo(Y::x as *const Y::X);
+//~^ ERROR dereference of raw pointer
 //~| ERROR E0015
 //~| ERROR use of extern static is unsafe and requires
 
index 435334c322808bbf92107c9a36a0cc378cf2a5c8..8365a1dbf6e5ebdb92e1a4fa9ae7c860629b8fb8 100644 (file)
@@ -1,27 +1,26 @@
+error[E0133]: dereference of raw pointer is unsafe and requires unsafe function or block
+  --> $DIR/issue-16538.rs:15:22
+   |
+LL | static foo: &Y::X = &*Y::foo(Y::x as *const Y::X);
+   |                      ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ dereference of raw pointer
+   |
+   = note: raw pointers may be null, dangling or unaligned; they can violate aliasing rules and cause data races: all of these are undefined behavior
+
 error[E0133]: use of extern static is unsafe and requires unsafe function or block
-  --> $DIR/issue-16538.rs:14:34
+  --> $DIR/issue-16538.rs:15:30
    |
-LL | static foo: *const Y::X = Y::foo(Y::x as *const Y::X);
-   |                                  ^^^^ use of extern static
+LL | static foo: &Y::X = &*Y::foo(Y::x as *const Y::X);
+   |                              ^^^^ use of extern static
    |
    = note: extern statics are not controlled by the Rust type system: invalid data, aliasing violations or data races will cause undefined behavior
 
 error[E0015]: calls in statics are limited to constant functions, tuple structs and tuple variants
-  --> $DIR/issue-16538.rs:14:27
-   |
-LL | static foo: *const Y::X = Y::foo(Y::x as *const Y::X);
-   |                           ^^^^^^^^^^^^^^^^^^^^^^^^^^^
-
-error[E0277]: `*const usize` cannot be shared between threads safely
-  --> $DIR/issue-16538.rs:14:1
-   |
-LL | static foo: *const Y::X = Y::foo(Y::x as *const Y::X);
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `*const usize` cannot be shared between threads safely
+  --> $DIR/issue-16538.rs:15:23
    |
-   = help: the trait `Sync` is not implemented for `*const usize`
-   = note: shared static variables must have a type that implements `Sync`
+LL | static foo: &Y::X = &*Y::foo(Y::x as *const Y::X);
+   |                       ^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: aborting due to 3 previous errors
 
-Some errors have detailed explanations: E0015, E0133, E0277.
+Some errors have detailed explanations: E0015, E0133.
 For more information about an error, try `rustc --explain E0015`.
index 4cd85124c35074aa64fa27c052fe7536f3264d59..bc6e45e59258f370cda1ad3e9541d376c2ee2cd0 100644 (file)
@@ -1,8 +1,8 @@
 error[E0277]: `Foo` cannot be shared between threads safely
-  --> $DIR/issue-17718-static-sync.rs:9:1
+  --> $DIR/issue-17718-static-sync.rs:9:13
    |
 LL | static BAR: Foo = Foo;
-   | ^^^^^^^^^^^^^^^^^^^^^^ `Foo` cannot be shared between threads safely
+   |             ^^^ `Foo` cannot be shared between threads safely
    |
    = help: the trait `Sync` is not implemented for `Foo`
    = note: shared static variables must have a type that implements `Sync`
index ffd6dfabc2890a1cb7f905485e1812780b86b903..9ab952ade9cf4636ccddc39c1d88908ee51addf5 100644 (file)
@@ -1,6 +1,7 @@
 fn main() {
     static foo: dyn Fn() -> u32 = || -> u32 {
         //~^ ERROR the size for values of type
+        //~| ERROR cannot be shared between threads safely
         0
     };
 }
index 1674fa8af2845fc482750bde1dce2b2af537cc22..4afb87c48254901a651d09cb9f8d1fa82f612b6a 100644 (file)
@@ -6,6 +6,15 @@ LL |     static foo: dyn Fn() -> u32 = || -> u32 {
    |
    = help: the trait `Sized` is not implemented for `(dyn Fn() -> u32 + 'static)`
 
-error: aborting due to previous error
+error[E0277]: `(dyn Fn() -> u32 + 'static)` cannot be shared between threads safely
+  --> $DIR/issue-24446.rs:2:17
+   |
+LL |     static foo: dyn Fn() -> u32 = || -> u32 {
+   |                 ^^^^^^^^^^^^^^^ `(dyn Fn() -> u32 + 'static)` cannot be shared between threads safely
+   |
+   = help: the trait `Sync` is not implemented for `(dyn Fn() -> u32 + 'static)`
+   = note: shared static variables must have a type that implements `Sync`
+
+error: aborting due to 2 previous errors
 
 For more information about this error, try `rustc --explain E0277`.
index 61cf3f25d0d07390e1de49fefba1ef988ab34187..4a1debf37a079547bdbdaff4a3a64c71de359a22 100644 (file)
@@ -8,6 +8,8 @@ LL |     let mut s_copy = s;
 ...
 LL |     println!("{}", s);
    |                    ^ value borrowed here after move
+   |
+   = note: this error originates in the macro `$crate::format_args_nl` (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error: aborting due to previous error
 
index eff1de3e01752c472e9b1e718574575058256c88..32e8588b3c0749dc3a9aeecd6ba43e2c54b11596 100644 (file)
@@ -12,6 +12,8 @@ LL |             println!("{:?}", heap);
 ...
 LL |     };
    |      - ... and the mutable borrow might be used here, when that temporary is dropped and runs the destructor for type `(Option<PeekMut<'_, i32>>, ())`
+   |
+   = note: this error originates in the macro `$crate::format_args_nl` (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error: aborting due to previous error
 
index 35b343edfbdbe870c23a63f1828936983106b212..4072a57cb10526aaccd0f12937c5328202db6608 100644 (file)
@@ -1,10 +1,10 @@
 fn f() { }
-struct S(Box<dyn FnMut()>);
+struct S(Box<dyn FnMut() + Sync>);
 pub static C: S = S(f); //~ ERROR mismatched types
 
 
 fn g() { }
-type T = Box<dyn FnMut()>;
+type T = Box<dyn FnMut() + Sync>;
 pub static D: T = g; //~ ERROR mismatched types
 
 fn main() {}
index 7a1f42adf65d48a07cd9ffaad1ea517301762264..29c95e4fb62b89f4206e0ccf144549423b43ec29 100644 (file)
@@ -4,7 +4,7 @@ error[E0308]: mismatched types
 LL | pub static C: S = S(f);
    |                     ^ expected struct `Box`, found fn item
    |
-   = note: expected struct `Box<(dyn FnMut() + 'static)>`
+   = note: expected struct `Box<(dyn FnMut() + Sync + 'static)>`
              found fn item `fn() {f}`
 
 error[E0308]: mismatched types
@@ -13,7 +13,7 @@ error[E0308]: mismatched types
 LL | pub static D: T = g;
    |                   ^ expected struct `Box`, found fn item
    |
-   = note: expected struct `Box<(dyn FnMut() + 'static)>`
+   = note: expected struct `Box<(dyn FnMut() + Sync + 'static)>`
              found fn item `fn() {g}`
 
 error: aborting due to 2 previous errors
index 29a1644673d4ec4ae652328f8be7b121251453bd..83c52d286a199c9ea1c2d9f71c22aafef4af4047 100644 (file)
@@ -4,7 +4,6 @@
 
 // Regression test for issue 7364
 static boxed: Box<RefCell<isize>> = box RefCell::new(0);
-//~^ ERROR allocations are not allowed in statics
-//~| ERROR `RefCell<isize>` cannot be shared between threads safely [E0277]
+//~^ ERROR `RefCell<isize>` cannot be shared between threads safely [E0277]
 
 fn main() { }
index 8ceb3be7ec913110853456edc191c7e75fcf42ad..f2e80f451695ac3a9c4fe235572cff1f146e1613 100644 (file)
@@ -1,21 +1,14 @@
-error[E0010]: allocations are not allowed in statics
-  --> $DIR/issue-7364.rs:6:37
-   |
-LL | static boxed: Box<RefCell<isize>> = box RefCell::new(0);
-   |                                     ^^^^^^^^^^^^^^^^^^^ allocation not allowed in statics
-
 error[E0277]: `RefCell<isize>` cannot be shared between threads safely
-  --> $DIR/issue-7364.rs:6:1
+  --> $DIR/issue-7364.rs:6:15
    |
 LL | static boxed: Box<RefCell<isize>> = box RefCell::new(0);
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `RefCell<isize>` cannot be shared between threads safely
+   |               ^^^^^^^^^^^^^^^^^^^ `RefCell<isize>` cannot be shared between threads safely
    |
    = help: the trait `Sync` is not implemented for `RefCell<isize>`
    = note: required because of the requirements on the impl of `Sync` for `Unique<RefCell<isize>>`
    = note: required because it appears within the type `Box<RefCell<isize>>`
    = note: shared static variables must have a type that implements `Sync`
 
-error: aborting due to 2 previous errors
+error: aborting due to previous error
 
-Some errors have detailed explanations: E0010, E0277.
-For more information about an error, try `rustc --explain E0010`.
+For more information about this error, try `rustc --explain E0277`.
index 6e597b7669abc632ebdcdfc973450c5666d9c163..966d76d148af3f69d901198d4955d3b4654d769a 100644 (file)
@@ -10,4 +10,4 @@ struct Multiply<N, M> {
 }
 impl<N, M> TypeVal<usize> for Multiply<N, M> where N: TypeVal<VAL> {}
 //~^ ERROR cannot find type `VAL` in this scope
-//~| ERROR type annotations needed
+//~| ERROR not all trait items implemented, missing: `VAL`
index f98556bc72f478ebb6d7a7053e00867048d6fce3..97bd5ab36b65d176d2e4ab0fb8580f0d2342dde0 100644 (file)
@@ -17,15 +17,16 @@ LL | impl<N, M> TypeVal<usize> for Multiply<N, M> where N: TypeVal<VAL> {}
    |          |
    |          help: you might be missing a type parameter: `, VAL`
 
-error[E0283]: type annotations needed
-  --> $DIR/issue-77919.rs:11:12
+error[E0046]: not all trait items implemented, missing: `VAL`
+  --> $DIR/issue-77919.rs:11:1
    |
+LL |     const VAL: T;
+   |     ------------- `VAL` from trait
+...
 LL | impl<N, M> TypeVal<usize> for Multiply<N, M> where N: TypeVal<VAL> {}
-   |            ^^^^^^^^^^^^^^ cannot infer type for struct `Multiply<N, M>`
-   |
-   = note: cannot satisfy `Multiply<N, M>: TypeVal<usize>`
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ missing `VAL` in implementation
 
 error: aborting due to 3 previous errors
 
-Some errors have detailed explanations: E0283, E0412.
-For more information about an error, try `rustc --explain E0283`.
+Some errors have detailed explanations: E0046, E0412.
+For more information about an error, try `rustc --explain E0046`.
index a7e382479021aeb8767c6b46391f0ecb8476eb30..90411353f08250496680c6466b0f8b594167663b 100644 (file)
@@ -18,6 +18,7 @@ LL |     println!("Size: {}", std::mem::size_of::<[u8; u64::MAX as usize]>());
    = note: `#[deny(const_err)]` on by default
    = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
    = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
+   = note: this error originates in the macro `$crate::format_args_nl` (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error: aborting due to 2 previous errors
 
index fd9baf8c6b9a28168e7433af05f1d3cd0ed15bb6..258f9e4831f9a3cddefc110f71cb43c55de0d763 100644 (file)
@@ -26,4 +26,7 @@ fn doc_comment_on_expr(num: u8) -> bool {
     num == 3
 }
 
+fn doc_comment_on_generic<#[doc = "x"] T>(val: T) {}
+//~^ ERROR: unused doc comment
+
 fn main() {}
index 403367017c6e6e35e4c9f2a8bfa6034b72d769ba..3ce1df71a2ed58b9c41004cc102416075dde40fc 100644 (file)
@@ -41,6 +41,14 @@ LL |     num == 3
    |
    = help: use `//` for a plain comment
 
+error: unused doc comment
+  --> $DIR/unused-doc-comments-edge-cases.rs:29:27
+   |
+LL | fn doc_comment_on_generic<#[doc = "x"] T>(val: T) {}
+   |                           ^^^^^^^^^^^^ - rustdoc does not generate documentation for generic parameters
+   |
+   = help: use `//` for a plain comment
+
 error[E0308]: mismatched types
   --> $DIR/unused-doc-comments-edge-cases.rs:14:9
    |
@@ -55,7 +63,7 @@ help: you might have meant to return this value
 LL |         return true;
    |         ++++++     +
 
-error: aborting due to 5 previous errors
+error: aborting due to 6 previous errors
 
 Some errors have detailed explanations: E0308, E0658.
 For more information about an error, try `rustc --explain E0308`.
index 6a8f239bd09a8a073862e455e3e15d7631167d78..ff6c02f2110f647daf0c1ecf6b6f446cf16bf974 100644 (file)
@@ -28,6 +28,8 @@ LL |         println!("{}", y);
    |                        ^ value borrowed here after move
 LL |         while true { while true { while true { x = y; x.clone(); } } }
    |                                                    - value moved here, in previous iteration of loop
+   |
+   = note: this error originates in the macro `$crate::format_args_nl` (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error: aborting due to previous error; 3 warnings emitted
 
index 292ce013dcc7622aaaa2cce9a285009cbe79b702..df54af9f0f2ce2e038bd2c420ea62fefce0920de 100644 (file)
@@ -8,6 +8,8 @@ LL |     let y = x;
 LL | 
 LL |     println!("{}", *x);
    |                    ^^ value borrowed here after move
+   |
+   = note: this error originates in the macro `$crate::format_args_nl` (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error: aborting due to previous error
 
index 50ae98ca9bedcca7190a8d4a7d5c2d88b3b0cbb4..becede1ceb6b3edd0b0f3eadad2c6ca2f7a7fe5e 100644 (file)
@@ -7,6 +7,8 @@ LL |     send(ch, message);
    |              ------- value moved here
 LL |     println!("{}", message);
    |                    ^^^^^^^ value borrowed here after move
+   |
+   = note: this error originates in the macro `$crate::format_args_nl` (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error: aborting due to previous error
 
index d55f9ff31e3ee7a43c343ab0da0a0ff49690ba64..20d5c66a3f20581c789238f26c733a54c859c8d5 100644 (file)
@@ -3,6 +3,8 @@ error[E0381]: borrow of possibly-uninitialized variable: `x`
    |
 LL |     println!("{:?}", x);
    |                      ^ use of possibly-uninitialized `x`
+   |
+   = note: this error originates in the macro `$crate::format_args_nl` (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error: aborting due to previous error
 
index acb0932f6d6b9a98f242db9be125f5192fac26fe..ac921c18e07d577ace08f15b684ff4269e709750 100644 (file)
@@ -10,6 +10,8 @@ LL |         println!("{}", x);
 LL |     });
 LL |     println!("{}", x);
    |                    ^ value borrowed here after move
+   |
+   = note: this error originates in the macro `$crate::format_args_nl` (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/optimization-remark.rs b/src/test/ui/optimization-remark.rs
new file mode 100644 (file)
index 0000000..36549cb
--- /dev/null
@@ -0,0 +1,28 @@
+// build-pass
+// ignore-pass
+// no-system-llvm
+// revisions: all inline merge1 merge2
+// compile-flags: --crate-type=lib -Cdebuginfo=1 -Copt-level=2
+//
+// Check that remarks can be enabled individually or with "all":
+//
+// [all]    compile-flags: -Cremark=all
+// [inline] compile-flags: -Cremark=inline
+//
+// Check that values of -Cremark flag are accumulated:
+//
+// [merge1] compile-flags: -Cremark=all    -Cremark=giraffe
+// [merge2] compile-flags: -Cremark=inline -Cremark=giraffe
+//
+// error-pattern: inline: f not inlined into g
+// dont-check-compiler-stderr
+
+#[no_mangle]
+#[inline(never)]
+pub fn f() {
+}
+
+#[no_mangle]
+pub fn g() {
+    f();
+}
index 4ee0b2054ff772dcc3c92ca5bbc99a06dc5ffb04..0b7b67496d6f32df39107feb43e1c957a029ae21 100644 (file)
@@ -1,11 +1,15 @@
 // Tests that a suggestion is issued if the user wrote a colon instead of
 // a path separator in a match arm.
 
-enum Foo {
-    Bar,
-    Baz,
+mod qux {
+    pub enum Foo {
+        Bar,
+        Baz,
+    }
 }
 
+use qux::Foo;
+
 fn f() -> Foo { Foo::Bar }
 
 fn g1() {
@@ -16,24 +20,24 @@ fn g1() {
         _ => {}
     }
     match f() {
-        Foo::Bar:Baz => {}
+        qux::Foo:Bar => {}
         //~^ ERROR: expected one of
         //~| HELP: maybe write a path separator here
         _ => {}
     }
     match f() {
-        Foo:Bar::Baz => {}
+        qux:Foo::Baz => {}
         //~^ ERROR: expected one of
         //~| HELP: maybe write a path separator here
         _ => {}
     }
     match f() {
-        Foo: Bar::Baz if true => {}
+        qux: Foo::Baz if true => {}
         //~^ ERROR: expected one of
         //~| HELP: maybe write a path separator here
         _ => {}
     }
-    if let Bar:Baz = f() {
+    if let Foo:Bar = f() {
     //~^ ERROR: expected one of
     //~| HELP: maybe write a path separator here
     }
@@ -41,16 +45,18 @@ fn g1() {
 
 fn g1_neg() {
     match f() {
-        ref Foo: Bar::Baz => {}
+        ref qux: Foo::Baz => {}
         //~^ ERROR: expected one of
+        //~| HELP: maybe write a path separator here
         _ => {}
     }
 }
 
 fn g2_neg() {
     match f() {
-        mut Foo: Bar::Baz => {}
+        mut qux: Foo::Baz => {}
         //~^ ERROR: expected one of
+        //~| HELP: maybe write a path separator here
         _ => {}
     }
 }
@@ -62,5 +68,12 @@ fn main() {
         Foo:Bar::Baz => {}
         //~^ ERROR: expected one of
         //~| HELP: maybe write a path separator here
+        //~| ERROR: failed to resolve: `Bar` is a variant, not a module
+    }
+    match myfoo {
+        Foo::Bar => {}
+        Foo:Bar => {}
+        //~^ ERROR: expected one of
+        //~| HELP: maybe write a path separator here
     }
 }
index 8f93661a626467f7e85ef154140fbbbf292b15be..2050a16beb34983c63e96f847a82c1d23f3f16d5 100644 (file)
@@ -1,5 +1,5 @@
 error: expected one of `@` or `|`, found `:`
-  --> $DIR/issue-87086-colon-path-sep.rs:13:12
+  --> $DIR/issue-87086-colon-path-sep.rs:17:12
    |
 LL |         Foo:Bar => {}
    |            ^
@@ -8,55 +8,61 @@ LL |         Foo:Bar => {}
    |            help: maybe write a path separator here: `::`
 
 error: expected one of `!`, `(`, `...`, `..=`, `..`, `::`, `{`, or `|`, found `:`
-  --> $DIR/issue-87086-colon-path-sep.rs:19:17
+  --> $DIR/issue-87086-colon-path-sep.rs:23:17
    |
-LL |         Foo::Bar:Baz => {}
+LL |         qux::Foo:Bar => {}
    |                 ^
    |                 |
    |                 expected one of 8 possible tokens
    |                 help: maybe write a path separator here: `::`
 
 error: expected one of `@` or `|`, found `:`
-  --> $DIR/issue-87086-colon-path-sep.rs:25:12
+  --> $DIR/issue-87086-colon-path-sep.rs:29:12
    |
-LL |         Foo:Bar::Baz => {}
+LL |         qux:Foo::Baz => {}
    |            ^
    |            |
    |            expected one of `@` or `|`
    |            help: maybe write a path separator here: `::`
 
 error: expected one of `@` or `|`, found `:`
-  --> $DIR/issue-87086-colon-path-sep.rs:31:12
+  --> $DIR/issue-87086-colon-path-sep.rs:35:12
    |
-LL |         Foo: Bar::Baz if true => {}
+LL |         qux: Foo::Baz if true => {}
    |            ^
    |            |
    |            expected one of `@` or `|`
    |            help: maybe write a path separator here: `::`
 
 error: expected one of `@` or `|`, found `:`
-  --> $DIR/issue-87086-colon-path-sep.rs:36:15
+  --> $DIR/issue-87086-colon-path-sep.rs:40:15
    |
-LL |     if let Bar:Baz = f() {
+LL |     if let Foo:Bar = f() {
    |               ^
    |               |
    |               expected one of `@` or `|`
    |               help: maybe write a path separator here: `::`
 
-error: expected one of `=>`, `@`, `if`, or `|`, found `:`
-  --> $DIR/issue-87086-colon-path-sep.rs:44:16
+error: expected one of `@` or `|`, found `:`
+  --> $DIR/issue-87086-colon-path-sep.rs:48:16
    |
-LL |         ref Foo: Bar::Baz => {}
-   |                ^ expected one of `=>`, `@`, `if`, or `|`
+LL |         ref qux: Foo::Baz => {}
+   |                ^
+   |                |
+   |                expected one of `@` or `|`
+   |                help: maybe write a path separator here: `::`
 
-error: expected one of `=>`, `@`, `if`, or `|`, found `:`
-  --> $DIR/issue-87086-colon-path-sep.rs:52:16
+error: expected one of `@` or `|`, found `:`
+  --> $DIR/issue-87086-colon-path-sep.rs:57:16
    |
-LL |         mut Foo: Bar::Baz => {}
-   |                ^ expected one of `=>`, `@`, `if`, or `|`
+LL |         mut qux: Foo::Baz => {}
+   |                ^
+   |                |
+   |                expected one of `@` or `|`
+   |                help: maybe write a path separator here: `::`
 
 error: expected one of `@` or `|`, found `:`
-  --> $DIR/issue-87086-colon-path-sep.rs:62:12
+  --> $DIR/issue-87086-colon-path-sep.rs:68:12
    |
 LL |         Foo:Bar::Baz => {}
    |            ^
@@ -64,5 +70,21 @@ LL |         Foo:Bar::Baz => {}
    |            expected one of `@` or `|`
    |            help: maybe write a path separator here: `::`
 
-error: aborting due to 8 previous errors
+error: expected one of `@` or `|`, found `:`
+  --> $DIR/issue-87086-colon-path-sep.rs:75:12
+   |
+LL |         Foo:Bar => {}
+   |            ^
+   |            |
+   |            expected one of `@` or `|`
+   |            help: maybe write a path separator here: `::`
+
+error[E0433]: failed to resolve: `Bar` is a variant, not a module
+  --> $DIR/issue-87086-colon-path-sep.rs:68:13
+   |
+LL |         Foo:Bar::Baz => {}
+   |             ^^^ `Bar` is a variant, not a module
+
+error: aborting due to 10 previous errors
 
+For more information about this error, try `rustc --explain E0433`.
diff --git a/src/test/ui/regions/regions-assoc-type-in-supertrait-outlives-container.migrate.nll.stderr b/src/test/ui/regions/regions-assoc-type-in-supertrait-outlives-container.migrate.nll.stderr
deleted file mode 100644 (file)
index 9bb385b..0000000
+++ /dev/null
@@ -1,15 +0,0 @@
-error: lifetime may not live long enough
-  --> $DIR/regions-assoc-type-in-supertrait-outlives-container.rs:39:12
-   |
-LL | fn with_assoc<'a,'b>() {
-   |               -- -- lifetime `'b` defined here
-   |               |
-   |               lifetime `'a` defined here
-...
-LL |     let _: &'a WithAssoc<TheType<'b>> = loop { };
-   |            ^^^^^^^^^^^^^^^^^^^^^^^^^^ type annotation requires that `'b` must outlive `'a`
-   |
-   = help: consider adding the following bound: `'b: 'a`
-
-error: aborting due to previous error
-
index 6ae70ec672ce1210b4371b7e3fd9f7e92cdd2c56..d9fd1aebf277d719cce674760eaa55991154a72d 100644 (file)
@@ -1,16 +1,16 @@
 error[E0491]: in type `&'a WithAssoc<TheType<'b>>`, reference has a longer lifetime than the data it references
-  --> $DIR/regions-assoc-type-in-supertrait-outlives-container.rs:39:12
+  --> $DIR/regions-assoc-type-in-supertrait-outlives-container.rs:44:12
    |
 LL |     let _: &'a WithAssoc<TheType<'b>> = loop { };
    |            ^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
 note: the pointer is valid for the lifetime `'a` as defined here
-  --> $DIR/regions-assoc-type-in-supertrait-outlives-container.rs:33:15
+  --> $DIR/regions-assoc-type-in-supertrait-outlives-container.rs:38:15
    |
 LL | fn with_assoc<'a,'b>() {
    |               ^^
 note: but the referenced data is only valid for the lifetime `'b` as defined here
-  --> $DIR/regions-assoc-type-in-supertrait-outlives-container.rs:33:18
+  --> $DIR/regions-assoc-type-in-supertrait-outlives-container.rs:38:18
    |
 LL | fn with_assoc<'a,'b>() {
    |                  ^^
index 9bb385b0dcdc8e0c0801f5b9003619c2450cad20..ba7572ebe31377ea9302d72836efb2fa9f337a47 100644 (file)
@@ -1,5 +1,5 @@
 error: lifetime may not live long enough
-  --> $DIR/regions-assoc-type-in-supertrait-outlives-container.rs:39:12
+  --> $DIR/regions-assoc-type-in-supertrait-outlives-container.rs:44:12
    |
 LL | fn with_assoc<'a,'b>() {
    |               -- -- lifetime `'b` defined here
index 046d010002e6e7a9ad26f0fbb04e8ee53ab67fd8..08bc64926fac365247fa73e9b3a78064c3f1f009 100644 (file)
@@ -6,6 +6,11 @@
 // revisions: migrate nll
 //[nll]compile-flags: -Z borrowck=mir
 
+// Since we are testing nll (and migration) explicitly as a separate
+// revisions, don't worry about the --compare-mode=nll on this test.
+
+// ignore-compare-mode-nll
+
 #![allow(dead_code)]
 
 pub trait TheTrait {
diff --git a/src/test/ui/regions/regions-free-region-ordering-caller.migrate.nll.stderr b/src/test/ui/regions/regions-free-region-ordering-caller.migrate.nll.stderr
deleted file mode 100644 (file)
index 0d4694a..0000000
+++ /dev/null
@@ -1,39 +0,0 @@
-error: lifetime may not live long enough
-  --> $DIR/regions-free-region-ordering-caller.rs:11:12
-   |
-LL | fn call2<'a, 'b>(a: &'a usize, b: &'b usize) {
-   |          --  -- lifetime `'b` defined here
-   |          |
-   |          lifetime `'a` defined here
-LL |     let z: Option<&'b &'a usize> = None;
-   |            ^^^^^^^^^^^^^^^^^^^^^ type annotation requires that `'a` must outlive `'b`
-   |
-   = help: consider adding the following bound: `'a: 'b`
-
-error: lifetime may not live long enough
-  --> $DIR/regions-free-region-ordering-caller.rs:17:12
-   |
-LL | fn call3<'a, 'b>(a: &'a usize, b: &'b usize) {
-   |          --  -- lifetime `'b` defined here
-   |          |
-   |          lifetime `'a` defined here
-LL |     let y: Paramd<'a> = Paramd { x: a };
-LL |     let z: Option<&'b Paramd<'a>> = None;
-   |            ^^^^^^^^^^^^^^^^^^^^^^ type annotation requires that `'a` must outlive `'b`
-   |
-   = help: consider adding the following bound: `'a: 'b`
-
-error: lifetime may not live long enough
-  --> $DIR/regions-free-region-ordering-caller.rs:22:12
-   |
-LL | fn call4<'a, 'b>(a: &'a usize, b: &'b usize) {
-   |          --  -- lifetime `'b` defined here
-   |          |
-   |          lifetime `'a` defined here
-LL |     let z: Option<&'a &'b usize> = None;
-   |            ^^^^^^^^^^^^^^^^^^^^^ type annotation requires that `'b` must outlive `'a`
-   |
-   = help: consider adding the following bound: `'b: 'a`
-
-error: aborting due to 3 previous errors
-
index c0f3b24f68cfec2f6d55fa7223896f13b7b500cc..a27a010d7f302346ff76cb066406ac0f7197708e 100644 (file)
@@ -1,50 +1,50 @@
 error[E0491]: in type `&'b &'a usize`, reference has a longer lifetime than the data it references
-  --> $DIR/regions-free-region-ordering-caller.rs:11:12
+  --> $DIR/regions-free-region-ordering-caller.rs:16:12
    |
 LL |     let z: Option<&'b &'a usize> = None;
    |            ^^^^^^^^^^^^^^^^^^^^^
    |
 note: the pointer is valid for the lifetime `'b` as defined here
-  --> $DIR/regions-free-region-ordering-caller.rs:10:14
+  --> $DIR/regions-free-region-ordering-caller.rs:15:14
    |
 LL | fn call2<'a, 'b>(a: &'a usize, b: &'b usize) {
    |              ^^
 note: but the referenced data is only valid for the lifetime `'a` as defined here
-  --> $DIR/regions-free-region-ordering-caller.rs:10:10
+  --> $DIR/regions-free-region-ordering-caller.rs:15:10
    |
 LL | fn call2<'a, 'b>(a: &'a usize, b: &'b usize) {
    |          ^^
 
 error[E0491]: in type `&'b Paramd<'a>`, reference has a longer lifetime than the data it references
-  --> $DIR/regions-free-region-ordering-caller.rs:17:12
+  --> $DIR/regions-free-region-ordering-caller.rs:22:12
    |
 LL |     let z: Option<&'b Paramd<'a>> = None;
    |            ^^^^^^^^^^^^^^^^^^^^^^
    |
 note: the pointer is valid for the lifetime `'b` as defined here
-  --> $DIR/regions-free-region-ordering-caller.rs:15:14
+  --> $DIR/regions-free-region-ordering-caller.rs:20:14
    |
 LL | fn call3<'a, 'b>(a: &'a usize, b: &'b usize) {
    |              ^^
 note: but the referenced data is only valid for the lifetime `'a` as defined here
-  --> $DIR/regions-free-region-ordering-caller.rs:15:10
+  --> $DIR/regions-free-region-ordering-caller.rs:20:10
    |
 LL | fn call3<'a, 'b>(a: &'a usize, b: &'b usize) {
    |          ^^
 
 error[E0491]: in type `&'a &'b usize`, reference has a longer lifetime than the data it references
-  --> $DIR/regions-free-region-ordering-caller.rs:22:12
+  --> $DIR/regions-free-region-ordering-caller.rs:27:12
    |
 LL |     let z: Option<&'a &'b usize> = None;
    |            ^^^^^^^^^^^^^^^^^^^^^
    |
 note: the pointer is valid for the lifetime `'a` as defined here
-  --> $DIR/regions-free-region-ordering-caller.rs:21:10
+  --> $DIR/regions-free-region-ordering-caller.rs:26:10
    |
 LL | fn call4<'a, 'b>(a: &'a usize, b: &'b usize) {
    |          ^^
 note: but the referenced data is only valid for the lifetime `'b` as defined here
-  --> $DIR/regions-free-region-ordering-caller.rs:21:14
+  --> $DIR/regions-free-region-ordering-caller.rs:26:14
    |
 LL | fn call4<'a, 'b>(a: &'a usize, b: &'b usize) {
    |              ^^
index 0d4694a64d087c7f7502b550ef7f043ba1bacd81..546eb93d8ecab9a7f45f018dcca3de8751a85b28 100644 (file)
@@ -1,5 +1,5 @@
 error: lifetime may not live long enough
-  --> $DIR/regions-free-region-ordering-caller.rs:11:12
+  --> $DIR/regions-free-region-ordering-caller.rs:16:12
    |
 LL | fn call2<'a, 'b>(a: &'a usize, b: &'b usize) {
    |          --  -- lifetime `'b` defined here
@@ -11,7 +11,7 @@ LL |     let z: Option<&'b &'a usize> = None;
    = help: consider adding the following bound: `'a: 'b`
 
 error: lifetime may not live long enough
-  --> $DIR/regions-free-region-ordering-caller.rs:17:12
+  --> $DIR/regions-free-region-ordering-caller.rs:22:12
    |
 LL | fn call3<'a, 'b>(a: &'a usize, b: &'b usize) {
    |          --  -- lifetime `'b` defined here
@@ -24,7 +24,7 @@ LL |     let z: Option<&'b Paramd<'a>> = None;
    = help: consider adding the following bound: `'a: 'b`
 
 error: lifetime may not live long enough
-  --> $DIR/regions-free-region-ordering-caller.rs:22:12
+  --> $DIR/regions-free-region-ordering-caller.rs:27:12
    |
 LL | fn call4<'a, 'b>(a: &'a usize, b: &'b usize) {
    |          --  -- lifetime `'b` defined here
index 2bf4734cf73802137006e1cd64f2865447231f85..11997a5fb56a5c3659da35785af282d549d6e4f4 100644 (file)
@@ -5,6 +5,11 @@
 // revisions: migrate nll
 //[nll]compile-flags: -Z borrowck=mir
 
+// Since we are testing nll (and migration) explicitly as a separate
+// revisions, don't worry about the --compare-mode=nll on this test.
+
+// ignore-compare-mode-nll
+
 struct Paramd<'a> { x: &'a usize }
 
 fn call2<'a, 'b>(a: &'a usize, b: &'b usize) {
diff --git a/src/test/ui/regions/regions-outlives-projection-container-hrtb.migrate.nll.stderr b/src/test/ui/regions/regions-outlives-projection-container-hrtb.migrate.nll.stderr
deleted file mode 100644 (file)
index 29e92f3..0000000
+++ /dev/null
@@ -1,28 +0,0 @@
-error: lifetime may not live long enough
-  --> $DIR/regions-outlives-projection-container-hrtb.rs:30:12
-   |
-LL | fn with_assoc<'a,'b>() {
-   |               -- -- lifetime `'b` defined here
-   |               |
-   |               lifetime `'a` defined here
-...
-LL |     let _: &'a WithHrAssoc<TheType<'b>> = loop { };
-   |            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type annotation requires that `'b` must outlive `'a`
-   |
-   = help: consider adding the following bound: `'b: 'a`
-
-error: lifetime may not live long enough
-  --> $DIR/regions-outlives-projection-container-hrtb.rs:50:12
-   |
-LL | fn with_assoc_sub<'a,'b>() {
-   |                   -- -- lifetime `'b` defined here
-   |                   |
-   |                   lifetime `'a` defined here
-...
-LL |     let _: &'a WithHrAssocSub<TheType<'b>> = loop { };
-   |            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type annotation requires that `'b` must outlive `'a`
-   |
-   = help: consider adding the following bound: `'b: 'a`
-
-error: aborting due to 2 previous errors
-
index 60c115b3f5939e2c5b61f37586457d7953973f3b..f2308bb7c78b1e140b34eb2080484eb37a270256 100644 (file)
@@ -1,33 +1,33 @@
 error[E0491]: in type `&'a WithHrAssoc<TheType<'b>>`, reference has a longer lifetime than the data it references
-  --> $DIR/regions-outlives-projection-container-hrtb.rs:30:12
+  --> $DIR/regions-outlives-projection-container-hrtb.rs:35:12
    |
 LL |     let _: &'a WithHrAssoc<TheType<'b>> = loop { };
    |            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
 note: the pointer is valid for the lifetime `'a` as defined here
-  --> $DIR/regions-outlives-projection-container-hrtb.rs:27:15
+  --> $DIR/regions-outlives-projection-container-hrtb.rs:32:15
    |
 LL | fn with_assoc<'a,'b>() {
    |               ^^
 note: but the referenced data is only valid for the lifetime `'b` as defined here
-  --> $DIR/regions-outlives-projection-container-hrtb.rs:27:18
+  --> $DIR/regions-outlives-projection-container-hrtb.rs:32:18
    |
 LL | fn with_assoc<'a,'b>() {
    |                  ^^
 
 error[E0491]: in type `&'a WithHrAssocSub<TheType<'b>>`, reference has a longer lifetime than the data it references
-  --> $DIR/regions-outlives-projection-container-hrtb.rs:50:12
+  --> $DIR/regions-outlives-projection-container-hrtb.rs:55:12
    |
 LL |     let _: &'a WithHrAssocSub<TheType<'b>> = loop { };
    |            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
 note: the pointer is valid for the lifetime `'a` as defined here
-  --> $DIR/regions-outlives-projection-container-hrtb.rs:46:19
+  --> $DIR/regions-outlives-projection-container-hrtb.rs:51:19
    |
 LL | fn with_assoc_sub<'a,'b>() {
    |                   ^^
 note: but the referenced data is only valid for the lifetime `'b` as defined here
-  --> $DIR/regions-outlives-projection-container-hrtb.rs:46:22
+  --> $DIR/regions-outlives-projection-container-hrtb.rs:51:22
    |
 LL | fn with_assoc_sub<'a,'b>() {
    |                      ^^
index 29e92f33ec9148a97bc12a522b49883726195c17..472323772c1a50a0e68adb29d06120b28aac045a 100644 (file)
@@ -1,5 +1,5 @@
 error: lifetime may not live long enough
-  --> $DIR/regions-outlives-projection-container-hrtb.rs:30:12
+  --> $DIR/regions-outlives-projection-container-hrtb.rs:35:12
    |
 LL | fn with_assoc<'a,'b>() {
    |               -- -- lifetime `'b` defined here
@@ -12,7 +12,7 @@ LL |     let _: &'a WithHrAssoc<TheType<'b>> = loop { };
    = help: consider adding the following bound: `'b: 'a`
 
 error: lifetime may not live long enough
-  --> $DIR/regions-outlives-projection-container-hrtb.rs:50:12
+  --> $DIR/regions-outlives-projection-container-hrtb.rs:55:12
    |
 LL | fn with_assoc_sub<'a,'b>() {
    |                   -- -- lifetime `'b` defined here
index cee741184ca2ab68a0ddb8b35bf7864274b13533..695a81dca27c84925390f361575fc3ab1bd773e3 100644 (file)
@@ -4,6 +4,11 @@
 // revisions: migrate nll
 //[nll]compile-flags: -Z borrowck=mir
 
+// Since we are testing nll (and migration) explicitly as a separate
+// revisions, don't worry about the --compare-mode=nll on this test.
+
+// ignore-compare-mode-nll
+
 #![allow(dead_code)]
 
 pub trait TheTrait<'b> {
diff --git a/src/test/ui/regions/regions-outlives-projection-container-wc.migrate.nll.stderr b/src/test/ui/regions/regions-outlives-projection-container-wc.migrate.nll.stderr
deleted file mode 100644 (file)
index 7035144..0000000
+++ /dev/null
@@ -1,15 +0,0 @@
-error: lifetime may not live long enough
-  --> $DIR/regions-outlives-projection-container-wc.rs:33:12
-   |
-LL | fn with_assoc<'a,'b>() {
-   |               -- -- lifetime `'b` defined here
-   |               |
-   |               lifetime `'a` defined here
-...
-LL |     let _: &'a WithAssoc<TheType<'b>> = loop { };
-   |            ^^^^^^^^^^^^^^^^^^^^^^^^^^ type annotation requires that `'b` must outlive `'a`
-   |
-   = help: consider adding the following bound: `'b: 'a`
-
-error: aborting due to previous error
-
index 8430b69f998326f36e2b9177f7aa5539329a2f98..bda2896fca4ac9b3bb831986f4e9494c630bd2b6 100644 (file)
@@ -1,16 +1,16 @@
 error[E0491]: in type `&'a WithAssoc<TheType<'b>>`, reference has a longer lifetime than the data it references
-  --> $DIR/regions-outlives-projection-container-wc.rs:33:12
+  --> $DIR/regions-outlives-projection-container-wc.rs:38:12
    |
 LL |     let _: &'a WithAssoc<TheType<'b>> = loop { };
    |            ^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
 note: the pointer is valid for the lifetime `'a` as defined here
-  --> $DIR/regions-outlives-projection-container-wc.rs:27:15
+  --> $DIR/regions-outlives-projection-container-wc.rs:32:15
    |
 LL | fn with_assoc<'a,'b>() {
    |               ^^
 note: but the referenced data is only valid for the lifetime `'b` as defined here
-  --> $DIR/regions-outlives-projection-container-wc.rs:27:18
+  --> $DIR/regions-outlives-projection-container-wc.rs:32:18
    |
 LL | fn with_assoc<'a,'b>() {
    |                  ^^
index 7035144302479f4a0578aa074b6d1d4607f78bca..fc32a72d508963db013d438d3df048b49ae6be1b 100644 (file)
@@ -1,5 +1,5 @@
 error: lifetime may not live long enough
-  --> $DIR/regions-outlives-projection-container-wc.rs:33:12
+  --> $DIR/regions-outlives-projection-container-wc.rs:38:12
    |
 LL | fn with_assoc<'a,'b>() {
    |               -- -- lifetime `'b` defined here
index 99965f333907bff77772640989900ecc090fc93d..c9b714cffb6e4528cc0bf1f8a7050fd61c98cd95 100644 (file)
@@ -6,6 +6,11 @@
 // revisions: migrate nll
 //[nll]compile-flags: -Z borrowck=mir
 
+// Since we are testing nll (and migration) explicitly as a separate
+// revisions, don't worry about the --compare-mode=nll on this test.
+
+// ignore-compare-mode-nll
+
 #![allow(dead_code)]
 
 pub trait TheTrait {
index 0098f087d10f8dcf469d7d45683beb8683c871dd..cb2b585ab96a8cd7680b5b006228e1cee1936a09 100644 (file)
@@ -30,3 +30,15 @@ pub enum VariantNonExhaustive {
 pub enum NonExhaustiveSingleVariant {
     A(bool),
 }
+
+#[repr(u8)]
+pub enum FieldLessWithNonExhaustiveVariant {
+    A,
+    B,
+    #[non_exhaustive]
+    C,
+}
+
+impl Default for FieldLessWithNonExhaustiveVariant {
+    fn default() -> Self { Self::A }
+}
diff --git a/src/test/ui/rfc-2008-non-exhaustive/enum-as-cast.rs b/src/test/ui/rfc-2008-non-exhaustive/enum-as-cast.rs
new file mode 100644 (file)
index 0000000..d9657ba
--- /dev/null
@@ -0,0 +1,17 @@
+// aux-build:enums.rs
+// run-pass
+
+extern crate enums;
+
+use enums::FieldLessWithNonExhaustiveVariant;
+
+fn main() {
+    let e = FieldLessWithNonExhaustiveVariant::default();
+    // FIXME: https://github.com/rust-lang/rust/issues/91161
+    // This `as` cast *should* be an error, since it would fail
+    // if the non-exhaustive variant got fields.  But today it
+    // doesn't.  The fix for that will update this test to
+    // show an error (and not be run-pass any more).
+    let d = e as u8;
+    assert_eq!(d, 0);
+}
index 7f15c1c1f57703473063f94fe6dfabd02498192f..86513b6064d2df50f0af1a961afea91cab6fb4bd 100644 (file)
@@ -1,26 +1,5 @@
-error[E0277]: `dyn for<'a, 'b> Fn(&'a Foo<'b>) -> &'a Foo<'b>` cannot be shared between threads safely
-  --> $DIR/rfc1623.rs:21:1
-   |
-LL | / static SOME_STRUCT: &SomeStruct = &SomeStruct {
-LL | |     foo: &Foo { bools: &[false, true] },
-LL | |     bar: &Bar { bools: &[true, true] },
-LL | |     f: &id,
-LL | |
-LL | | };
-   | |__^ `dyn for<'a, 'b> Fn(&'a Foo<'b>) -> &'a Foo<'b>` cannot be shared between threads safely
-   |
-   = help: within `&SomeStruct`, the trait `Sync` is not implemented for `dyn for<'a, 'b> Fn(&'a Foo<'b>) -> &'a Foo<'b>`
-   = note: required because it appears within the type `&dyn for<'a, 'b> Fn(&'a Foo<'b>) -> &'a Foo<'b>`
-note: required because it appears within the type `SomeStruct`
-  --> $DIR/rfc1623.rs:11:8
-   |
-LL | struct SomeStruct<'x, 'y, 'z: 'x> {
-   |        ^^^^^^^^^^
-   = note: required because it appears within the type `&SomeStruct`
-   = note: shared static variables must have a type that implements `Sync`
-
 error[E0308]: mismatched types
-  --> $DIR/rfc1623.rs:21:35
+  --> $DIR/rfc1623.rs:25:35
    |
 LL |   static SOME_STRUCT: &SomeStruct = &SomeStruct {
    |  ___________________________________^
@@ -35,7 +14,7 @@ LL | | };
               found type `Fn<(&Foo<'_>,)>`
 
 error[E0308]: mismatched types
-  --> $DIR/rfc1623.rs:21:35
+  --> $DIR/rfc1623.rs:25:35
    |
 LL |   static SOME_STRUCT: &SomeStruct = &SomeStruct {
    |  ___________________________________^
@@ -50,7 +29,7 @@ LL | | };
               found type `Fn<(&Foo<'_>,)>`
 
 error: implementation of `FnOnce` is not general enough
-  --> $DIR/rfc1623.rs:21:35
+  --> $DIR/rfc1623.rs:25:35
    |
 LL |   static SOME_STRUCT: &SomeStruct = &SomeStruct {
    |  ___________________________________^
@@ -65,7 +44,7 @@ LL | | };
    = note: ...but it actually implements `FnOnce<(&'2 Foo<'_>,)>`, for some specific lifetime `'2`
 
 error: implementation of `FnOnce` is not general enough
-  --> $DIR/rfc1623.rs:21:35
+  --> $DIR/rfc1623.rs:25:35
    |
 LL |   static SOME_STRUCT: &SomeStruct = &SomeStruct {
    |  ___________________________________^
@@ -79,7 +58,6 @@ LL | | };
    = note: `fn(&Foo<'2>) -> &Foo<'2> {id::<&Foo<'2>>}` must implement `FnOnce<(&'a Foo<'1>,)>`, for any lifetime `'1`...
    = note: ...but it actually implements `FnOnce<(&Foo<'2>,)>`, for some specific lifetime `'2`
 
-error: aborting due to 5 previous errors
+error: aborting due to 4 previous errors
 
-Some errors have detailed explanations: E0277, E0308.
-For more information about an error, try `rustc --explain E0277`.
+For more information about this error, try `rustc --explain E0308`.
index 9ff4813d11286e860c0daf2a9f35dcd2c6c78789..32e00f9cb76c301e5c3107c6e03a803979389d3b 100644 (file)
@@ -14,6 +14,10 @@ struct SomeStruct<'x, 'y, 'z: 'x> {
     f: &'y dyn for<'a, 'b> Fn(&'a Foo<'b>) -> &'a Foo<'b>,
 }
 
+// Without this, the wf-check will fail early so we'll never see the
+// error in SOME_STRUCT's body.
+unsafe impl<'x, 'y, 'z: 'x> Sync for SomeStruct<'x, 'y, 'z> {}
+
 fn id<T>(t: T) -> T {
     t
 }
index e95e68c8e6d26c92669d517b9e78f9d6d95ae2eb..16829b5caa0b6894304ddcae9ba8d5706acd515d 100644 (file)
@@ -1,5 +1,5 @@
 error: implementation of `FnOnce` is not general enough
-  --> $DIR/rfc1623.rs:24:8
+  --> $DIR/rfc1623.rs:28:8
    |
 LL |     f: &id,
    |        ^^^ implementation of `FnOnce` is not general enough
index c092aa26946f6140d813be7289cc95263f6b0220..d6822d94ca8c96ec0529461bee12948d6bec2fb2 100644 (file)
@@ -21,6 +21,8 @@ LL |             ::std::mem::drop(x);
 LL |         };
 LL |         println!("{}", x);
    |                        ^ value borrowed here after move
+   |
+   = note: this error originates in the macro `$crate::format_args_nl` (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error[E0506]: cannot assign to `i` because it is borrowed
   --> $DIR/try-block-maybe-bad-lifetime.rs:40:9
index f630d2783350306983396776befcecc2bb8d6f21..86b685022b20ec7dd71e5b9b757c57c01253285c 100644 (file)
@@ -5,12 +5,9 @@
 
 use std::fmt::Debug;
 
-type Foo = impl Debug;
-//~^ ERROR: could not find defining uses
+type Foo = impl Debug; //~ ERROR could not find defining uses
 
-static FOO1: Foo = 22_u32;
-//~^ ERROR: mismatched types [E0308]
-const FOO2: Foo = 22_u32;
-//~^ ERROR: mismatched types [E0308]
+static FOO1: Foo = 22_u32; //~ ERROR mismatched types
+const FOO2: Foo = 22_u32; //~ ERROR mismatched types
 
 fn main() {}
index 72083d014fe3a0006ad14af3949cbec9828b858a..6f4c2944f72851e4ec6b1c8084091b1d86d19b2f 100644 (file)
@@ -1,9 +1,9 @@
 error[E0308]: mismatched types
-  --> $DIR/static-const-types.rs:11:20
+  --> $DIR/static-const-types.rs:10:20
    |
 LL | type Foo = impl Debug;
    |            ---------- the expected opaque type
-...
+LL | 
 LL | static FOO1: Foo = 22_u32;
    |                    ^^^^^^ expected opaque type, found `u32`
    |
@@ -11,7 +11,7 @@ LL | static FOO1: Foo = 22_u32;
                      found type `u32`
 
 error[E0308]: mismatched types
-  --> $DIR/static-const-types.rs:13:19
+  --> $DIR/static-const-types.rs:11:19
    |
 LL | type Foo = impl Debug;
    |            ---------- the expected opaque type
index 11ce005bb457c861e50921de05d2be07185e9c82..361a6e2d8c2786658f49be72d2f1e800aed5cc39 100644 (file)
@@ -7,6 +7,8 @@ LL |     let _y = x;
    |              - value moved here
 LL |     println!("{}", x);
    |                    ^ value borrowed here after move
+   |
+   = note: this error originates in the macro `$crate::format_args_nl` (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error: aborting due to previous error
 
index cda08b0f4e09cc6c1404a2389535e1b39f83c42e..377a8074458912c55e789f70828f813b7afa3e69 100644 (file)
@@ -13,6 +13,7 @@ note: this function takes ownership of the receiver `self`, which moves `start`
    |
 LL |     fn make_string_bar(mut self) -> Mine{
    |                            ^^^^
+   = note: this error originates in the macro `$crate::format_args_nl` (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error: aborting due to previous error
 
index 7f08ace4f1305de7f3b1b0e2f765911957226bd4..294967c53f0c70d598fc54ca189313c86c576ea7 160000 (submodule)
@@ -1 +1 @@
-Subproject commit 7f08ace4f1305de7f3b1b0e2f765911957226bd4
+Subproject commit 294967c53f0c70d598fc54ca189313c86c576ea7
index 24ac5917dcb0521350e0072234bee02982e58f7a..94b35ad88af2d605243fb06db7379633d43bb15b 100644 (file)
@@ -3,7 +3,6 @@
 use clippy_utils::ty::{implements_trait, is_copy};
 use clippy_utils::{get_trait_def_id, is_automatically_derived, is_lint_allowed, match_def_path};
 use if_chain::if_chain;
-use rustc_hir::def_id::DefId;
 use rustc_hir::intravisit::{walk_expr, walk_fn, walk_item, FnKind, NestedVisitorMap, Visitor};
 use rustc_hir::{
     BlockCheckMode, BodyId, Expr, ExprKind, FnDecl, HirId, Impl, Item, ItemKind, TraitRef, UnsafeSource, Unsafety,
@@ -343,11 +342,6 @@ fn check_unsafe_derive_deserialize<'tcx>(
     trait_ref: &TraitRef<'_>,
     ty: Ty<'tcx>,
 ) {
-    fn item_from_def_id<'tcx>(cx: &LateContext<'tcx>, def_id: DefId) -> &'tcx Item<'tcx> {
-        let hir_id = cx.tcx.hir().local_def_id_to_hir_id(def_id.expect_local());
-        cx.tcx.hir().expect_item(hir_id)
-    }
-
     fn has_unsafe<'tcx>(cx: &LateContext<'tcx>, item: &'tcx Item<'_>) -> bool {
         let mut visitor = UnsafeVisitor { cx, has_unsafe: false };
         walk_item(&mut visitor, item);
@@ -363,7 +357,7 @@ fn has_unsafe<'tcx>(cx: &LateContext<'tcx>, item: &'tcx Item<'_>) -> bool {
         if !is_lint_allowed(cx, UNSAFE_DERIVE_DESERIALIZE, adt_hir_id);
         if cx.tcx.inherent_impls(def.did)
             .iter()
-            .map(|imp_did| item_from_def_id(cx, *imp_did))
+            .map(|imp_did| cx.tcx.hir().expect_item(imp_did.expect_local()))
             .any(|imp| has_unsafe(cx, imp));
         then {
             span_lint_and_help(
index 26c29fbb289cb7f8d11e1aa41ce5d22d46a07cb0..e46739fea34beb1b70e1f8c0d6a68d5d834bc592 100644 (file)
@@ -1939,7 +1939,7 @@ fn check_impl_item(&mut self, cx: &LateContext<'tcx>, impl_item: &'tcx hir::Impl
             return;
         }
         let name = impl_item.ident.name.as_str();
-        let parent = cx.tcx.hir().get_parent_item(impl_item.hir_id());
+        let parent = cx.tcx.hir().get_parent_did(impl_item.hir_id());
         let item = cx.tcx.hir().expect_item(parent);
         let self_ty = cx.tcx.type_of(item.def_id);
 
index 2a85a67fa099cac9355d26e61ca5bdada9387994..2ea97eb88f783558076b8655f62b0444723d4701 100644 (file)
@@ -279,8 +279,8 @@ fn check_trait_item(&mut self, cx: &LateContext<'tcx>, trait_item: &'tcx TraitIt
 
     fn check_impl_item(&mut self, cx: &LateContext<'tcx>, impl_item: &'tcx ImplItem<'_>) {
         if let ImplItemKind::Const(hir_ty, body_id) = &impl_item.kind {
-            let item_hir_id = cx.tcx.hir().get_parent_node(impl_item.hir_id());
-            let item = cx.tcx.hir().expect_item(item_hir_id);
+            let item_def_id = cx.tcx.hir().get_parent_did(impl_item.hir_id());
+            let item = cx.tcx.hir().expect_item(item_def_id);
 
             match &item.kind {
                 ItemKind::Impl(Impl {
index 4ba5e1a0f5357829f95fad45aec80029882e8b88..9390378d789cdddec8c5b27f5156843e7366169d 100644 (file)
@@ -50,7 +50,7 @@ fn check_impl_item(&mut self, cx: &LateContext<'tcx>, impl_item: &'tcx ImplItem<
             _ => return,
         }
 
-        let parent = cx.tcx.hir().get_parent_item(impl_item.hir_id());
+        let parent = cx.tcx.hir().get_parent_did(impl_item.hir_id());
         let item = cx.tcx.hir().expect_item(parent);
         let self_ty = cx.tcx.type_of(item.def_id);
         let ret_ty = return_ty(cx, impl_item.hir_id());
index e7e249c79a2fad0f6f97e1a8110d62b41f763029..c961f995667952343e846eeee07c36b68cb214a5 100644 (file)
@@ -41,7 +41,7 @@ fn check_impl_item(&mut self, cx: &LateContext<'tcx>, impl_item: &ImplItem<'_>)
         if impl_item.span.from_expansion() {
             return;
         }
-        let parent = cx.tcx.hir().get_parent_item(impl_item.hir_id());
+        let parent = cx.tcx.hir().get_parent_did(impl_item.hir_id());
         let parent_item = cx.tcx.hir().expect_item(parent);
         let assoc_item = cx.tcx.associated_item(impl_item.def_id);
         if_chain! {
index abca7af30a00617510de76edd51c976e577d1e80..c8239897f3abb5b7032d8f574aeae103599b1e71 100644 (file)
@@ -21,15 +21,16 @@ LL | impl<N, M> TypeVal<usize> for Multiply<N, M> where N: TypeVal<VAL> {}
    |          |
    |          help: you might be missing a type parameter: `, VAL`
 
-error[E0283]: type annotations needed
-  --> $DIR/ice-6252.rs:10:12
+error[E0046]: not all trait items implemented, missing: `VAL`
+  --> $DIR/ice-6252.rs:10:1
    |
+LL |     const VAL: T;
+   |     ------------- `VAL` from trait
+...
 LL | impl<N, M> TypeVal<usize> for Multiply<N, M> where N: TypeVal<VAL> {}
-   |            ^^^^^^^^^^^^^^ cannot infer type for struct `Multiply<N, M>`
-   |
-   = note: cannot satisfy `Multiply<N, M>: TypeVal<usize>`
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ missing `VAL` in implementation
 
 error: aborting due to 3 previous errors
 
-Some errors have detailed explanations: E0283, E0412.
-For more information about an error, try `rustc --explain E0283`.
+Some errors have detailed explanations: E0046, E0412.
+For more information about an error, try `rustc --explain E0046`.
index 76a3329f51439ff2cacda4d26d478a9dc1682a06..9983e0fc634e11717eb457a73fe84cfc9409ba8f 160000 (submodule)
@@ -1 +1 @@
-Subproject commit 76a3329f51439ff2cacda4d26d478a9dc1682a06
+Subproject commit 9983e0fc634e11717eb457a73fe84cfc9409ba8f
index 183ef048f61ae36aa389d1d0345cde940fe788e9..d9b2291f546abc77d24499339a72a89127464b95 160000 (submodule)
@@ -1 +1 @@
-Subproject commit 183ef048f61ae36aa389d1d0345cde940fe788e9
+Subproject commit d9b2291f546abc77d24499339a72a89127464b95
index 79f82f6b8e0ceb99fe26d976bae0285f53a07473..bb120e876c620345b6e6704bf5eb2578a2b044ed 100644 (file)
@@ -1 +1 @@
-1.58.0
+1.59.0