summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Cargo.lock81
-rw-r--r--Cargo.toml2
-rw-r--r--compiler/rustc_abi/src/lib.rs7
-rw-r--r--compiler/rustc_ast_lowering/src/expr.rs77
-rw-r--r--compiler/rustc_ast_lowering/src/item.rs28
-rw-r--r--compiler/rustc_ast_pretty/src/pprust/state/item.rs15
-rw-r--r--compiler/rustc_borrowck/src/type_check/canonical.rs6
-rw-r--r--compiler/rustc_const_eval/src/const_eval/machine.rs2
-rw-r--r--compiler/rustc_const_eval/src/interpret/eval_context.rs4
-rw-r--r--compiler/rustc_data_structures/src/fingerprint.rs2
-rw-r--r--compiler/rustc_data_structures/src/intern.rs83
-rw-r--r--compiler/rustc_data_structures/src/sorted_map.rs4
-rw-r--r--compiler/rustc_data_structures/src/sorted_map/index_map.rs9
-rw-r--r--compiler/rustc_data_structures/src/stable_hasher.rs97
-rw-r--r--compiler/rustc_error_messages/locales/en-US/hir_analysis.ftl2
-rw-r--r--compiler/rustc_hir/src/hir_id.rs6
-rw-r--r--compiler/rustc_hir/src/lang_items.rs3
-rw-r--r--compiler/rustc_hir_analysis/src/astconv/mod.rs1
-rw-r--r--compiler/rustc_hir_analysis/src/check/compare_method.rs51
-rw-r--r--compiler/rustc_hir_analysis/src/errors.rs4
-rw-r--r--compiler/rustc_hir_analysis/src/variance/mod.rs42
-rw-r--r--compiler/rustc_hir_pretty/src/lib.rs13
-rw-r--r--compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs10
-rw-r--r--compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs4
-rw-r--r--compiler/rustc_hir_typeck/src/method/suggest.rs23
-rw-r--r--compiler/rustc_infer/src/infer/error_reporting/mod.rs10
-rw-r--r--compiler/rustc_interface/src/passes.rs23
-rw-r--r--compiler/rustc_interface/src/queries.rs14
-rw-r--r--compiler/rustc_interface/src/tests.rs1
-rw-r--r--compiler/rustc_lint/src/pass_by_value.rs2
-rw-r--r--compiler/rustc_lint/src/unused.rs31
-rw-r--r--compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp11
-rw-r--r--compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp16
-rw-r--r--compiler/rustc_macros/src/query.rs4
-rw-r--r--compiler/rustc_metadata/src/fs.rs10
-rw-r--r--compiler/rustc_middle/src/arena.rs7
-rw-r--r--compiler/rustc_middle/src/mir/interpret/allocation.rs2
-rw-r--r--compiler/rustc_middle/src/query/mod.rs2
-rw-r--r--compiler/rustc_middle/src/ty/context.rs123
-rw-r--r--compiler/rustc_middle/src/ty/generics.rs14
-rw-r--r--compiler/rustc_middle/src/ty/mod.rs149
-rw-r--r--compiler/rustc_middle/src/ty/query.rs24
-rw-r--r--compiler/rustc_middle/src/ty/sty.rs15
-rw-r--r--compiler/rustc_middle/src/ty/subst.rs23
-rw-r--r--compiler/rustc_mir_build/src/build/mod.rs20
-rw-r--r--compiler/rustc_mir_build/src/build/scope.rs56
-rw-r--r--compiler/rustc_mir_dataflow/src/value_analysis.rs2
-rw-r--r--compiler/rustc_mir_transform/src/dump_mir.rs6
-rw-r--r--compiler/rustc_mir_transform/src/inline.rs28
-rw-r--r--compiler/rustc_mir_transform/src/remove_zsts.rs27
-rw-r--r--compiler/rustc_parse/src/parser/expr.rs19
-rw-r--r--compiler/rustc_parse/src/parser/item.rs5
-rw-r--r--compiler/rustc_parse/src/parser/mod.rs4
-rw-r--r--compiler/rustc_passes/src/liveness.rs8
-rw-r--r--compiler/rustc_query_system/src/dep_graph/graph.rs15
-rw-r--r--compiler/rustc_resolve/src/late.rs4
-rw-r--r--compiler/rustc_session/src/config.rs5
-rw-r--r--compiler/rustc_session/src/options.rs3
-rw-r--r--compiler/rustc_span/src/def_id.rs2
-rw-r--r--compiler/rustc_span/src/symbol.rs3
-rw-r--r--compiler/rustc_trait_selection/src/traits/codegen.rs2
-rw-r--r--compiler/rustc_trait_selection/src/traits/const_evaluatable.rs58
-rw-r--r--compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs98
-rw-r--r--compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs4
-rw-r--r--compiler/rustc_trait_selection/src/traits/mod.rs2
-rw-r--r--compiler/rustc_trait_selection/src/traits/project.rs42
-rw-r--r--compiler/rustc_trait_selection/src/traits/query/normalize.rs14
-rw-r--r--compiler/rustc_trait_selection/src/traits/select/mod.rs13
-rw-r--r--compiler/rustc_trait_selection/src/traits/wf.rs19
-rw-r--r--compiler/rustc_type_ir/src/lib.rs2
-rw-r--r--compiler/rustc_type_ir/src/sty.rs582
-rw-r--r--compiler/rustc_type_ir/src/ty_info.rs122
-rw-r--r--config.toml.example10
-rw-r--r--library/alloc/src/collections/vec_deque/mod.rs17
-rw-r--r--library/core/src/cmp.rs5
-rw-r--r--library/core/src/convert/num.rs2
-rw-r--r--library/core/src/future/mod.rs10
-rw-r--r--library/core/src/iter/sources/repeat_n.rs2
-rw-r--r--library/core/src/str/pattern.rs2
-rw-r--r--library/core/src/task/wake.rs1
-rw-r--r--library/std/Cargo.toml2
-rw-r--r--library/std/src/sync/mpmc/array.rs2
-rw-r--r--library/std/src/sync/mpsc/mod.rs12
-rw-r--r--library/std/src/thread/scoped.rs2
-rw-r--r--src/bootstrap/builder.rs2
-rw-r--r--src/bootstrap/config.rs3
-rw-r--r--src/bootstrap/flags.rs9
-rw-r--r--src/bootstrap/lib.rs50
-rw-r--r--src/bootstrap/run.rs63
-rw-r--r--src/bootstrap/sanity.rs7
-rw-r--r--src/bootstrap/setup.rs91
-rw-r--r--src/bootstrap/tool.rs2
-rw-r--r--src/ci/docker/host-aarch64/aarch64-gnu/Dockerfile3
-rw-r--r--src/ci/docker/host-x86_64/dist-i686-linux/Dockerfile3
-rw-r--r--src/ci/docker/host-x86_64/dist-x86_64-freebsd/Dockerfile3
-rw-r--r--src/ci/docker/host-x86_64/dist-x86_64-illumos/Dockerfile3
-rw-r--r--src/ci/docker/host-x86_64/dist-x86_64-linux/Dockerfile3
-rw-r--r--src/ci/docker/host-x86_64/dist-x86_64-musl/Dockerfile3
-rw-r--r--src/ci/docker/host-x86_64/i686-gnu-nopt/Dockerfile3
-rw-r--r--src/ci/docker/host-x86_64/i686-gnu/Dockerfile3
-rw-r--r--src/ci/docker/host-x86_64/mingw-check/Dockerfile8
-rw-r--r--src/ci/docker/host-x86_64/test-various/Dockerfile3
-rw-r--r--src/ci/docker/host-x86_64/wasm32/Dockerfile3
-rw-r--r--src/ci/docker/host-x86_64/x86_64-gnu-aux/Dockerfile3
-rw-r--r--src/ci/docker/host-x86_64/x86_64-gnu-debug/Dockerfile3
-rw-r--r--src/ci/docker/host-x86_64/x86_64-gnu-distcheck/Dockerfile3
-rw-r--r--src/ci/docker/host-x86_64/x86_64-gnu-llvm-13-stage1/Dockerfile3
-rw-r--r--src/ci/docker/host-x86_64/x86_64-gnu-llvm-13/Dockerfile8
-rw-r--r--src/ci/docker/host-x86_64/x86_64-gnu-nopt/Dockerfile3
-rw-r--r--src/ci/docker/host-x86_64/x86_64-gnu-tools/Dockerfile6
-rw-r--r--src/ci/docker/host-x86_64/x86_64-gnu/Dockerfile3
-rwxr-xr-xsrc/ci/docker/scripts/freebsd-toolchain.sh2
m---------src/doc/book0
m---------src/doc/embedded-book0
m---------src/doc/nomicon0
m---------src/doc/reference0
m---------src/doc/rust-by-example0
m---------src/doc/rustc-dev-guide0
-rw-r--r--src/doc/unstable-book/src/language-features/abi-efiapi.md2
-rw-r--r--src/librustdoc/html/static/css/rustdoc.css18
-rw-r--r--src/librustdoc/html/static/js/scrape-examples.js2
-rw-r--r--src/librustdoc/html/static_files.rs2
-rw-r--r--src/test/mir-opt/inline/cycle.g.Inline.diff23
-rw-r--r--src/test/mir-opt/inline/cycle.main.Inline.diff40
-rw-r--r--src/test/mir-opt/inline/exponential_runtime.main.Inline.diff50
-rw-r--r--src/test/mir-opt/inline/exponential_runtime.rs87
-rw-r--r--src/test/mir-opt/inline/inline_cycle.one.Inline.diff11
-rw-r--r--src/test/mir-opt/inline/inline_cycle.two.Inline.diff23
-rw-r--r--src/test/mir-opt/inline/inline_cycle_generic.main.Inline.diff9
-rw-r--r--src/test/mir-opt/inline/inline_diverging.h.Inline.diff52
-rw-r--r--src/test/mir-opt/remove_zsts.get_union.PreCodegen.after.mir10
-rw-r--r--src/test/mir-opt/remove_zsts.get_union.RemoveZsts.diff19
-rw-r--r--src/test/mir-opt/remove_zsts.rs14
-rw-r--r--src/test/mir-opt/remove_zsts_dont_touch_unions.get_union.RemoveZsts.after.mir15
-rw-r--r--src/test/mir-opt/remove_zsts_dont_touch_unions.rs19
-rw-r--r--src/test/mir-opt/separate_const_switch.identity.SeparateConstSwitch.diff35
-rw-r--r--src/test/rustdoc-gui/enum-variants.goml5
-rw-r--r--src/test/rustdoc-gui/method-margins.goml1
-rw-r--r--src/test/rustdoc-gui/scrape-examples-button-focus.goml13
-rw-r--r--src/test/rustdoc-gui/src/scrape_examples/examples/check.rs1
-rw-r--r--src/test/rustdoc-gui/src/test_docs/lib.rs1
-rw-r--r--src/test/rustdoc-gui/toggle-docs.goml4
-rw-r--r--src/test/rustdoc-ui/z-help.stdout1
-rw-r--r--src/test/ui/associated-inherent-types/issue-104260.rs14
-rw-r--r--src/test/ui/associated-inherent-types/normalize-projection-0.rs22
-rw-r--r--src/test/ui/associated-inherent-types/normalize-projection-1.rs22
-rw-r--r--src/test/ui/async-await/async-await-let-else.drop-tracking.stderr2
-rw-r--r--src/test/ui/async-await/in-trait/return-type-suggestion.rs14
-rw-r--r--src/test/ui/async-await/in-trait/return-type-suggestion.stderr23
-rw-r--r--src/test/ui/async-await/issue-68112.drop_tracking.stderr2
-rw-r--r--src/test/ui/async-await/issue-68112.no_drop_tracking.stderr2
-rw-r--r--src/test/ui/async-await/issue-69446-fnmut-capture.stderr3
-rw-r--r--src/test/ui/async-await/issue-70935-complex-spans.drop_tracking.stderr2
-rw-r--r--src/test/ui/async-await/partial-drop-partial-reinit.drop_tracking.stderr2
-rw-r--r--src/test/ui/async-await/partial-drop-partial-reinit.no_drop_tracking.stderr2
-rw-r--r--src/test/ui/async-await/track-caller/issue-105134.rs11
-rw-r--r--src/test/ui/async-await/track-caller/panic-track-caller.rs14
-rw-r--r--src/test/ui/auto-traits/bad-generics-on-dyn.rs11
-rw-r--r--src/test/ui/auto-traits/bad-generics-on-dyn.stderr11
-rw-r--r--src/test/ui/binop/binop-mul-i32-f32.stderr11
-rw-r--r--src/test/ui/const-generics/defaults/rp_impl_trait_fail.stderr8
-rw-r--r--src/test/ui/const-generics/defaults/self-referential.rs4
-rw-r--r--src/test/ui/const-generics/defaults/self-referential.stderr11
-rw-r--r--src/test/ui/const-generics/generic_const_exprs/const_kind_expr/wf_obligation.rs22
-rw-r--r--src/test/ui/const-generics/generic_const_exprs/const_kind_expr/wf_obligation.stderr20
-rw-r--r--src/test/ui/consts/const-eval/const-eval-overflow-3b.stderr11
-rw-r--r--src/test/ui/consts/const-eval/const-eval-overflow-4b.stderr11
-rw-r--r--src/test/ui/did_you_mean/issue-39802-show-5-trait-impls.stderr9
-rw-r--r--src/test/ui/duplicate/duplicate-type-parameter.stderr4
-rw-r--r--src/test/ui/generic-associated-types/own-bound-span.rs17
-rw-r--r--src/test/ui/generic-associated-types/own-bound-span.stderr15
-rw-r--r--src/test/ui/impl-trait/equality.stderr13
-rw-r--r--src/test/ui/impl-trait/nested-return-type4.rs8
-rw-r--r--src/test/ui/impl-trait/nested-return-type4.stderr20
-rw-r--r--src/test/ui/issues/issue-105330.rs21
-rw-r--r--src/test/ui/issues/issue-105330.stderr109
-rw-r--r--src/test/ui/issues/issue-24352.stderr11
-rw-r--r--src/test/ui/kindck/kindck-copy.stderr22
-rw-r--r--src/test/ui/lexer/lex-bad-char-literals-6.stderr18
-rw-r--r--src/test/ui/lint/issue-104897.rs6
-rw-r--r--src/test/ui/lint/issue-104897.stderr43
-rw-r--r--src/test/ui/macros/syntax-error-recovery.stderr1
-rw-r--r--src/test/ui/maximal_mir_to_hir_coverage.rs10
-rw-r--r--src/test/ui/mismatched_types/binops.stderr13
-rw-r--r--src/test/ui/never_type/issue-13352.stderr13
-rw-r--r--src/test/ui/numbers-arithmetic/not-suggest-float-literal.stderr141
-rw-r--r--src/test/ui/numbers-arithmetic/suggest-float-literal.stderr88
-rw-r--r--src/test/ui/object-safety/object-safety-supertrait-mentions-GAT.stderr6
-rw-r--r--src/test/ui/parser/expr-as-stmt.fixed12
-rw-r--r--src/test/ui/parser/expr-as-stmt.rs12
-rw-r--r--src/test/ui/parser/expr-as-stmt.stderr43
-rw-r--r--src/test/ui/parser/issue-101477-enum.stderr2
-rw-r--r--src/test/ui/parser/issue-103869.rs9
-rw-r--r--src/test/ui/parser/issue-103869.stderr16
-rw-r--r--src/test/ui/parser/macro/issue-37113.stderr1
-rw-r--r--src/test/ui/regions/closure-in-projection-issue-97405.rs4
-rw-r--r--src/test/ui/regions/closure-in-projection-issue-97405.stderr20
-rw-r--r--src/test/ui/rfc-1445-restrict-constants-in-patterns/match-requires-both-partialeq-and-eq.rs2
-rw-r--r--src/test/ui/span/multiline-span-simple.stderr13
-rw-r--r--src/test/ui/structs/struct-fn-in-definition.rs1
-rw-r--r--src/test/ui/structs/struct-fn-in-definition.stderr1
-rw-r--r--src/test/ui/suggestions/assoc-const-as-fn.stderr6
-rw-r--r--src/test/ui/suggestions/try-removing-the-field.rs15
-rw-r--r--src/test/ui/suggestions/try-removing-the-field.stderr16
-rw-r--r--src/test/ui/trait-bounds/impl-missing-where-clause-lifetimes-from-trait.rs38
-rw-r--r--src/test/ui/trait-bounds/impl-missing-where-clause-lifetimes-from-trait.stderr36
-rw-r--r--src/test/ui/traits/issue-79458.stderr5
-rw-r--r--src/test/ui/try-trait/bad-interconversion.stderr11
-rw-r--r--src/test/ui/type-alias-impl-trait/self-referential-2.stderr11
-rw-r--r--src/test/ui/type-alias-impl-trait/self-referential-4.stderr33
-rw-r--r--src/test/ui/type-alias-impl-trait/self-referential.stderr33
-rw-r--r--src/test/ui/type/type-check-defaults.stderr11
-rw-r--r--src/test/ui/typeck/issue-81293.stderr13
-rw-r--r--src/test/ui/typeck/path-to-method-sugg-unresolved-expr.rs4
-rw-r--r--src/test/ui/typeck/path-to-method-sugg-unresolved-expr.stderr9
-rw-r--r--src/test/ui/ufcs/ufcs-qpath-self-mismatch.stderr22
-rw-r--r--src/tools/collect-license-metadata/Cargo.toml10
-rw-r--r--src/tools/collect-license-metadata/src/licenses.rs65
-rw-r--r--src/tools/collect-license-metadata/src/main.rs30
-rw-r--r--src/tools/collect-license-metadata/src/path_tree.rs294
-rw-r--r--src/tools/collect-license-metadata/src/reuse.rs49
-rw-r--r--src/tools/compiletest/src/header.rs8
-rw-r--r--src/tools/generate-copyright/Cargo.toml11
-rw-r--r--src/tools/generate-copyright/src/main.rs94
-rw-r--r--src/tools/miri/rust-version2
-rw-r--r--src/tools/miri/src/borrow_tracker/stacked_borrows/mod.rs23
-rw-r--r--src/tools/miri/tests/fail/stacked_borrows/notunpin_dereferenceable_fakeread.rs17
-rw-r--r--src/tools/miri/tests/fail/stacked_borrows/notunpin_dereferenceable_fakeread.stderr28
-rw-r--r--src/tools/miri/tests/pass/stacked-borrows/future-self-referential.rs102
-rw-r--r--triagebot.toml12
230 files changed, 3269 insertions, 1763 deletions
diff --git a/Cargo.lock b/Cargo.lock
index dae79e5bc26..150a70341f5 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -581,6 +581,7 @@ dependencies = [
"libc",
"num-integer",
"num-traits",
+ "serde",
"time",
"winapi",
]
@@ -731,6 +732,16 @@ dependencies = [
]
[[package]]
+name = "collect-license-metadata"
+version = "0.1.0"
+dependencies = [
+ "anyhow",
+ "serde",
+ "serde_json",
+ "spdx-rs",
+]
+
+[[package]]
name = "color-eyre"
version = "0.6.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -1553,6 +1564,15 @@ dependencies = [
]
[[package]]
+name = "generate-copyright"
+version = "0.1.0"
+dependencies = [
+ "anyhow",
+ "serde",
+ "serde_json",
+]
+
+[[package]]
name = "generic-array"
version = "0.14.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -2085,9 +2105,9 @@ checksum = "830d08ce1d1d941e6b30645f1a0eb5643013d835ce3779a5fc208261dbe10f55"
[[package]]
name = "libc"
-version = "0.2.135"
+version = "0.2.138"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "68783febc7782c6c5cb401fbda4de5a9898be1762314da0bb2c10ced61f18b0c"
+checksum = "db6d7e329c562c5dfab7a46a2afabc8b987ab9a4834c9d1ca04dc54c1546cef8"
dependencies = [
"rustc-std-workspace-core",
]
@@ -4865,6 +4885,35 @@ dependencies = [
]
[[package]]
+name = "spdx-expression"
+version = "0.5.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "53d7ac03c67c572d85049d6db815e20a4a19b41b3d5cca732ac582342021ad77"
+dependencies = [
+ "nom",
+ "serde",
+ "thiserror",
+ "tracing",
+]
+
+[[package]]
+name = "spdx-rs"
+version = "0.5.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b3c02f6eb7e7b4100c272f685a9ccaccaab302324e8c7ec3e2ee72340fb29ff3"
+dependencies = [
+ "chrono",
+ "log",
+ "nom",
+ "serde",
+ "spdx-expression",
+ "strum",
+ "strum_macros",
+ "thiserror",
+ "uuid",
+]
+
+[[package]]
name = "stable_deref_trait"
version = "1.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -4968,6 +5017,25 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623"
[[package]]
+name = "strum"
+version = "0.24.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "063e6045c0e62079840579a7e47a355ae92f60eb74daaf156fb1e84ba164e63f"
+
+[[package]]
+name = "strum_macros"
+version = "0.24.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1e385be0d24f186b4ce2f9982191e7101bb737312ad61c1f2f984f34bcf85d59"
+dependencies = [
+ "heck",
+ "proc-macro2",
+ "quote",
+ "rustversion",
+ "syn",
+]
+
+[[package]]
name = "syn"
version = "1.0.102"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -5597,6 +5665,15 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8772a4ccbb4e89959023bc5b7cb8623a795caa7092d99f3aa9501b9484d4557d"
[[package]]
+name = "uuid"
+version = "0.8.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "bc5cf98d8186244414c848017f0e2676b3fcb46807f6668a97dfe67359a3c4b7"
+dependencies = [
+ "getrandom 0.2.0",
+]
+
+[[package]]
name = "valuable"
version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
diff --git a/Cargo.toml b/Cargo.toml
index 13a98eedde8..000c10a1f90 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -39,6 +39,8 @@ members = [
"src/tools/bump-stage0",
"src/tools/replace-version-placeholder",
"src/tools/lld-wrapper",
+ "src/tools/collect-license-metadata",
+ "src/tools/generate-copyright",
]
exclude = [
diff --git a/compiler/rustc_abi/src/lib.rs b/compiler/rustc_abi/src/lib.rs
index 85693259cd0..e14c9ea9a5d 100644
--- a/compiler/rustc_abi/src/lib.rs
+++ b/compiler/rustc_abi/src/lib.rs
@@ -9,6 +9,8 @@ use std::ops::{Add, AddAssign, Mul, RangeInclusive, Sub};
use std::str::FromStr;
use bitflags::bitflags;
+#[cfg(feature = "nightly")]
+use rustc_data_structures::stable_hasher::StableOrd;
use rustc_index::vec::{Idx, IndexVec};
#[cfg(feature = "nightly")]
use rustc_macros::HashStable_Generic;
@@ -403,6 +405,11 @@ pub struct Size {
raw: u64,
}
+// Safety: Ord is implement as just comparing numerical values and numerical values
+// are not changed by (de-)serialization.
+#[cfg(feature = "nightly")]
+unsafe impl StableOrd for Size {}
+
// This is debug-printed a lot in larger structs, don't waste too much space there
impl fmt::Debug for Size {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
diff --git a/compiler/rustc_ast_lowering/src/expr.rs b/compiler/rustc_ast_lowering/src/expr.rs
index 4260805f1dd..9974ebff311 100644
--- a/compiler/rustc_ast_lowering/src/expr.rs
+++ b/compiler/rustc_ast_lowering/src/expr.rs
@@ -16,7 +16,7 @@ use rustc_hir::def::Res;
use rustc_hir::definitions::DefPathData;
use rustc_session::errors::report_lit_error;
use rustc_span::source_map::{respan, DesugaringKind, Span, Spanned};
-use rustc_span::symbol::{sym, Ident};
+use rustc_span::symbol::{kw, sym, Ident};
use rustc_span::DUMMY_SP;
use thin_vec::thin_vec;
@@ -147,6 +147,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
),
ExprKind::Async(capture_clause, closure_node_id, block) => self.make_async_expr(
*capture_clause,
+ None,
*closure_node_id,
None,
e.span,
@@ -584,6 +585,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
pub(super) fn make_async_expr(
&mut self,
capture_clause: CaptureBy,
+ outer_hir_id: Option<hir::HirId>,
closure_node_id: NodeId,
ret_ty: Option<hir::FnRetTy<'hir>>,
span: Span,
@@ -592,14 +594,38 @@ impl<'hir> LoweringContext<'_, 'hir> {
) -> hir::ExprKind<'hir> {
let output = ret_ty.unwrap_or_else(|| hir::FnRetTy::DefaultReturn(self.lower_span(span)));
- // Resume argument type: `ResumeTy`
- let unstable_span =
- self.mark_span_with_reason(DesugaringKind::Async, span, self.allow_gen_future.clone());
- let resume_ty = hir::QPath::LangItem(hir::LangItem::ResumeTy, unstable_span, None);
+ // Resume argument type, which should be `&mut Context<'_>`.
+ // NOTE: Using the `'static` lifetime here is technically cheating.
+ // The `Future::poll` argument really is `&'a mut Context<'b>`, but we cannot
+ // express the fact that we are not storing it across yield-points yet,
+ // and we would thus run into lifetime errors.
+ // See <https://github.com/rust-lang/rust/issues/68923>.
+ // Our lowering makes sure we are not mis-using the `_task_context` input type
+ // in the sense that we are indeed not using it across yield points. We
+ // get a fresh `&mut Context` for each resume / call of `Future::poll`.
+ // This "cheating" was previously done with a `ResumeTy` that contained a raw
+ // pointer, and a `get_context` accessor that pulled the `Context` lifetimes
+ // out of thin air.
+ let context_lifetime_ident = Ident::with_dummy_span(kw::StaticLifetime);
+ let context_lifetime = self.arena.alloc(hir::Lifetime {
+ hir_id: self.next_id(),
+ ident: context_lifetime_ident,
+ res: hir::LifetimeName::Static,
+ });
+ let context_path =
+ hir::QPath::LangItem(hir::LangItem::Context, self.lower_span(span), None);
+ let context_ty = hir::MutTy {
+ ty: self.arena.alloc(hir::Ty {
+ hir_id: self.next_id(),
+ kind: hir::TyKind::Path(context_path),
+ span: self.lower_span(span),
+ }),
+ mutbl: hir::Mutability::Mut,
+ };
let input_ty = hir::Ty {
hir_id: self.next_id(),
- kind: hir::TyKind::Path(resume_ty),
- span: unstable_span,
+ kind: hir::TyKind::Rptr(context_lifetime, context_ty),
+ span: self.lower_span(span),
};
// The closure/generator `FnDecl` takes a single (resume) argument of type `input_ty`.
@@ -651,18 +677,17 @@ impl<'hir> LoweringContext<'_, 'hir> {
hir::ExprKind::Closure(c)
};
- let parent_has_track_caller = self
- .attrs
- .values()
- .find(|attrs| attrs.into_iter().find(|attr| attr.has_name(sym::track_caller)).is_some())
- .is_some();
+
+ let track_caller = outer_hir_id
+ .and_then(|id| self.attrs.get(&id.local_id))
+ .map_or(false, |attrs| attrs.into_iter().any(|attr| attr.has_name(sym::track_caller)));
+
+ let hir_id = self.lower_node_id(closure_node_id);
let unstable_span =
self.mark_span_with_reason(DesugaringKind::Async, span, self.allow_gen_future.clone());
-
- let hir_id = if parent_has_track_caller {
- let generator_hir_id = self.lower_node_id(closure_node_id);
+ if track_caller {
self.lower_attrs(
- generator_hir_id,
+ hir_id,
&[Attribute {
kind: AttrKind::Normal(ptr::P(NormalAttr {
item: AttrItem {
@@ -677,10 +702,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
span: unstable_span,
}],
);
- generator_hir_id
- } else {
- self.lower_node_id(closure_node_id)
- };
+ }
let generator = hir::Expr { hir_id, kind: generator_kind, span: self.lower_span(span) };
@@ -710,7 +732,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
/// mut __awaitee => loop {
/// match unsafe { ::std::future::Future::poll(
/// <::std::pin::Pin>::new_unchecked(&mut __awaitee),
- /// ::std::future::get_context(task_context),
+ /// task_context,
/// ) } {
/// ::std::task::Poll::Ready(result) => break result,
/// ::std::task::Poll::Pending => {}
@@ -751,7 +773,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
// unsafe {
// ::std::future::Future::poll(
// ::std::pin::Pin::new_unchecked(&mut __awaitee),
- // ::std::future::get_context(task_context),
+ // task_context,
// )
// }
let poll_expr = {
@@ -769,16 +791,10 @@ impl<'hir> LoweringContext<'_, 'hir> {
arena_vec![self; ref_mut_awaitee],
Some(expr_hir_id),
);
- let get_context = self.expr_call_lang_item_fn_mut(
- gen_future_span,
- hir::LangItem::GetContext,
- arena_vec![self; task_context],
- Some(expr_hir_id),
- );
let call = self.expr_call_lang_item_fn(
span,
hir::LangItem::FuturePoll,
- arena_vec![self; new_unchecked, get_context],
+ arena_vec![self; new_unchecked, task_context],
Some(expr_hir_id),
);
self.arena.alloc(self.expr_unsafe(call))
@@ -1019,6 +1035,9 @@ impl<'hir> LoweringContext<'_, 'hir> {
let async_body = this.make_async_expr(
capture_clause,
+ // FIXME(nbdd0121): This should also use a proper HIR id so `#[track_caller]`
+ // can be applied on async closures as well.
+ None,
inner_closure_id,
async_ret_ty,
body.span,
diff --git a/compiler/rustc_ast_lowering/src/item.rs b/compiler/rustc_ast_lowering/src/item.rs
index f6275433fc5..9eda48e9329 100644
--- a/compiler/rustc_ast_lowering/src/item.rs
+++ b/compiler/rustc_ast_lowering/src/item.rs
@@ -253,8 +253,13 @@ impl<'hir> LoweringContext<'_, 'hir> {
// only cares about the input argument patterns in the function
// declaration (decl), not the return types.
let asyncness = header.asyncness;
- let body_id =
- this.lower_maybe_async_body(span, &decl, asyncness, body.as_deref());
+ let body_id = this.lower_maybe_async_body(
+ span,
+ hir_id,
+ &decl,
+ asyncness,
+ body.as_deref(),
+ );
let mut itctx = ImplTraitContext::Universal;
let (generics, decl) = this.lower_generics(generics, id, &mut itctx, |this| {
@@ -701,6 +706,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
fn lower_trait_item(&mut self, i: &AssocItem) -> &'hir hir::TraitItem<'hir> {
let hir_id = self.lower_node_id(i.id);
+ self.lower_attrs(hir_id, &i.attrs);
let trait_item_def_id = hir_id.expect_owner();
let (generics, kind, has_default) = match &i.kind {
@@ -724,7 +730,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
AssocItemKind::Fn(box Fn { sig, generics, body: Some(body), .. }) => {
let asyncness = sig.header.asyncness;
let body_id =
- self.lower_maybe_async_body(i.span, &sig.decl, asyncness, Some(&body));
+ self.lower_maybe_async_body(i.span, hir_id, &sig.decl, asyncness, Some(&body));
let (generics, sig) = self.lower_method_sig(
generics,
sig,
@@ -759,7 +765,6 @@ impl<'hir> LoweringContext<'_, 'hir> {
AssocItemKind::MacCall(..) => panic!("macro item shouldn't exist at this point"),
};
- self.lower_attrs(hir_id, &i.attrs);
let item = hir::TraitItem {
owner_id: trait_item_def_id,
ident: self.lower_ident(i.ident),
@@ -798,6 +803,8 @@ impl<'hir> LoweringContext<'_, 'hir> {
// Since `default impl` is not yet implemented, this is always true in impls.
let has_value = true;
let (defaultness, _) = self.lower_defaultness(i.kind.defaultness(), has_value);
+ let hir_id = self.lower_node_id(i.id);
+ self.lower_attrs(hir_id, &i.attrs);
let (generics, kind) = match &i.kind {
AssocItemKind::Const(_, ty, expr) => {
@@ -810,8 +817,13 @@ impl<'hir> LoweringContext<'_, 'hir> {
AssocItemKind::Fn(box Fn { sig, generics, body, .. }) => {
self.current_item = Some(i.span);
let asyncness = sig.header.asyncness;
- let body_id =
- self.lower_maybe_async_body(i.span, &sig.decl, asyncness, body.as_deref());
+ let body_id = self.lower_maybe_async_body(
+ i.span,
+ hir_id,
+ &sig.decl,
+ asyncness,
+ body.as_deref(),
+ );
let (generics, sig) = self.lower_method_sig(
generics,
sig,
@@ -844,8 +856,6 @@ impl<'hir> LoweringContext<'_, 'hir> {
AssocItemKind::MacCall(..) => panic!("`TyMac` should have been expanded by now"),
};
- let hir_id = self.lower_node_id(i.id);
- self.lower_attrs(hir_id, &i.attrs);
let item = hir::ImplItem {
owner_id: hir_id.expect_owner(),
ident: self.lower_ident(i.ident),
@@ -978,6 +988,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
fn lower_maybe_async_body(
&mut self,
span: Span,
+ fn_id: hir::HirId,
decl: &FnDecl,
asyncness: Async,
body: Option<&Block>,
@@ -1128,6 +1139,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
let async_expr = this.make_async_expr(
CaptureBy::Value,
+ Some(fn_id),
closure_id,
None,
body.span,
diff --git a/compiler/rustc_ast_pretty/src/pprust/state/item.rs b/compiler/rustc_ast_pretty/src/pprust/state/item.rs
index e68a7b3f202..5b6a07721e2 100644
--- a/compiler/rustc_ast_pretty/src/pprust/state/item.rs
+++ b/compiler/rustc_ast_pretty/src/pprust/state/item.rs
@@ -348,21 +348,10 @@ impl<'a> State<'a> {
self.head(visibility_qualified(&item.vis, "trait"));
self.print_ident(item.ident);
self.print_generic_params(&generics.params);
- let mut real_bounds = Vec::with_capacity(bounds.len());
- // FIXME(durka) this seems to be some quite outdated syntax
- for b in bounds.iter() {
- if let GenericBound::Trait(ptr, ast::TraitBoundModifier::Maybe) = b {
- self.space();
- self.word_space("for ?");
- self.print_trait_ref(&ptr.trait_ref);
- } else {
- real_bounds.push(b.clone());
- }
- }
self.nbsp();
- if !real_bounds.is_empty() {
+ if !bounds.is_empty() {
self.word_nbsp("=");
- self.print_type_bounds(&real_bounds);
+ self.print_type_bounds(&bounds);
}
self.print_where_clause(&generics.where_clause);
self.word(";");
diff --git a/compiler/rustc_borrowck/src/type_check/canonical.rs b/compiler/rustc_borrowck/src/type_check/canonical.rs
index 1aad6738bba..3617bf58be9 100644
--- a/compiler/rustc_borrowck/src/type_check/canonical.rs
+++ b/compiler/rustc_borrowck/src/type_check/canonical.rs
@@ -121,9 +121,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
pub(super) fn prove_predicates(
&mut self,
- predicates: impl IntoIterator<
- Item = impl ToPredicate<'tcx, ty::Predicate<'tcx>> + std::fmt::Debug,
- >,
+ predicates: impl IntoIterator<Item = impl ToPredicate<'tcx> + std::fmt::Debug>,
locations: Locations,
category: ConstraintCategory<'tcx>,
) {
@@ -135,7 +133,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
#[instrument(skip(self), level = "debug")]
pub(super) fn prove_predicate(
&mut self,
- predicate: impl ToPredicate<'tcx, ty::Predicate<'tcx>> + std::fmt::Debug,
+ predicate: impl ToPredicate<'tcx> + std::fmt::Debug,
locations: Locations,
category: ConstraintCategory<'tcx>,
) {
diff --git a/compiler/rustc_const_eval/src/const_eval/machine.rs b/compiler/rustc_const_eval/src/const_eval/machine.rs
index 04e68b96455..3dfded2d930 100644
--- a/compiler/rustc_const_eval/src/const_eval/machine.rs
+++ b/compiler/rustc_const_eval/src/const_eval/machine.rs
@@ -240,7 +240,7 @@ impl<'mir, 'tcx: 'mir> CompileTimeEvalContext<'mir, 'tcx> {
let align = ImmTy::from_uint(target_align, args[1].layout).into();
let fn_abi = self.fn_abi_of_instance(instance, ty::List::empty())?;
- // We replace the entire entire function call with a "tail call".
+ // We replace the entire function call with a "tail call".
// Note that this happens before the frame of the original function
// is pushed on the stack.
self.eval_fn_call(
diff --git a/compiler/rustc_const_eval/src/interpret/eval_context.rs b/compiler/rustc_const_eval/src/interpret/eval_context.rs
index 79450fccfc4..e17d3e516a6 100644
--- a/compiler/rustc_const_eval/src/interpret/eval_context.rs
+++ b/compiler/rustc_const_eval/src/interpret/eval_context.rs
@@ -676,6 +676,10 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
return_to_block: StackPopCleanup,
) -> InterpResult<'tcx> {
trace!("body: {:#?}", body);
+ // Clobber previous return place contents, nobody is supposed to be able to see them any more
+ // This also checks dereferenceable, but not align. We rely on all constructed places being
+ // sufficiently aligned (in particular we rely on `deref_operand` checking alignment).
+ self.write_uninit(return_place)?;
// first push a stack frame so we have access to the local substs
let pre_frame = Frame {
body,
diff --git a/compiler/rustc_data_structures/src/fingerprint.rs b/compiler/rustc_data_structures/src/fingerprint.rs
index a39178016ce..d98f4e43fe8 100644
--- a/compiler/rustc_data_structures/src/fingerprint.rs
+++ b/compiler/rustc_data_structures/src/fingerprint.rs
@@ -140,7 +140,7 @@ impl stable_hasher::StableHasherResult for Fingerprint {
}
}
-impl_stable_hash_via_hash!(Fingerprint);
+impl_stable_traits_for_trivial_type!(Fingerprint);
impl<E: Encoder> Encodable<E> for Fingerprint {
#[inline]
diff --git a/compiler/rustc_data_structures/src/intern.rs b/compiler/rustc_data_structures/src/intern.rs
index 76a1288e6d3..ba94f3776eb 100644
--- a/compiler/rustc_data_structures/src/intern.rs
+++ b/compiler/rustc_data_structures/src/intern.rs
@@ -4,8 +4,6 @@ use std::hash::{Hash, Hasher};
use std::ops::Deref;
use std::ptr;
-use crate::fingerprint::Fingerprint;
-
mod private {
#[derive(Clone, Copy, Debug)]
pub struct PrivateZst;
@@ -110,86 +108,5 @@ where
}
}
-/// A helper type that you can wrap round your own type in order to automatically
-/// cache the stable hash on creation and not recompute it whenever the stable hash
-/// of the type is computed.
-/// This is only done in incremental mode. You can also opt out of caching by using
-/// StableHash::ZERO for the hash, in which case the hash gets computed each time.
-/// This is useful if you have values that you intern but never (can?) use for stable
-/// hashing.
-#[derive(Copy, Clone)]
-pub struct WithStableHash<T> {
- pub internee: T,
- pub stable_hash: Fingerprint,
-}
-
-impl<T: PartialEq> PartialEq for WithStableHash<T> {
- #[inline]
- fn eq(&self, other: &Self) -> bool {
- self.internee.eq(&other.internee)
- }
-}
-
-impl<T: Eq> Eq for WithStableHash<T> {}
-
-impl<T: Ord> PartialOrd for WithStableHash<T> {
- fn partial_cmp(&self, other: &WithStableHash<T>) -> Option<Ordering> {
- Some(self.internee.cmp(&other.internee))
- }
-}
-
-impl<T: Ord> Ord for WithStableHash<T> {
- fn cmp(&self, other: &WithStableHash<T>) -> Ordering {
- self.internee.cmp(&other.internee)
- }
-}
-
-impl<T> Deref for WithStableHash<T> {
- type Target = T;
-
- #[inline]
- fn deref(&self) -> &T {
- &self.internee
- }
-}
-
-impl<T: Hash> Hash for WithStableHash<T> {
- #[inline]
- fn hash<H: Hasher>(&self, s: &mut H) {
- if self.stable_hash != Fingerprint::ZERO {
- self.stable_hash.hash(s)
- } else {
- self.internee.hash(s)
- }
- }
-}
-
-impl<T: HashStable<CTX>, CTX> HashStable<CTX> for WithStableHash<T> {
- fn hash_stable(&self, hcx: &mut CTX, hasher: &mut StableHasher) {
- if self.stable_hash == Fingerprint::ZERO || cfg!(debug_assertions) {
- // No cached hash available. This can only mean that incremental is disabled.
- // We don't cache stable hashes in non-incremental mode, because they are used
- // so rarely that the performance actually suffers.
-
- // We need to build the hash as if we cached it and then hash that hash, as
- // otherwise the hashes will differ between cached and non-cached mode.
- let stable_hash: Fingerprint = {
- let mut hasher = StableHasher::new();
- self.internee.hash_stable(hcx, &mut hasher);
- hasher.finish()
- };
- if cfg!(debug_assertions) && self.stable_hash != Fingerprint::ZERO {
- assert_eq!(
- stable_hash, self.stable_hash,
- "cached stable hash does not match freshly computed stable hash"
- );
- }
- stable_hash.hash_stable(hcx, hasher);
- } else {
- self.stable_hash.hash_stable(hcx, hasher);
- }
- }
-}
-
#[cfg(test)]
mod tests;
diff --git a/compiler/rustc_data_structures/src/sorted_map.rs b/compiler/rustc_data_structures/src/sorted_map.rs
index d607a5c8314..d13313dfd0e 100644
--- a/compiler/rustc_data_structures/src/sorted_map.rs
+++ b/compiler/rustc_data_structures/src/sorted_map.rs
@@ -1,4 +1,4 @@
-use crate::stable_hasher::{HashStable, StableHasher};
+use crate::stable_hasher::{HashStable, StableHasher, StableOrd};
use std::borrow::Borrow;
use std::cmp::Ordering;
use std::iter::FromIterator;
@@ -308,7 +308,7 @@ impl<K: Ord, V> FromIterator<(K, V)> for SortedMap<K, V> {
}
}
-impl<K: HashStable<CTX>, V: HashStable<CTX>, CTX> HashStable<CTX> for SortedMap<K, V> {
+impl<K: HashStable<CTX> + StableOrd, V: HashStable<CTX>, CTX> HashStable<CTX> for SortedMap<K, V> {
#[inline]
fn hash_stable(&self, ctx: &mut CTX, hasher: &mut StableHasher) {
self.data.hash_stable(ctx, hasher);
diff --git a/compiler/rustc_data_structures/src/sorted_map/index_map.rs b/compiler/rustc_data_structures/src/sorted_map/index_map.rs
index 0ec32dc4307..c2f0ae32896 100644
--- a/compiler/rustc_data_structures/src/sorted_map/index_map.rs
+++ b/compiler/rustc_data_structures/src/sorted_map/index_map.rs
@@ -120,13 +120,20 @@ where
self.items.hash(hasher)
}
}
+
impl<I: Idx, K, V, C> HashStable<C> for SortedIndexMultiMap<I, K, V>
where
K: HashStable<C>,
V: HashStable<C>,
{
fn hash_stable(&self, ctx: &mut C, hasher: &mut StableHasher) {
- self.items.hash_stable(ctx, hasher)
+ let SortedIndexMultiMap {
+ items,
+ // We can ignore this field because it is not observable from the outside.
+ idx_sorted_by_item_key: _,
+ } = self;
+
+ items.hash_stable(ctx, hasher)
}
}
diff --git a/compiler/rustc_data_structures/src/stable_hasher.rs b/compiler/rustc_data_structures/src/stable_hasher.rs
index cd392a7b678..1a728f82f00 100644
--- a/compiler/rustc_data_structures/src/stable_hasher.rs
+++ b/compiler/rustc_data_structures/src/stable_hasher.rs
@@ -219,7 +219,35 @@ pub trait ToStableHashKey<HCX> {
fn to_stable_hash_key(&self, hcx: &HCX) -> Self::KeyType;
}
-/// Implement HashStable by just calling `Hash::hash()`.
+/// Trait for marking a type as having a sort order that is
+/// stable across compilation session boundaries. More formally:
+///
+/// ```txt
+/// Ord::cmp(a1, b1) == Ord:cmp(a2, b2)
+/// where a2 = decode(encode(a1, context1), context2)
+/// b2 = decode(encode(b1, context1), context2)
+/// ```
+///
+/// i.e. the result of `Ord::cmp` is not influenced by encoding
+/// the values in one session and then decoding them in another
+/// session.
+///
+/// This is trivially true for types where encoding and decoding
+/// don't change the bytes of the values that are used during
+/// comparison and comparison only depends on these bytes (as
+/// opposed to some non-local state). Examples are u32, String,
+/// Path, etc.
+///
+/// But it is not true for:
+/// - `*const T` and `*mut T` because the values of these pointers
+/// will change between sessions.
+/// - `DefIndex`, `CrateNum`, `LocalDefId`, because their concrete
+/// values depend on state that might be different between
+/// compilation sessions.
+pub unsafe trait StableOrd: Ord {}
+
+/// Implement HashStable by just calling `Hash::hash()`. Also implement `StableOrd` for the type since
+/// that has the same requirements.
///
/// **WARNING** This is only valid for types that *really* don't need any context for fingerprinting.
/// But it is easy to misuse this macro (see [#96013](https://github.com/rust-lang/rust/issues/96013)
@@ -227,7 +255,7 @@ pub trait ToStableHashKey<HCX> {
/// here in this module.
///
/// Use `#[derive(HashStable_Generic)]` instead.
-macro_rules! impl_stable_hash_via_hash {
+macro_rules! impl_stable_traits_for_trivial_type {
($t:ty) => {
impl<CTX> $crate::stable_hasher::HashStable<CTX> for $t {
#[inline]
@@ -235,26 +263,28 @@ macro_rules! impl_stable_hash_via_hash {
::std::hash::Hash::hash(self, hasher);
}
}
+
+ unsafe impl $crate::stable_hasher::StableOrd for $t {}
};
}
-impl_stable_hash_via_hash!(i8);
-impl_stable_hash_via_hash!(i16);
-impl_stable_hash_via_hash!(i32);
-impl_stable_hash_via_hash!(i64);
-impl_stable_hash_via_hash!(isize);
+impl_stable_traits_for_trivial_type!(i8);
+impl_stable_traits_for_trivial_type!(i16);
+impl_stable_traits_for_trivial_type!(i32);
+impl_stable_traits_for_trivial_type!(i64);
+impl_stable_traits_for_trivial_type!(isize);
-impl_stable_hash_via_hash!(u8);
-impl_stable_hash_via_hash!(u16);
-impl_stable_hash_via_hash!(u32);
-impl_stable_hash_via_hash!(u64);
-impl_stable_hash_via_hash!(usize);
+impl_stable_traits_for_trivial_type!(u8);
+impl_stable_traits_for_trivial_type!(u16);
+impl_stable_traits_for_trivial_type!(u32);
+impl_stable_traits_for_trivial_type!(u64);
+impl_stable_traits_for_trivial_type!(usize);
-impl_stable_hash_via_hash!(u128);
-impl_stable_hash_via_hash!(i128);
+impl_stable_traits_for_trivial_type!(u128);
+impl_stable_traits_for_trivial_type!(i128);
-impl_stable_hash_via_hash!(char);
-impl_stable_hash_via_hash!(());
+impl_stable_traits_for_trivial_type!(char);
+impl_stable_traits_for_trivial_type!(());
impl<CTX> HashStable<CTX> for ! {
fn hash_stable(&self, _ctx: &mut CTX, _hasher: &mut StableHasher) {
@@ -444,6 +474,10 @@ impl<CTX> HashStable<CTX> for String {
}
}
+// Safety: String comparison only depends on their contents and the
+// contents are not changed by (de-)serialization.
+unsafe impl StableOrd for String {}
+
impl<HCX> ToStableHashKey<HCX> for String {
type KeyType = String;
#[inline]
@@ -459,6 +493,9 @@ impl<CTX> HashStable<CTX> for bool {
}
}
+// Safety: sort order of bools is not changed by (de-)serialization.
+unsafe impl StableOrd for bool {}
+
impl<T, CTX> HashStable<CTX> for Option<T>
where
T: HashStable<CTX>,
@@ -474,6 +511,9 @@ where
}
}
+// Safety: the Option wrapper does not add instability to comparison.
+unsafe impl<T: StableOrd> StableOrd for Option<T> {}
+
impl<T1, T2, CTX> HashStable<CTX> for Result<T1, T2>
where
T1: HashStable<CTX>,
@@ -550,8 +590,8 @@ where
}
}
-impl_stable_hash_via_hash!(::std::path::Path);
-impl_stable_hash_via_hash!(::std::path::PathBuf);
+impl_stable_traits_for_trivial_type!(::std::path::Path);
+impl_stable_traits_for_trivial_type!(::std::path::PathBuf);
impl<K, V, R, HCX> HashStable<HCX> for ::std::collections::HashMap<K, V, R>
where
@@ -584,27 +624,26 @@ where
impl<K, V, HCX> HashStable<HCX> for ::std::collections::BTreeMap<K, V>
where
- K: ToStableHashKey<HCX>,
+ K: HashStable<HCX> + StableOrd,
V: HashStable<HCX>,
{
fn hash_stable(&self, hcx: &mut HCX, hasher: &mut StableHasher) {
- stable_hash_reduce(hcx, hasher, self.iter(), self.len(), |hasher, hcx, (key, value)| {
- let key = key.to_stable_hash_key(hcx);
- key.hash_stable(hcx, hasher);
- value.hash_stable(hcx, hasher);
- });
+ self.len().hash_stable(hcx, hasher);
+ for entry in self.iter() {
+ entry.hash_stable(hcx, hasher);
+ }
}
}
impl<K, HCX> HashStable<HCX> for ::std::collections::BTreeSet<K>
where
- K: ToStableHashKey<HCX>,
+ K: HashStable<HCX> + StableOrd,
{
fn hash_stable(&self, hcx: &mut HCX, hasher: &mut StableHasher) {
- stable_hash_reduce(hcx, hasher, self.iter(), self.len(), |hasher, hcx, key| {
- let key = key.to_stable_hash_key(hcx);
- key.hash_stable(hcx, hasher);
- });
+ self.len().hash_stable(hcx, hasher);
+ for entry in self.iter() {
+ entry.hash_stable(hcx, hasher);
+ }
}
}
diff --git a/compiler/rustc_error_messages/locales/en-US/hir_analysis.ftl b/compiler/rustc_error_messages/locales/en-US/hir_analysis.ftl
index 0894bbcaad4..a5cb8a88819 100644
--- a/compiler/rustc_error_messages/locales/en-US/hir_analysis.ftl
+++ b/compiler/rustc_error_messages/locales/en-US/hir_analysis.ftl
@@ -17,6 +17,8 @@ hir_analysis_lifetimes_or_bounds_mismatch_on_trait =
lifetime parameters or bounds on {$item_kind} `{$ident}` do not match the trait declaration
.label = lifetimes do not match {$item_kind} in trait
.generics_label = lifetimes in impl do not match this {$item_kind} in trait
+ .where_label = this `where` clause might not match the one in the trait
+ .bounds_label = this bound might be missing in the impl
hir_analysis_drop_impl_on_wrong_item =
the `Drop` trait may only be implemented for local structs, enums, and unions
diff --git a/compiler/rustc_hir/src/hir_id.rs b/compiler/rustc_hir/src/hir_id.rs
index 93613ef27d4..060f40919f5 100644
--- a/compiler/rustc_hir/src/hir_id.rs
+++ b/compiler/rustc_hir/src/hir_id.rs
@@ -1,5 +1,5 @@
use crate::def_id::{DefId, DefIndex, LocalDefId, CRATE_DEF_ID};
-use rustc_data_structures::stable_hasher::{HashStable, StableHasher, ToStableHashKey};
+use rustc_data_structures::stable_hasher::{HashStable, StableHasher, StableOrd, ToStableHashKey};
use rustc_span::{def_id::DefPathHash, HashStableContext};
use std::fmt;
@@ -146,6 +146,10 @@ impl ItemLocalId {
pub const INVALID: ItemLocalId = ItemLocalId::MAX;
}
+// Safety: Ord is implement as just comparing the LocalItemId's numerical
+// values and these are not changed by (de-)serialization.
+unsafe impl StableOrd for ItemLocalId {}
+
/// The `HirId` corresponding to `CRATE_NODE_ID` and `CRATE_DEF_ID`.
pub const CRATE_HIR_ID: HirId =
HirId { owner: OwnerId { def_id: CRATE_DEF_ID }, local_id: ItemLocalId::from_u32(0) };
diff --git a/compiler/rustc_hir/src/lang_items.rs b/compiler/rustc_hir/src/lang_items.rs
index 038509031b1..b51257df713 100644
--- a/compiler/rustc_hir/src/lang_items.rs
+++ b/compiler/rustc_hir/src/lang_items.rs
@@ -286,10 +286,9 @@ language_item_table! {
// FIXME(swatinem): the following lang items are used for async lowering and
// should become obsolete eventually.
- ResumeTy, sym::ResumeTy, resume_ty, Target::Struct, GenericRequirement::None;
IdentityFuture, sym::identity_future, identity_future_fn, Target::Fn, GenericRequirement::None;
- GetContext, sym::get_context, get_context_fn, Target::Fn, GenericRequirement::None;
+ Context, sym::Context, context, Target::Struct, GenericRequirement::None;
FuturePoll, sym::poll, future_poll_fn, Target::Method(MethodKind::Trait { body: false }), GenericRequirement::None;
FromFrom, sym::from, from_fn, Target::Method(MethodKind::Trait { body: false }), GenericRequirement::None;
diff --git a/compiler/rustc_hir_analysis/src/astconv/mod.rs b/compiler/rustc_hir_analysis/src/astconv/mod.rs
index f204d59d005..66906b331da 100644
--- a/compiler/rustc_hir_analysis/src/astconv/mod.rs
+++ b/compiler/rustc_hir_analysis/src/astconv/mod.rs
@@ -1930,6 +1930,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
adt_substs,
);
let ty = tcx.bound_type_of(assoc_ty_did).subst(tcx, item_substs);
+ let ty = self.normalize_ty(span, ty);
return Ok((ty, DefKind::AssocTy, assoc_ty_did));
}
}
diff --git a/compiler/rustc_hir_analysis/src/check/compare_method.rs b/compiler/rustc_hir_analysis/src/check/compare_method.rs
index 82a77416a19..1d6f9b29176 100644
--- a/compiler/rustc_hir_analysis/src/check/compare_method.rs
+++ b/compiler/rustc_hir_analysis/src/check/compare_method.rs
@@ -751,17 +751,45 @@ fn check_region_bounds_on_impl_item<'tcx>(
.get_generics(impl_m.def_id.expect_local())
.expect("expected impl item to have generics or else we can't compare them")
.span;
- let generics_span = if let Some(local_def_id) = trait_m.def_id.as_local() {
- Some(
- tcx.hir()
- .get_generics(local_def_id)
- .expect("expected trait item to have generics or else we can't compare them")
- .span,
- )
- } else {
- None
- };
+ let mut generics_span = None;
+ let mut bounds_span = vec![];
+ let mut where_span = None;
+ if let Some(trait_node) = tcx.hir().get_if_local(trait_m.def_id)
+ && let Some(trait_generics) = trait_node.generics()
+ {
+ generics_span = Some(trait_generics.span);
+ // FIXME: we could potentially look at the impl's bounds to not point at bounds that
+ // *are* present in the impl.
+ for p in trait_generics.predicates {
+ if let hir::WherePredicate::BoundPredicate(pred) = p {
+ for b in pred.bounds {
+ if let hir::GenericBound::Outlives(lt) = b {
+ bounds_span.push(lt.ident.span);
+ }
+ }
+ }
+ }
+ if let Some(impl_node) = tcx.hir().get_if_local(impl_m.def_id)
+ && let Some(impl_generics) = impl_node.generics()
+ {
+ let mut impl_bounds = 0;
+ for p in impl_generics.predicates {
+ if let hir::WherePredicate::BoundPredicate(pred) = p {
+ for b in pred.bounds {
+ if let hir::GenericBound::Outlives(_) = b {
+ impl_bounds += 1;
+ }
+ }
+ }
+ }
+ if impl_bounds == bounds_span.len() {
+ bounds_span = vec![];
+ } else if impl_generics.has_where_clause_predicates {
+ where_span = Some(impl_generics.where_clause_span);
+ }
+ }
+ }
let reported = tcx
.sess
.create_err(LifetimesOrBoundsMismatchOnTrait {
@@ -769,9 +797,10 @@ fn check_region_bounds_on_impl_item<'tcx>(
item_kind: assoc_item_kind_str(impl_m),
ident: impl_m.ident(tcx),
generics_span,
+ bounds_span,
+ where_span,
})
.emit_unless(delay);
-
return Err(reported);
}
diff --git a/compiler/rustc_hir_analysis/src/errors.rs b/compiler/rustc_hir_analysis/src/errors.rs
index afbb27155a2..5156d432b5b 100644
--- a/compiler/rustc_hir_analysis/src/errors.rs
+++ b/compiler/rustc_hir_analysis/src/errors.rs
@@ -43,6 +43,10 @@ pub struct LifetimesOrBoundsMismatchOnTrait {
pub span: Span,
#[label(generics_label)]
pub generics_span: Option<Span>,
+ #[label(where_label)]
+ pub where_span: Option<Span>,
+ #[label(bounds_label)]
+ pub bounds_span: Vec<Span>,
pub item_kind: &'static str,
pub ident: Ident,
}
diff --git a/compiler/rustc_hir_analysis/src/variance/mod.rs b/compiler/rustc_hir_analysis/src/variance/mod.rs
index 9db05eedbde..8b2719c2f8a 100644
--- a/compiler/rustc_hir_analysis/src/variance/mod.rs
+++ b/compiler/rustc_hir_analysis/src/variance/mod.rs
@@ -7,7 +7,8 @@ use rustc_arena::DroplessArena;
use rustc_hir::def::DefKind;
use rustc_hir::def_id::{DefId, LocalDefId};
use rustc_middle::ty::query::Providers;
-use rustc_middle::ty::{self, CrateVariancesMap, TyCtxt, TypeSuperVisitable, TypeVisitable};
+use rustc_middle::ty::{self, CrateVariancesMap, SubstsRef, Ty, TyCtxt};
+use rustc_middle::ty::{DefIdTree, TypeSuperVisitable, TypeVisitable};
use std::ops::ControlFlow;
/// Defines the `TermsContext` basically houses an arena where we can
@@ -75,11 +76,30 @@ fn variance_of_opaque(tcx: TyCtxt<'_>, item_def_id: LocalDefId) -> &[ty::Varianc
// type Foo<'a, 'b, 'c> = impl Trait<'a> + 'b;
// ```
// we may not use `'c` in the hidden type.
- struct OpaqueTypeLifetimeCollector {
+ struct OpaqueTypeLifetimeCollector<'tcx> {
+ tcx: TyCtxt<'tcx>,
+ root_def_id: DefId,
variances: Vec<ty::Variance>,
}
- impl<'tcx> ty::TypeVisitor<'tcx> for OpaqueTypeLifetimeCollector {
+ impl<'tcx> OpaqueTypeLifetimeCollector<'tcx> {
+ #[instrument(level = "trace", skip(self), ret)]
+ fn visit_opaque(&mut self, def_id: DefId, substs: SubstsRef<'tcx>) -> ControlFlow<!> {
+ if def_id != self.root_def_id && self.tcx.is_descendant_of(def_id, self.root_def_id) {
+ let child_variances = self.tcx.variances_of(def_id);
+ for (a, v) in substs.iter().zip(child_variances) {
+ if *v != ty::Bivariant {
+ a.visit_with(self)?;
+ }
+ }
+ ControlFlow::CONTINUE
+ } else {
+ substs.visit_with(self)
+ }
+ }
+ }
+
+ impl<'tcx> ty::TypeVisitor<'tcx> for OpaqueTypeLifetimeCollector<'tcx> {
#[instrument(level = "trace", skip(self), ret)]
fn visit_region(&mut self, r: ty::Region<'tcx>) -> ControlFlow<Self::BreakTy> {
if let ty::RegionKind::ReEarlyBound(ebr) = r.kind() {
@@ -87,6 +107,19 @@ fn variance_of_opaque(tcx: TyCtxt<'_>, item_def_id: LocalDefId) -> &[ty::Varianc
}
r.super_visit_with(self)
}
+
+ #[instrument(level = "trace", skip(self), ret)]
+ fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow<Self::BreakTy> {
+ match t.kind() {
+ ty::Opaque(def_id, substs) => self.visit_opaque(*def_id, substs),
+ ty::Projection(proj)
+ if self.tcx.def_kind(proj.item_def_id) == DefKind::ImplTraitPlaceholder =>
+ {
+ self.visit_opaque(proj.item_def_id, proj.substs)
+ }
+ _ => t.super_visit_with(self),
+ }
+ }
}
// By default, RPIT are invariant wrt type and const generics, but they are bivariant wrt
@@ -111,7 +144,8 @@ fn variance_of_opaque(tcx: TyCtxt<'_>, item_def_id: LocalDefId) -> &[ty::Varianc
}
}
- let mut collector = OpaqueTypeLifetimeCollector { variances };
+ let mut collector =
+ OpaqueTypeLifetimeCollector { tcx, root_def_id: item_def_id.to_def_id(), variances };
let id_substs = ty::InternalSubsts::identity_for_item(tcx, item_def_id.to_def_id());
for pred in tcx.bound_explicit_item_bounds(item_def_id.to_def_id()).transpose_iter() {
let pred = pred.map_bound(|(pred, _)| *pred).subst(tcx, id_substs);
diff --git a/compiler/rustc_hir_pretty/src/lib.rs b/compiler/rustc_hir_pretty/src/lib.rs
index 3791b2c8661..94bab9f339d 100644
--- a/compiler/rustc_hir_pretty/src/lib.rs
+++ b/compiler/rustc_hir_pretty/src/lib.rs
@@ -695,19 +695,8 @@ impl<'a> State<'a> {
self.head("trait");
self.print_ident(item.ident);
self.print_generic_params(generics.params);
- let mut real_bounds = Vec::with_capacity(bounds.len());
- // FIXME(durka) this seems to be some quite outdated syntax
- for b in bounds {
- if let GenericBound::Trait(ptr, hir::TraitBoundModifier::Maybe) = b {
- self.space();
- self.word_space("for ?");
- self.print_trait_ref(&ptr.trait_ref);
- } else {
- real_bounds.push(b);
- }
- }
self.nbsp();
- self.print_bounds("=", real_bounds);
+ self.print_bounds("=", bounds);
self.print_where_clause(generics);
self.word(";");
self.end(); // end inner head-block
diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs
index 3078e0cbeda..8a875e05b19 100644
--- a/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs
+++ b/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs
@@ -1918,15 +1918,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
receiver: Option<&'tcx hir::Expr<'tcx>>,
args: &'tcx [hir::Expr<'tcx>],
) -> bool {
- // Do not call `fn_sig` on non-functions.
- if !matches!(
- self.tcx.def_kind(def_id),
- DefKind::Fn | DefKind::AssocFn | DefKind::Variant | DefKind::Ctor(..)
- ) {
+ let ty = self.tcx.type_of(def_id);
+ if !ty.is_fn() {
return false;
}
-
- let sig = self.tcx.fn_sig(def_id).skip_binder();
+ let sig = ty.fn_sig(self.tcx).skip_binder();
let args_referencing_param: Vec<_> = sig
.inputs()
.iter()
diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs
index 1daca464b47..4f92477b5d8 100644
--- a/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs
+++ b/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs
@@ -32,11 +32,13 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
}
pub(in super::super) fn suggest_semicolon_at_end(&self, span: Span, err: &mut Diagnostic) {
+ // This suggestion is incorrect for
+ // fn foo() -> bool { match () { () => true } || match () { () => true } }
err.span_suggestion_short(
span.shrink_to_hi(),
"consider using a semicolon here",
";",
- Applicability::MachineApplicable,
+ Applicability::MaybeIncorrect,
);
}
diff --git a/compiler/rustc_hir_typeck/src/method/suggest.rs b/compiler/rustc_hir_typeck/src/method/suggest.rs
index 9ba4ddfd5cf..db93cfab2c0 100644
--- a/compiler/rustc_hir_typeck/src/method/suggest.rs
+++ b/compiler/rustc_hir_typeck/src/method/suggest.rs
@@ -1482,15 +1482,17 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
ident_name: Symbol,
}
+ // FIXME: This really should be taking scoping, etc into account.
impl<'v> Visitor<'v> for LetVisitor<'v> {
fn visit_stmt(&mut self, ex: &'v hir::Stmt<'v>) {
- if let hir::StmtKind::Local(hir::Local { pat, init, .. }) = &ex.kind {
- if let Binding(_, _, ident, ..) = pat.kind &&
- ident.name == self.ident_name {
- self.result = *init;
- }
+ if let hir::StmtKind::Local(hir::Local { pat, init, .. }) = &ex.kind
+ && let Binding(_, _, ident, ..) = pat.kind
+ && ident.name == self.ident_name
+ {
+ self.result = *init;
+ } else {
+ hir::intravisit::walk_stmt(self, ex);
}
- hir::intravisit::walk_stmt(self, ex);
}
}
@@ -1498,9 +1500,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
visitor.visit_body(&body);
let parent = self.tcx.hir().get_parent_node(seg1.hir_id);
- if let Some(Node::Expr(call_expr)) = self.tcx.hir().find(parent) &&
- let Some(expr) = visitor.result {
- let self_ty = self.node_ty(expr.hir_id);
+ if let Some(Node::Expr(call_expr)) = self.tcx.hir().find(parent)
+ && let Some(expr) = visitor.result
+ && let Some(self_ty) = self.node_ty_opt(expr.hir_id)
+ {
let probe = self.lookup_probe(
seg2.ident,
self_ty,
@@ -1513,7 +1516,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
sm.span_extend_while(seg1.ident.span.shrink_to_hi(), |c| c == ':').unwrap(),
"you may have meant to call an instance method",
".".to_string(),
- Applicability::MaybeIncorrect
+ Applicability::MaybeIncorrect,
);
}
}
diff --git a/compiler/rustc_infer/src/infer/error_reporting/mod.rs b/compiler/rustc_infer/src/infer/error_reporting/mod.rs
index 662136ca18d..3256ca1fb20 100644
--- a/compiler/rustc_infer/src/infer/error_reporting/mod.rs
+++ b/compiler/rustc_infer/src/infer/error_reporting/mod.rs
@@ -341,7 +341,15 @@ pub fn unexpected_hidden_region_diagnostic<'tcx>(
impl<'tcx> InferCtxt<'tcx> {
pub fn get_impl_future_output_ty(&self, ty: Ty<'tcx>) -> Option<Ty<'tcx>> {
- let ty::Opaque(def_id, substs) = *ty.kind() else { return None; };
+ let (def_id, substs) = match *ty.kind() {
+ ty::Opaque(def_id, substs) => (def_id, substs),
+ ty::Projection(data)
+ if self.tcx.def_kind(data.item_def_id) == DefKind::ImplTraitPlaceholder =>
+ {
+ (data.item_def_id, data.substs)
+ }
+ _ => return None,
+ };
let future_trait = self.tcx.require_lang_item(LangItem::Future, None);
let item_def_id = self.tcx.associated_item_def_ids(future_trait)[0];
diff --git a/compiler/rustc_interface/src/passes.rs b/compiler/rustc_interface/src/passes.rs
index 6b5b5df9e2a..f75c8669fa1 100644
--- a/compiler/rustc_interface/src/passes.rs
+++ b/compiler/rustc_interface/src/passes.rs
@@ -12,6 +12,7 @@ use rustc_ast::{self as ast, visit};
use rustc_borrowck as mir_borrowck;
use rustc_codegen_ssa::traits::CodegenBackend;
use rustc_data_structures::parallel;
+use rustc_data_structures::steal::Steal;
use rustc_data_structures::sync::{Lrc, OnceCell, WorkerLocal};
use rustc_errors::{ErrorGuaranteed, PResult};
use rustc_expand::base::{ExtCtxt, LintStoreExpand, ResolverExpand};
@@ -801,6 +802,12 @@ pub fn create_global_ctxt<'tcx>(
TcxQueries::new(local_providers, extern_providers, query_result_on_disk_cache)
});
+ let ty::ResolverOutputs {
+ definitions,
+ global_ctxt: untracked_resolutions,
+ ast_lowering: untracked_resolver_for_lowering,
+ } = resolver_outputs;
+
let gcx = sess.time("setup_global_ctxt", || {
global_ctxt.get_or_init(move || {
TyCtxt::create_global_ctxt(
@@ -808,7 +815,8 @@ pub fn create_global_ctxt<'tcx>(
lint_store,
arena,
hir_arena,
- resolver_outputs,
+ definitions,
+ untracked_resolutions,
krate,
dep_graph,
queries.on_disk_cache.as_ref().map(OnDiskCache::as_dyn),
@@ -820,7 +828,12 @@ pub fn create_global_ctxt<'tcx>(
})
});
- QueryContext { gcx }
+ let mut qcx = QueryContext { gcx };
+ qcx.enter(|tcx| {
+ tcx.feed_unit_query()
+ .resolver_for_lowering(tcx.arena.alloc(Steal::new(untracked_resolver_for_lowering)))
+ });
+ qcx
}
/// Runs the resolution, type-checking, region checking and other
@@ -965,12 +978,10 @@ fn analysis(tcx: TyCtxt<'_>, (): ()) -> Result<()> {
pub fn start_codegen<'tcx>(
codegen_backend: &dyn CodegenBackend,
tcx: TyCtxt<'tcx>,
- outputs: &OutputFilenames,
) -> Box<dyn Any> {
info!("Pre-codegen\n{:?}", tcx.debug_stats());
- let (metadata, need_metadata_module) =
- rustc_metadata::fs::encode_and_write_metadata(tcx, outputs);
+ let (metadata, need_metadata_module) = rustc_metadata::fs::encode_and_write_metadata(tcx);
let codegen = tcx.sess.time("codegen_crate", move || {
codegen_backend.codegen_crate(tcx, metadata, need_metadata_module)
@@ -986,7 +997,7 @@ pub fn start_codegen<'tcx>(
info!("Post-codegen\n{:?}", tcx.debug_stats());
if tcx.sess.opts.output_types.contains_key(&OutputType::Mir) {
- if let Err(error) = rustc_mir_transform::dump_mir::emit_mir(tcx, outputs) {
+ if let Err(error) = rustc_mir_transform::dump_mir::emit_mir(tcx) {
tcx.sess.emit_err(CantEmitMIR { error });
tcx.sess.abort_if_errors();
}
diff --git a/compiler/rustc_interface/src/queries.rs b/compiler/rustc_interface/src/queries.rs
index fc0b11183f7..f5ddd647b24 100644
--- a/compiler/rustc_interface/src/queries.rs
+++ b/compiler/rustc_interface/src/queries.rs
@@ -20,6 +20,7 @@ use rustc_span::symbol::sym;
use std::any::Any;
use std::cell::{Ref, RefCell, RefMut};
use std::rc::Rc;
+use std::sync::Arc;
/// Represent the result of a query.
///
@@ -214,7 +215,7 @@ impl<'tcx> Queries<'tcx> {
pub fn global_ctxt(&'tcx self) -> Result<&Query<QueryContext<'tcx>>> {
self.global_ctxt.compute(|| {
let crate_name = self.crate_name()?.peek().clone();
- let outputs = self.prepare_outputs()?.peek().clone();
+ let outputs = self.prepare_outputs()?.take();
let dep_graph = self.dep_graph()?.peek().clone();
let (krate, resolver, lint_store) = self.expansion()?.take();
Ok(passes::create_global_ctxt(
@@ -235,7 +236,6 @@ impl<'tcx> Queries<'tcx> {
pub fn ongoing_codegen(&'tcx self) -> Result<&Query<Box<dyn Any>>> {
self.ongoing_codegen.compute(|| {
- let outputs = self.prepare_outputs()?;
self.global_ctxt()?.peek_mut().enter(|tcx| {
tcx.analysis(()).ok();
@@ -249,7 +249,7 @@ impl<'tcx> Queries<'tcx> {
// Hook for UI tests.
Self::check_for_rustc_errors_attr(tcx);
- Ok(passes::start_codegen(&***self.codegen_backend(), tcx, &*outputs.peek()))
+ Ok(passes::start_codegen(&***self.codegen_backend(), tcx))
})
})
}
@@ -293,8 +293,10 @@ impl<'tcx> Queries<'tcx> {
let codegen_backend = self.codegen_backend().clone();
let dep_graph = self.dep_graph()?.peek().clone();
- let prepare_outputs = self.prepare_outputs()?.take();
- let crate_hash = self.global_ctxt()?.peek_mut().enter(|tcx| tcx.crate_hash(LOCAL_CRATE));
+ let (crate_hash, prepare_outputs) = self
+ .global_ctxt()?
+ .peek_mut()
+ .enter(|tcx| (tcx.crate_hash(LOCAL_CRATE), tcx.output_filenames(()).clone()));
let ongoing_codegen = self.ongoing_codegen()?.take();
Ok(Linker {
@@ -316,7 +318,7 @@ pub struct Linker {
// compilation outputs
dep_graph: DepGraph,
- prepare_outputs: OutputFilenames,
+ prepare_outputs: Arc<OutputFilenames>,
crate_hash: Svh,
ongoing_codegen: Box<dyn Any>,
}
diff --git a/compiler/rustc_interface/src/tests.rs b/compiler/rustc_interface/src/tests.rs
index a6205f4d3a5..2b8f6557c82 100644
--- a/compiler/rustc_interface/src/tests.rs
+++ b/compiler/rustc_interface/src/tests.rs
@@ -747,6 +747,7 @@ fn test_unstable_options_tracking_hash() {
tracked!(link_only, true);
tracked!(llvm_plugins, vec![String::from("plugin_name")]);
tracked!(location_detail, LocationDetail { file: true, line: false, column: false });
+ tracked!(maximal_hir_to_mir_coverage, true);
tracked!(merge_functions, Some(MergeFunctions::Disabled));
tracked!(mir_emit_retag, true);
tracked!(mir_enable_passes, vec![("DestProp".to_string(), false)]);
diff --git a/compiler/rustc_lint/src/pass_by_value.rs b/compiler/rustc_lint/src/pass_by_value.rs
index cf1d82f4c06..0fa81b7e4e0 100644
--- a/compiler/rustc_lint/src/pass_by_value.rs
+++ b/compiler/rustc_lint/src/pass_by_value.rs
@@ -10,7 +10,7 @@ declare_tool_lint! {
/// The `rustc_pass_by_value` lint marks a type with `#[rustc_pass_by_value]` requiring it to
/// always be passed by value. This is usually used for types that are thin wrappers around
/// references, so there is no benefit to an extra layer of indirection. (Example: `Ty` which
- /// is a reference to an `Interned<TyS>`)
+ /// is a reference to an `Interned<TyKind>`)
pub rustc::PASS_BY_VALUE,
Warn,
"pass by reference of a type flagged as `#[rustc_pass_by_value]`",
diff --git a/compiler/rustc_lint/src/unused.rs b/compiler/rustc_lint/src/unused.rs
index a7836ea8e7a..b5db94f8c06 100644
--- a/compiler/rustc_lint/src/unused.rs
+++ b/compiler/rustc_lint/src/unused.rs
@@ -633,13 +633,34 @@ trait UnusedDelimLint {
left_pos: Option<BytePos>,
right_pos: Option<BytePos>,
) {
+ // If `value` has `ExprKind::Err`, unused delim lint can be broken.
+ // For example, the following code caused ICE.
+ // This is because the `ExprKind::Call` in `value` has `ExprKind::Err` as its argument
+ // and this leads to wrong spans. #104897
+ //
+ // ```
+ // fn f(){(print!(á
+ // ```
+ use rustc_ast::visit::{walk_expr, Visitor};
+ struct ErrExprVisitor {
+ has_error: bool,
+ }
+ impl<'ast> Visitor<'ast> for ErrExprVisitor {
+ fn visit_expr(&mut self, expr: &'ast ast::Expr) {
+ if let ExprKind::Err = expr.kind {
+ self.has_error = true;
+ return;
+ }
+ walk_expr(self, expr)
+ }
+ }
+ let mut visitor = ErrExprVisitor { has_error: false };
+ visitor.visit_expr(value);
+ if visitor.has_error {
+ return;
+ }
let spans = match value.kind {
ast::ExprKind::Block(ref block, None) if block.stmts.len() == 1 => {
- if let StmtKind::Expr(expr) = &block.stmts[0].kind
- && let ExprKind::Err = expr.kind
- {
- return
- }
if let Some(span) = block.stmts[0].span.find_ancestor_inside(value.span) {
Some((value.span.with_hi(span.lo()), value.span.with_lo(span.hi())))
} else {
diff --git a/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp b/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp
index 7f4d63eed8b..1a3d458c300 100644
--- a/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp
+++ b/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp
@@ -205,7 +205,12 @@ enum class LLVMRustCodeModel {
None,
};
-static Optional<CodeModel::Model> fromRust(LLVMRustCodeModel Model) {
+#if LLVM_VERSION_LT(16, 0)
+static Optional<CodeModel::Model>
+#else
+static std::optional<CodeModel::Model>
+#endif
+fromRust(LLVMRustCodeModel Model) {
switch (Model) {
case LLVMRustCodeModel::Tiny:
return CodeModel::Tiny;
@@ -638,7 +643,11 @@ LLVMRustOptimize(
LLVMSelfProfileInitializeCallbacks(PIC,LlvmSelfProfiler,BeforePassCallback,AfterPassCallback);
}
+#if LLVM_VERSION_LT(16, 0)
Optional<PGOOptions> PGOOpt;
+#else
+ std::optional<PGOOptions> PGOOpt;
+#endif
if (PGOGenPath) {
assert(!PGOUsePath && !PGOSampleUsePath);
PGOOpt = PGOOptions(PGOGenPath, "", "", PGOOptions::IRInstr,
diff --git a/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp b/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp
index 792d921c6a4..3a748f38995 100644
--- a/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp
+++ b/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp
@@ -17,7 +17,9 @@
#include "llvm/Pass.h"
#include "llvm/Bitcode/BitcodeWriter.h"
#include "llvm/Support/Signals.h"
+#if LLVM_VERSION_LT(16, 0)
#include "llvm/ADT/Optional.h"
+#endif
#include <iostream>
@@ -708,7 +710,11 @@ enum class LLVMRustChecksumKind {
SHA256,
};
+#if LLVM_VERSION_LT(16, 0)
static Optional<DIFile::ChecksumKind> fromRust(LLVMRustChecksumKind Kind) {
+#else
+static std::optional<DIFile::ChecksumKind> fromRust(LLVMRustChecksumKind Kind) {
+#endif
switch (Kind) {
case LLVMRustChecksumKind::None:
return None;
@@ -787,8 +793,18 @@ extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateFile(
const char *Filename, size_t FilenameLen,
const char *Directory, size_t DirectoryLen, LLVMRustChecksumKind CSKind,
const char *Checksum, size_t ChecksumLen) {
+
+#if LLVM_VERSION_LT(16, 0)
Optional<DIFile::ChecksumKind> llvmCSKind = fromRust(CSKind);
+#else
+ std::optional<DIFile::ChecksumKind> llvmCSKind = fromRust(CSKind);
+#endif
+
+#if LLVM_VERSION_LT(16, 0)
Optional<DIFile::ChecksumInfo<StringRef>> CSInfo{};
+#else
+ std::optional<DIFile::ChecksumInfo<StringRef>> CSInfo{};
+#endif
if (llvmCSKind)
CSInfo.emplace(*llvmCSKind, StringRef{Checksum, ChecksumLen});
return wrap(Builder->createFile(StringRef(Filename, FilenameLen),
diff --git a/compiler/rustc_macros/src/query.rs b/compiler/rustc_macros/src/query.rs
index 4047969724a..789d83a0dd0 100644
--- a/compiler/rustc_macros/src/query.rs
+++ b/compiler/rustc_macros/src/query.rs
@@ -364,10 +364,6 @@ pub fn rustc_queries(input: TokenStream) -> TokenStream {
modifiers.eval_always.is_none(),
"Query {name} cannot be both `feedable` and `eval_always`."
);
- assert!(
- modifiers.no_hash.is_none(),
- "Query {name} cannot be both `feedable` and `no_hash`."
- );
feedable_queries.extend(quote! {
#(#doc_comments)*
[#attribute_stream] fn #name(#arg) #result,
diff --git a/compiler/rustc_metadata/src/fs.rs b/compiler/rustc_metadata/src/fs.rs
index c41ae8d55cd..4fa440c7ca6 100644
--- a/compiler/rustc_metadata/src/fs.rs
+++ b/compiler/rustc_metadata/src/fs.rs
@@ -6,7 +6,7 @@ use crate::{encode_metadata, EncodedMetadata};
use rustc_data_structures::temp_dir::MaybeTempDir;
use rustc_hir::def_id::LOCAL_CRATE;
use rustc_middle::ty::TyCtxt;
-use rustc_session::config::{CrateType, OutputFilenames, OutputType};
+use rustc_session::config::{CrateType, OutputType};
use rustc_session::output::filename_for_metadata;
use rustc_session::Session;
use tempfile::Builder as TempFileBuilder;
@@ -38,10 +38,7 @@ pub fn emit_wrapper_file(
out_filename
}
-pub fn encode_and_write_metadata(
- tcx: TyCtxt<'_>,
- outputs: &OutputFilenames,
-) -> (EncodedMetadata, bool) {
+pub fn encode_and_write_metadata(tcx: TyCtxt<'_>) -> (EncodedMetadata, bool) {
#[derive(PartialEq, Eq, PartialOrd, Ord)]
enum MetadataKind {
None,
@@ -64,7 +61,8 @@ pub fn encode_and_write_metadata(
.unwrap_or(MetadataKind::None);
let crate_name = tcx.crate_name(LOCAL_CRATE);
- let out_filename = filename_for_metadata(tcx.sess, crate_name.as_str(), outputs);
+ let out_filename =
+ filename_for_metadata(tcx.sess, crate_name.as_str(), tcx.output_filenames(()));
// To avoid races with another rustc process scanning the output directory,
// we need to write the file somewhere else and atomically move it to its
// final destination, with an `fs::rename` call. In order for the rename to
diff --git a/compiler/rustc_middle/src/arena.rs b/compiler/rustc_middle/src/arena.rs
index e83106b1ee5..6de68841fe9 100644
--- a/compiler/rustc_middle/src/arena.rs
+++ b/compiler/rustc_middle/src/arena.rs
@@ -1,3 +1,5 @@
+#![allow(rustc::usage_of_ty_tykind)]
+
/// This higher-order macro declares a list of types which can be allocated by `Arena`.
///
/// Specifying the `decode` modifier will add decode impls for `&T` and `&[T]` where `T` is the type
@@ -28,6 +30,7 @@ macro_rules! arena_types {
[decode] typeck_results: rustc_middle::ty::TypeckResults<'tcx>,
[decode] borrowck_result:
rustc_middle::mir::BorrowCheckResult<'tcx>,
+ [] resolver: rustc_data_structures::steal::Steal<rustc_middle::ty::ResolverAstLowering>,
[decode] unsafety_check_result: rustc_middle::mir::UnsafetyCheckResult,
[decode] code_region: rustc_middle::mir::coverage::CodeRegion,
[] const_allocs: rustc_middle::mir::interpret::Allocation,
@@ -88,8 +91,8 @@ macro_rules! arena_types {
[] hir_id_set: rustc_hir::HirIdSet,
// Interned types
- [] tys: rustc_data_structures::intern::WithStableHash<rustc_middle::ty::TyS<'tcx>>,
- [] predicates: rustc_data_structures::intern::WithStableHash<rustc_middle::ty::PredicateS<'tcx>>,
+ [] tys: rustc_type_ir::WithCachedTypeInfo<rustc_middle::ty::TyKind<'tcx>>,
+ [] predicates: rustc_type_ir::WithCachedTypeInfo<rustc_middle::ty::PredicateKind<'tcx>>,
[] consts: rustc_middle::ty::ConstS<'tcx>,
// Note that this deliberately duplicates items in the `rustc_hir::arena`,
diff --git a/compiler/rustc_middle/src/mir/interpret/allocation.rs b/compiler/rustc_middle/src/mir/interpret/allocation.rs
index 5f911d5884a..221105ac48f 100644
--- a/compiler/rustc_middle/src/mir/interpret/allocation.rs
+++ b/compiler/rustc_middle/src/mir/interpret/allocation.rs
@@ -103,7 +103,7 @@ impl hash::Hash for Allocation {
/// Interned types generally have an `Outer` type and an `Inner` type, where
/// `Outer` is a newtype around `Interned<Inner>`, and all the operations are
/// done on `Outer`, because all occurrences are interned. E.g. `Ty` is an
-/// outer type and `TyS` is its inner type.
+/// outer type and `TyKind` is its inner type.
///
/// Here things are different because only const allocations are interned. This
/// means that both the inner type (`Allocation`) and the outer type
diff --git a/compiler/rustc_middle/src/query/mod.rs b/compiler/rustc_middle/src/query/mod.rs
index d6dea0e9f30..f2f2b22f52a 100644
--- a/compiler/rustc_middle/src/query/mod.rs
+++ b/compiler/rustc_middle/src/query/mod.rs
@@ -33,7 +33,7 @@ rustc_queries! {
}
query resolver_for_lowering(_: ()) -> &'tcx Steal<ty::ResolverAstLowering> {
- eval_always
+ feedable
no_hash
desc { "getting the resolver for lowering" }
}
diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs
index c5683a9db94..82ca1b87535 100644
--- a/compiler/rustc_middle/src/ty/context.rs
+++ b/compiler/rustc_middle/src/ty/context.rs
@@ -1,5 +1,7 @@
//! Type context book-keeping.
+#![allow(rustc::usage_of_ty_tykind)]
+
use crate::arena::Arena;
use crate::dep_graph::{DepGraph, DepKindStruct};
use crate::hir::place::Place as HirPlace;
@@ -19,15 +21,15 @@ use crate::ty::{
self, AdtDef, AdtDefData, AdtKind, Binder, BindingMode, BoundVar, CanonicalPolyFnSig,
ClosureSizeProfileData, Const, ConstS, DefIdTree, FloatTy, FloatVar, FloatVid,
GenericParamDefKind, InferTy, IntTy, IntVar, IntVid, List, ParamConst, ParamTy,
- PolyExistentialPredicate, PolyFnSig, Predicate, PredicateKind, PredicateS, ProjectionTy,
- Region, RegionKind, ReprOptions, TraitObjectVisitor, Ty, TyKind, TyS, TyVar, TyVid, TypeAndMut,
- UintTy, Visibility,
+ PolyExistentialPredicate, PolyFnSig, Predicate, PredicateKind, ProjectionTy, Region,
+ RegionKind, ReprOptions, TraitObjectVisitor, Ty, TyKind, TyVar, TyVid, TypeAndMut, UintTy,
+ Visibility,
};
use crate::ty::{GenericArg, GenericArgKind, InternalSubsts, SubstsRef, UserSubsts};
use rustc_ast as ast;
use rustc_data_structures::fingerprint::Fingerprint;
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
-use rustc_data_structures::intern::{Interned, WithStableHash};
+use rustc_data_structures::intern::Interned;
use rustc_data_structures::memmap::Mmap;
use rustc_data_structures::profiling::SelfProfilerRef;
use rustc_data_structures::sharded::{IntoPointer, ShardedHashMap};
@@ -68,6 +70,7 @@ use rustc_span::{Span, DUMMY_SP};
use rustc_target::abi::{Layout, LayoutS, TargetDataLayout, VariantIdx};
use rustc_target::spec::abi;
use rustc_type_ir::sty::TyKind::*;
+use rustc_type_ir::WithCachedTypeInfo;
use rustc_type_ir::{DynKind, InternAs, InternIteratorElement, Interner, TypeFlags};
use std::any::Any;
@@ -81,7 +84,7 @@ use std::mem;
use std::ops::{Bound, Deref};
use std::sync::Arc;
-use super::{ImplPolarity, ResolverOutputs, RvalueScopes};
+use super::{ImplPolarity, RvalueScopes};
pub trait OnDiskCache<'tcx>: rustc_data_structures::sync::Sync {
/// Creates a new `OnDiskCache` instance from the serialized data in `data`.
@@ -137,13 +140,13 @@ pub struct CtxtInterners<'tcx> {
// Specifically use a speedy hash algorithm for these hash sets, since
// they're accessed quite often.
- type_: InternedSet<'tcx, WithStableHash<TyS<'tcx>>>,
+ type_: InternedSet<'tcx, WithCachedTypeInfo<TyKind<'tcx>>>,
const_lists: InternedSet<'tcx, List<ty::Const<'tcx>>>,
substs: InternedSet<'tcx, InternalSubsts<'tcx>>,
canonical_var_infos: InternedSet<'tcx, List<CanonicalVarInfo<'tcx>>>,
region: InternedSet<'tcx, RegionKind<'tcx>>,
poly_existential_predicates: InternedSet<'tcx, List<PolyExistentialPredicate<'tcx>>>,
- predicate: InternedSet<'tcx, WithStableHash<PredicateS<'tcx>>>,
+ predicate: InternedSet<'tcx, WithCachedTypeInfo<ty::Binder<'tcx, PredicateKind<'tcx>>>>,
predicates: InternedSet<'tcx, List<Predicate<'tcx>>>,
projs: InternedSet<'tcx, List<ProjectionKind>>,
place_elems: InternedSet<'tcx, List<PlaceElem<'tcx>>>,
@@ -194,15 +197,12 @@ impl<'tcx> CtxtInterners<'tcx> {
let stable_hash =
self.stable_hash(&flags, sess, definitions, cstore, source_span, &kind);
- let ty_struct = TyS {
- kind,
+ InternedInSet(self.arena.alloc(WithCachedTypeInfo {
+ internee: kind,
+ stable_hash,
flags: flags.flags,
outer_exclusive_binder: flags.outer_exclusive_binder,
- };
-
- InternedInSet(
- self.arena.alloc(WithStableHash { internee: ty_struct, stable_hash }),
- )
+ }))
})
.0,
))
@@ -246,16 +246,12 @@ impl<'tcx> CtxtInterners<'tcx> {
let stable_hash =
self.stable_hash(&flags, sess, definitions, cstore, source_span, &kind);
- let predicate_struct = PredicateS {
- kind,
+ InternedInSet(self.arena.alloc(WithCachedTypeInfo {
+ internee: kind,
+ stable_hash,
flags: flags.flags,
outer_exclusive_binder: flags.outer_exclusive_binder,
- };
-
- InternedInSet(
- self.arena
- .alloc(WithStableHash { internee: predicate_struct, stable_hash }),
- )
+ }))
})
.0,
))
@@ -1034,16 +1030,29 @@ pub struct FreeRegionInfo {
/// This struct should only be created by `create_def`.
#[derive(Copy, Clone)]
-pub struct TyCtxtFeed<'tcx> {
+pub struct TyCtxtFeed<'tcx, KEY: Copy> {
pub tcx: TyCtxt<'tcx>,
// Do not allow direct access, as downstream code must not mutate this field.
- def_id: LocalDefId,
+ key: KEY,
+}
+
+impl<'tcx> TyCtxt<'tcx> {
+ pub fn feed_unit_query(self) -> TyCtxtFeed<'tcx, ()> {
+ TyCtxtFeed { tcx: self, key: () }
+ }
}
-impl<'tcx> TyCtxtFeed<'tcx> {
+impl<'tcx, KEY: Copy> TyCtxtFeed<'tcx, KEY> {
+ #[inline(always)]
+ pub fn key(&self) -> KEY {
+ self.key
+ }
+}
+
+impl<'tcx> TyCtxtFeed<'tcx, LocalDefId> {
#[inline(always)]
pub fn def_id(&self) -> LocalDefId {
- self.def_id
+ self.key
}
}
@@ -1099,7 +1108,6 @@ pub struct GlobalCtxt<'tcx> {
/// Output of the resolver.
pub(crate) untracked_resolutions: ty::ResolverGlobalCtxt,
- untracked_resolver_for_lowering: Steal<ty::ResolverAstLowering>,
/// The entire crate as AST. This field serves as the input for the hir_crate query,
/// which lowers it from AST to HIR. It must not be read or used by anything else.
pub untracked_crate: Steal<Lrc<ast::Crate>>,
@@ -1262,7 +1270,8 @@ impl<'tcx> TyCtxt<'tcx> {
lint_store: Lrc<dyn Any + sync::Send + sync::Sync>,
arena: &'tcx WorkerLocal<Arena<'tcx>>,
hir_arena: &'tcx WorkerLocal<hir::Arena<'tcx>>,
- resolver_outputs: ResolverOutputs,
+ definitions: Definitions,
+ untracked_resolutions: ty::ResolverGlobalCtxt,
krate: Lrc<ast::Crate>,
dep_graph: DepGraph,
on_disk_cache: Option<&'tcx dyn OnDiskCache<'tcx>>,
@@ -1271,11 +1280,6 @@ impl<'tcx> TyCtxt<'tcx> {
crate_name: &str,
output_filenames: OutputFilenames,
) -> GlobalCtxt<'tcx> {
- let ResolverOutputs {
- definitions,
- global_ctxt: untracked_resolutions,
- ast_lowering: untracked_resolver_for_lowering,
- } = resolver_outputs;
let data_layout = s.target.parse_data_layout().unwrap_or_else(|err| {
s.emit_fatal(err);
});
@@ -1304,7 +1308,6 @@ impl<'tcx> TyCtxt<'tcx> {
lifetimes: common_lifetimes,
consts: common_consts,
untracked_resolutions,
- untracked_resolver_for_lowering: Steal::new(untracked_resolver_for_lowering),
untracked_crate: Steal::new(krate),
on_disk_cache,
queries,
@@ -1515,7 +1518,7 @@ impl<'tcx> TyCtxtAt<'tcx> {
self,
parent: LocalDefId,
data: hir::definitions::DefPathData,
- ) -> TyCtxtFeed<'tcx> {
+ ) -> TyCtxtFeed<'tcx, LocalDefId> {
// This function modifies `self.definitions` using a side-effect.
// We need to ensure that these side effects are re-run by the incr. comp. engine.
// Depending on the forever-red node will tell the graph that the calling query
@@ -1536,9 +1539,9 @@ impl<'tcx> TyCtxtAt<'tcx> {
// This is fine because:
// - those queries are `eval_always` so we won't miss their result changing;
// - this write will have happened before these queries are called.
- let def_id = self.definitions.write().create_def(parent, data);
+ let key = self.definitions.write().create_def(parent, data);
- let feed = TyCtxtFeed { tcx: self.tcx, def_id };
+ let feed = TyCtxtFeed { tcx: self.tcx, key };
feed.def_span(self.span);
feed
}
@@ -2097,7 +2100,7 @@ macro_rules! sty_debug_print {
let shards = tcx.interners.type_.lock_shards();
let types = shards.iter().flat_map(|shard| shard.keys());
for &InternedInSet(t) in types {
- let variant = match t.kind {
+ let variant = match t.internee {
ty::Bool | ty::Char | ty::Int(..) | ty::Uint(..) |
ty::Float(..) | ty::Str | ty::Never => continue,
ty::Error(_) => /* unimportant */ continue,
@@ -2207,51 +2210,26 @@ impl<'tcx, T: 'tcx + ?Sized> IntoPointer for InternedInSet<'tcx, T> {
}
#[allow(rustc::usage_of_ty_tykind)]
-impl<'tcx> Borrow<TyKind<'tcx>> for InternedInSet<'tcx, WithStableHash<TyS<'tcx>>> {
- fn borrow<'a>(&'a self) -> &'a TyKind<'tcx> {
- &self.0.kind
- }
-}
-
-impl<'tcx> PartialEq for InternedInSet<'tcx, WithStableHash<TyS<'tcx>>> {
- fn eq(&self, other: &InternedInSet<'tcx, WithStableHash<TyS<'tcx>>>) -> bool {
- // The `Borrow` trait requires that `x.borrow() == y.borrow()` equals
- // `x == y`.
- self.0.kind == other.0.kind
- }
-}
-
-impl<'tcx> Eq for InternedInSet<'tcx, WithStableHash<TyS<'tcx>>> {}
-
-impl<'tcx> Hash for InternedInSet<'tcx, WithStableHash<TyS<'tcx>>> {
- fn hash<H: Hasher>(&self, s: &mut H) {
- // The `Borrow` trait requires that `x.borrow().hash(s) == x.hash(s)`.
- self.0.kind.hash(s)
- }
-}
-
-impl<'tcx> Borrow<Binder<'tcx, PredicateKind<'tcx>>>
- for InternedInSet<'tcx, WithStableHash<PredicateS<'tcx>>>
-{
- fn borrow<'a>(&'a self) -> &'a Binder<'tcx, PredicateKind<'tcx>> {
- &self.0.kind
+impl<'tcx, T> Borrow<T> for InternedInSet<'tcx, WithCachedTypeInfo<T>> {
+ fn borrow<'a>(&'a self) -> &'a T {
+ &self.0.internee
}
}
-impl<'tcx> PartialEq for InternedInSet<'tcx, WithStableHash<PredicateS<'tcx>>> {
- fn eq(&self, other: &InternedInSet<'tcx, WithStableHash<PredicateS<'tcx>>>) -> bool {
+impl<'tcx, T: PartialEq> PartialEq for InternedInSet<'tcx, WithCachedTypeInfo<T>> {
+ fn eq(&self, other: &InternedInSet<'tcx, WithCachedTypeInfo<T>>) -> bool {
// The `Borrow` trait requires that `x.borrow() == y.borrow()` equals
// `x == y`.
- self.0.kind == other.0.kind
+ self.0.internee == other.0.internee
}
}
-impl<'tcx> Eq for InternedInSet<'tcx, WithStableHash<PredicateS<'tcx>>> {}
+impl<'tcx, T: Eq> Eq for InternedInSet<'tcx, WithCachedTypeInfo<T>> {}
-impl<'tcx> Hash for InternedInSet<'tcx, WithStableHash<PredicateS<'tcx>>> {
+impl<'tcx, T: Hash> Hash for InternedInSet<'tcx, WithCachedTypeInfo<T>> {
fn hash<H: Hasher>(&self, s: &mut H) {
// The `Borrow` trait requires that `x.borrow().hash(s) == x.hash(s)`.
- self.0.kind.hash(s)
+ self.0.internee.hash(s)
}
}
@@ -3107,7 +3085,6 @@ fn ptr_eq<T, U>(t: *const T, u: *const U) -> bool {
pub fn provide(providers: &mut ty::query::Providers) {
providers.resolutions = |tcx, ()| &tcx.untracked_resolutions;
- providers.resolver_for_lowering = |tcx, ()| &tcx.untracked_resolver_for_lowering;
providers.module_reexports =
|tcx, id| tcx.resolutions(()).reexport_map.get(&id).map(|v| &v[..]);
providers.crate_name = |tcx, id| {
diff --git a/compiler/rustc_middle/src/ty/generics.rs b/compiler/rustc_middle/src/ty/generics.rs
index a8da93e4c69..48329da3e63 100644
--- a/compiler/rustc_middle/src/ty/generics.rs
+++ b/compiler/rustc_middle/src/ty/generics.rs
@@ -101,6 +101,20 @@ impl GenericParamDef {
_ => None,
}
}
+
+ pub fn to_error<'tcx>(
+ &self,
+ tcx: TyCtxt<'tcx>,
+ preceding_substs: &[ty::GenericArg<'tcx>],
+ ) -> ty::GenericArg<'tcx> {
+ match &self.kind {
+ ty::GenericParamDefKind::Lifetime => tcx.lifetimes.re_static.into(),
+ ty::GenericParamDefKind::Type { .. } => tcx.ty_error().into(),
+ ty::GenericParamDefKind::Const { .. } => {
+ tcx.const_error(tcx.bound_type_of(self.def_id).subst(tcx, preceding_substs)).into()
+ }
+ }
+ }
}
#[derive(Default)]
diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs
index dd4ab3e8d30..cd679ffdfbc 100644
--- a/compiler/rustc_middle/src/ty/mod.rs
+++ b/compiler/rustc_middle/src/ty/mod.rs
@@ -9,6 +9,8 @@
//!
//! ["The `ty` module: representing types"]: https://rustc-dev-guide.rust-lang.org/ty.html
+#![allow(rustc::usage_of_ty_tykind)]
+
pub use self::fold::{FallibleTypeFolder, TypeFoldable, TypeFolder, TypeSuperFoldable};
pub use self::visit::{TypeSuperVisitable, TypeVisitable, TypeVisitor};
pub use self::AssocItemContainer::*;
@@ -32,7 +34,7 @@ use rustc_ast::node_id::NodeMap;
use rustc_attr as attr;
use rustc_data_structures::fingerprint::Fingerprint;
use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexMap, FxIndexSet};
-use rustc_data_structures::intern::{Interned, WithStableHash};
+use rustc_data_structures::intern::Interned;
use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
use rustc_data_structures::tagged_ptr::CopyTaggedPtr;
use rustc_hir as hir;
@@ -50,6 +52,7 @@ use rustc_span::symbol::{kw, sym, Ident, Symbol};
use rustc_span::{ExpnId, Span};
use rustc_target::abi::{Align, Integer, IntegerType, VariantIdx};
pub use rustc_target::abi::{ReprFlags, ReprOptions};
+use rustc_type_ir::WithCachedTypeInfo;
pub use subst::*;
pub use vtable::*;
@@ -82,8 +85,8 @@ pub use self::consts::{
pub use self::context::{
tls, CanonicalUserType, CanonicalUserTypeAnnotation, CanonicalUserTypeAnnotations,
CtxtInterners, DeducedParamAttrs, FreeRegionInfo, GeneratorDiagnosticData,
- GeneratorInteriorTypeCause, GlobalCtxt, Lift, OnDiskCache, TyCtxt, TypeckResults, UserType,
- UserTypeAnnotationIndex,
+ GeneratorInteriorTypeCause, GlobalCtxt, Lift, OnDiskCache, TyCtxt, TyCtxtFeed, TypeckResults,
+ UserType, UserTypeAnnotationIndex,
};
pub use self::instance::{Instance, InstanceDef, ShortInstance};
pub use self::list::List;
@@ -445,86 +448,22 @@ pub struct CReaderCacheKey {
pub pos: usize,
}
-/// Represents a type.
-///
-/// IMPORTANT:
-/// - This is a very "dumb" struct (with no derives and no `impls`).
-/// - Values of this type are always interned and thus unique, and are stored
-/// as an `Interned<TyS>`.
-/// - `Ty` (which contains a reference to a `Interned<TyS>`) or `Interned<TyS>`
-/// should be used everywhere instead of `TyS`. In particular, `Ty` has most
-/// of the relevant methods.
-#[derive(PartialEq, Eq, PartialOrd, Ord)]
-#[allow(rustc::usage_of_ty_tykind)]
-pub(crate) struct TyS<'tcx> {
- /// This field shouldn't be used directly and may be removed in the future.
- /// Use `Ty::kind()` instead.
- kind: TyKind<'tcx>,
-
- /// This field provides fast access to information that is also contained
- /// in `kind`.
- ///
- /// This field shouldn't be used directly and may be removed in the future.
- /// Use `Ty::flags()` instead.
- flags: TypeFlags,
-
- /// This field provides fast access to information that is also contained
- /// in `kind`.
- ///
- /// This is a kind of confusing thing: it stores the smallest
- /// binder such that
- ///
- /// (a) the binder itself captures nothing but
- /// (b) all the late-bound things within the type are captured
- /// by some sub-binder.
- ///
- /// So, for a type without any late-bound things, like `u32`, this
- /// will be *innermost*, because that is the innermost binder that
- /// captures nothing. But for a type `&'D u32`, where `'D` is a
- /// late-bound region with De Bruijn index `D`, this would be `D + 1`
- /// -- the binder itself does not capture `D`, but `D` is captured
- /// by an inner binder.
- ///
- /// We call this concept an "exclusive" binder `D` because all
- /// De Bruijn indices within the type are contained within `0..D`
- /// (exclusive).
- outer_exclusive_binder: ty::DebruijnIndex,
-}
-
-/// Use this rather than `TyS`, whenever possible.
+/// Use this rather than `TyKind`, whenever possible.
#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, HashStable)]
#[rustc_diagnostic_item = "Ty"]
#[rustc_pass_by_value]
-pub struct Ty<'tcx>(Interned<'tcx, WithStableHash<TyS<'tcx>>>);
+pub struct Ty<'tcx>(Interned<'tcx, WithCachedTypeInfo<TyKind<'tcx>>>);
impl<'tcx> TyCtxt<'tcx> {
/// A "bool" type used in rustc_mir_transform unit tests when we
/// have not spun up a TyCtxt.
- pub const BOOL_TY_FOR_UNIT_TESTING: Ty<'tcx> = Ty(Interned::new_unchecked(&WithStableHash {
- internee: TyS {
- kind: ty::Bool,
+ pub const BOOL_TY_FOR_UNIT_TESTING: Ty<'tcx> =
+ Ty(Interned::new_unchecked(&WithCachedTypeInfo {
+ internee: ty::Bool,
+ stable_hash: Fingerprint::ZERO,
flags: TypeFlags::empty(),
outer_exclusive_binder: DebruijnIndex::from_usize(0),
- },
- stable_hash: Fingerprint::ZERO,
- }));
-}
-
-impl<'a, 'tcx> HashStable<StableHashingContext<'a>> for TyS<'tcx> {
- #[inline]
- fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher) {
- let TyS {
- kind,
-
- // The other fields just provide fast access to information that is
- // also contained in `kind`, so no need to hash them.
- flags: _,
-
- outer_exclusive_binder: _,
- } = self;
-
- kind.hash_stable(hcx, hasher)
- }
+ }));
}
impl ty::EarlyBoundRegion {
@@ -535,28 +474,18 @@ impl ty::EarlyBoundRegion {
}
}
-/// Represents a predicate.
-///
-/// See comments on `TyS`, which apply here too (albeit for
-/// `PredicateS`/`Predicate` rather than `TyS`/`Ty`).
-#[derive(Debug)]
-pub(crate) struct PredicateS<'tcx> {
- kind: Binder<'tcx, PredicateKind<'tcx>>,
- flags: TypeFlags,
- /// See the comment for the corresponding field of [TyS].
- outer_exclusive_binder: ty::DebruijnIndex,
-}
-
-/// Use this rather than `PredicateS`, whenever possible.
+/// Use this rather than `PredicateKind`, whenever possible.
#[derive(Clone, Copy, PartialEq, Eq, Hash, HashStable)]
#[rustc_pass_by_value]
-pub struct Predicate<'tcx>(Interned<'tcx, WithStableHash<PredicateS<'tcx>>>);
+pub struct Predicate<'tcx>(
+ Interned<'tcx, WithCachedTypeInfo<ty::Binder<'tcx, PredicateKind<'tcx>>>>,
+);
impl<'tcx> Predicate<'tcx> {
/// Gets the inner `Binder<'tcx, PredicateKind<'tcx>>`.
#[inline]
pub fn kind(self) -> Binder<'tcx, PredicateKind<'tcx>> {
- self.0.kind
+ self.0.internee
}
#[inline(always)]
@@ -631,21 +560,6 @@ impl<'tcx> Predicate<'tcx> {
}
}
-impl<'a, 'tcx> HashStable<StableHashingContext<'a>> for PredicateS<'tcx> {
- fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher) {
- let PredicateS {
- ref kind,
-
- // The other fields just provide fast access to information that is
- // also contained in `kind`, so no need to hash them.
- flags: _,
- outer_exclusive_binder: _,
- } = self;
-
- kind.hash_stable(hcx, hasher);
- }
-}
-
impl rustc_errors::IntoDiagnosticArg for Predicate<'_> {
fn into_diagnostic_arg(self) -> rustc_errors::DiagnosticArgValue<'static> {
rustc_errors::DiagnosticArgValue::Str(std::borrow::Cow::Owned(self.to_string()))
@@ -1028,7 +942,7 @@ impl<'tcx> Term<'tcx> {
unsafe {
match ptr & TAG_MASK {
TYPE_TAG => TermKind::Ty(Ty(Interned::new_unchecked(
- &*((ptr & !TAG_MASK) as *const WithStableHash<ty::TyS<'tcx>>),
+ &*((ptr & !TAG_MASK) as *const WithCachedTypeInfo<ty::TyKind<'tcx>>),
))),
CONST_TAG => TermKind::Const(ty::Const(Interned::new_unchecked(
&*((ptr & !TAG_MASK) as *const ty::ConstS<'tcx>),
@@ -1072,7 +986,7 @@ impl<'tcx> TermKind<'tcx> {
TermKind::Ty(ty) => {
// Ensure we can use the tag bits.
assert_eq!(mem::align_of_val(&*ty.0.0) & TAG_MASK, 0);
- (TYPE_TAG, ty.0.0 as *const WithStableHash<ty::TyS<'tcx>> as usize)
+ (TYPE_TAG, ty.0.0 as *const WithCachedTypeInfo<ty::TyKind<'tcx>> as usize)
}
TermKind::Const(ct) => {
// Ensure we can use the tag bits.
@@ -1150,8 +1064,8 @@ impl<'tcx> ToPolyTraitRef<'tcx> for PolyTraitPredicate<'tcx> {
}
}
-pub trait ToPredicate<'tcx, Predicate> {
- fn to_predicate(self, tcx: TyCtxt<'tcx>) -> Predicate;
+pub trait ToPredicate<'tcx, P = Predicate<'tcx>> {
+ fn to_predicate(self, tcx: TyCtxt<'tcx>) -> P;
}
impl<'tcx, T> ToPredicate<'tcx, T> for T {
@@ -1160,21 +1074,21 @@ impl<'tcx, T> ToPredicate<'tcx, T> for T {
}
}
-impl<'tcx> ToPredicate<'tcx, Predicate<'tcx>> for Binder<'tcx, PredicateKind<'tcx>> {
+impl<'tcx> ToPredicate<'tcx> for Binder<'tcx, PredicateKind<'tcx>> {
#[inline(always)]
fn to_predicate(self, tcx: TyCtxt<'tcx>) -> Predicate<'tcx> {
tcx.mk_predicate(self)
}
}
-impl<'tcx> ToPredicate<'tcx, Predicate<'tcx>> for Clause<'tcx> {
+impl<'tcx> ToPredicate<'tcx> for Clause<'tcx> {
#[inline(always)]
fn to_predicate(self, tcx: TyCtxt<'tcx>) -> Predicate<'tcx> {
tcx.mk_predicate(ty::Binder::dummy(ty::PredicateKind::Clause(self)))
}
}
-impl<'tcx> ToPredicate<'tcx, Predicate<'tcx>> for Binder<'tcx, TraitRef<'tcx>> {
+impl<'tcx> ToPredicate<'tcx> for Binder<'tcx, TraitRef<'tcx>> {
#[inline(always)]
fn to_predicate(self, tcx: TyCtxt<'tcx>) -> Predicate<'tcx> {
let pred: PolyTraitPredicate<'tcx> = self.to_predicate(tcx);
@@ -1193,25 +1107,25 @@ impl<'tcx> ToPredicate<'tcx, PolyTraitPredicate<'tcx>> for Binder<'tcx, TraitRef
}
}
-impl<'tcx> ToPredicate<'tcx, Predicate<'tcx>> for PolyTraitPredicate<'tcx> {
+impl<'tcx> ToPredicate<'tcx> for PolyTraitPredicate<'tcx> {
fn to_predicate(self, tcx: TyCtxt<'tcx>) -> Predicate<'tcx> {
self.map_bound(|p| PredicateKind::Clause(Clause::Trait(p))).to_predicate(tcx)
}
}
-impl<'tcx> ToPredicate<'tcx, Predicate<'tcx>> for PolyRegionOutlivesPredicate<'tcx> {
+impl<'tcx> ToPredicate<'tcx> for PolyRegionOutlivesPredicate<'tcx> {
fn to_predicate(self, tcx: TyCtxt<'tcx>) -> Predicate<'tcx> {
self.map_bound(|p| PredicateKind::Clause(Clause::RegionOutlives(p))).to_predicate(tcx)
}
}
-impl<'tcx> ToPredicate<'tcx, Predicate<'tcx>> for PolyTypeOutlivesPredicate<'tcx> {
+impl<'tcx> ToPredicate<'tcx> for PolyTypeOutlivesPredicate<'tcx> {
fn to_predicate(self, tcx: TyCtxt<'tcx>) -> Predicate<'tcx> {
self.map_bound(|p| PredicateKind::Clause(Clause::TypeOutlives(p))).to_predicate(tcx)
}
}
-impl<'tcx> ToPredicate<'tcx, Predicate<'tcx>> for PolyProjectionPredicate<'tcx> {
+impl<'tcx> ToPredicate<'tcx> for PolyProjectionPredicate<'tcx> {
fn to_predicate(self, tcx: TyCtxt<'tcx>) -> Predicate<'tcx> {
self.map_bound(|p| PredicateKind::Clause(Clause::Projection(p))).to_predicate(tcx)
}
@@ -2692,8 +2606,7 @@ mod size_asserts {
use super::*;
use rustc_data_structures::static_assert_size;
// tidy-alphabetical-start
- static_assert_size!(PredicateS<'_>, 48);
- static_assert_size!(TyS<'_>, 40);
- static_assert_size!(WithStableHash<TyS<'_>>, 56);
+ static_assert_size!(PredicateKind<'_>, 32);
+ static_assert_size!(WithCachedTypeInfo<TyKind<'_>>, 56);
// tidy-alphabetical-end
}
diff --git a/compiler/rustc_middle/src/ty/query.rs b/compiler/rustc_middle/src/ty/query.rs
index a7fd1754960..642900d3ab4 100644
--- a/compiler/rustc_middle/src/ty/query.rs
+++ b/compiler/rustc_middle/src/ty/query.rs
@@ -328,13 +328,25 @@ macro_rules! define_callbacks {
};
}
+macro_rules! hash_result {
+ ([]) => {{
+ Some(dep_graph::hash_result)
+ }};
+ ([(no_hash) $($rest:tt)*]) => {{
+ None
+ }};
+ ([$other:tt $($modifiers:tt)*]) => {
+ hash_result!([$($modifiers)*])
+ };
+}
+
macro_rules! define_feedable {
($($(#[$attr:meta])* [$($modifiers:tt)*] fn $name:ident($($K:tt)*) -> $V:ty,)*) => {
- impl<'tcx> TyCtxtFeed<'tcx> {
- $($(#[$attr])*
+ $(impl<'tcx, K: IntoQueryParam<$($K)*> + Copy> TyCtxtFeed<'tcx, K> {
+ $(#[$attr])*
#[inline(always)]
pub fn $name(self, value: $V) -> query_stored::$name<'tcx> {
- let key = self.def_id().into_query_param();
+ let key = self.key().into_query_param();
opt_remap_env_constness!([$($modifiers)*][key]);
let tcx = self.tcx;
@@ -358,11 +370,11 @@ macro_rules! define_feedable {
tcx,
key,
&value,
- dep_graph::hash_result,
+ hash_result!([$($modifiers)*]),
);
cache.complete(key, value, dep_node_index)
- })*
- }
+ }
+ })*
}
}
diff --git a/compiler/rustc_middle/src/ty/sty.rs b/compiler/rustc_middle/src/ty/sty.rs
index 5984686044b..9cbda95a4df 100644
--- a/compiler/rustc_middle/src/ty/sty.rs
+++ b/compiler/rustc_middle/src/ty/sty.rs
@@ -722,8 +722,17 @@ impl<'tcx> PolyExistentialPredicate<'tcx> {
self.rebind(p.with_self_ty(tcx, self_ty)).to_predicate(tcx)
}
ExistentialPredicate::AutoTrait(did) => {
- let trait_ref = self.rebind(tcx.mk_trait_ref(did, [self_ty]));
- trait_ref.without_const().to_predicate(tcx)
+ let generics = tcx.generics_of(did);
+ let trait_ref = if generics.params.len() == 1 {
+ tcx.mk_trait_ref(did, [self_ty])
+ } else {
+ // If this is an ill-formed auto trait, then synthesize
+ // new error substs for the missing generics.
+ let err_substs =
+ ty::InternalSubsts::extend_with_error(tcx, did, &[self_ty.into()]);
+ tcx.mk_trait_ref(did, err_substs)
+ };
+ self.rebind(trait_ref).without_const().to_predicate(tcx)
}
}
}
@@ -1602,7 +1611,7 @@ impl<'tcx> Region<'tcx> {
impl<'tcx> Ty<'tcx> {
#[inline(always)]
pub fn kind(self) -> &'tcx TyKind<'tcx> {
- &self.0.0.kind
+ &self.0.0
}
#[inline(always)]
diff --git a/compiler/rustc_middle/src/ty/subst.rs b/compiler/rustc_middle/src/ty/subst.rs
index 141c8354c18..a1b084a5e89 100644
--- a/compiler/rustc_middle/src/ty/subst.rs
+++ b/compiler/rustc_middle/src/ty/subst.rs
@@ -6,10 +6,11 @@ use crate::ty::sty::{ClosureSubsts, GeneratorSubsts, InlineConstSubsts};
use crate::ty::visit::{TypeVisitable, TypeVisitor};
use crate::ty::{self, Lift, List, ParamConst, Ty, TyCtxt};
-use rustc_data_structures::intern::{Interned, WithStableHash};
+use rustc_data_structures::intern::Interned;
use rustc_hir::def_id::DefId;
use rustc_macros::HashStable;
use rustc_serialize::{self, Decodable, Encodable};
+use rustc_type_ir::WithCachedTypeInfo;
use smallvec::SmallVec;
use core::intrinsics;
@@ -84,7 +85,7 @@ impl<'tcx> GenericArgKind<'tcx> {
GenericArgKind::Type(ty) => {
// Ensure we can use the tag bits.
assert_eq!(mem::align_of_val(&*ty.0.0) & TAG_MASK, 0);
- (TYPE_TAG, ty.0.0 as *const WithStableHash<ty::TyS<'tcx>> as usize)
+ (TYPE_TAG, ty.0.0 as *const WithCachedTypeInfo<ty::TyKind<'tcx>> as usize)
}
GenericArgKind::Const(ct) => {
// Ensure we can use the tag bits.
@@ -162,7 +163,7 @@ impl<'tcx> GenericArg<'tcx> {
&*((ptr & !TAG_MASK) as *const ty::RegionKind<'tcx>),
))),
TYPE_TAG => GenericArgKind::Type(Ty(Interned::new_unchecked(
- &*((ptr & !TAG_MASK) as *const WithStableHash<ty::TyS<'tcx>>),
+ &*((ptr & !TAG_MASK) as *const WithCachedTypeInfo<ty::TyKind<'tcx>>),
))),
CONST_TAG => GenericArgKind::Const(ty::Const(Interned::new_unchecked(
&*((ptr & !TAG_MASK) as *const ty::ConstS<'tcx>),
@@ -352,6 +353,22 @@ impl<'tcx> InternalSubsts<'tcx> {
}
}
+ // Extend an `original_substs` list to the full number of substs expected by `def_id`,
+ // filling in the missing parameters with error ty/ct or 'static regions.
+ pub fn extend_with_error(
+ tcx: TyCtxt<'tcx>,
+ def_id: DefId,
+ original_substs: &[GenericArg<'tcx>],
+ ) -> SubstsRef<'tcx> {
+ ty::InternalSubsts::for_item(tcx, def_id, |def, substs| {
+ if let Some(subst) = original_substs.get(def.index as usize) {
+ *subst
+ } else {
+ def.to_error(tcx, substs)
+ }
+ })
+ }
+
#[inline]
pub fn types(&'tcx self) -> impl DoubleEndedIterator<Item = Ty<'tcx>> + 'tcx {
self.iter()
diff --git a/compiler/rustc_mir_build/src/build/mod.rs b/compiler/rustc_mir_build/src/build/mod.rs
index b456e2aa37a..007f3b55ec8 100644
--- a/compiler/rustc_mir_build/src/build/mod.rs
+++ b/compiler/rustc_mir_build/src/build/mod.rs
@@ -948,20 +948,12 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
original_source_scope: SourceScope,
pattern_span: Span,
) {
- let tcx = self.tcx;
- let current_root = tcx.maybe_lint_level_root_bounded(arg_hir_id, self.hir_id);
- let parent_root = tcx.maybe_lint_level_root_bounded(
- self.source_scopes[original_source_scope]
- .local_data
- .as_ref()
- .assert_crate_local()
- .lint_root,
- self.hir_id,
- );
- if current_root != parent_root {
- self.source_scope =
- self.new_source_scope(pattern_span, LintLevel::Explicit(current_root), None);
- }
+ let parent_id = self.source_scopes[original_source_scope]
+ .local_data
+ .as_ref()
+ .assert_crate_local()
+ .lint_root;
+ self.maybe_new_source_scope(pattern_span, None, arg_hir_id, parent_id);
}
fn get_unit_temp(&mut self) -> Place<'tcx> {
diff --git a/compiler/rustc_mir_build/src/build/scope.rs b/compiler/rustc_mir_build/src/build/scope.rs
index 5ddae5f5300..33f49ffdaf6 100644
--- a/compiler/rustc_mir_build/src/build/scope.rs
+++ b/compiler/rustc_mir_build/src/build/scope.rs
@@ -85,6 +85,7 @@ use std::mem;
use crate::build::{BlockAnd, BlockAndExtension, BlockFrame, Builder, CFG};
use rustc_data_structures::fx::FxHashMap;
+use rustc_hir::HirId;
use rustc_index::vec::IndexVec;
use rustc_middle::middle::region;
use rustc_middle::mir::*;
@@ -567,25 +568,10 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
F: FnOnce(&mut Builder<'a, 'tcx>) -> BlockAnd<R>,
{
let source_scope = self.source_scope;
- let tcx = self.tcx;
if let LintLevel::Explicit(current_hir_id) = lint_level {
- // Use `maybe_lint_level_root_bounded` with `root_lint_level` as a bound
- // to avoid adding Hir dependencies on our parents.
- // We estimate the true lint roots here to avoid creating a lot of source scopes.
-
- let parent_root = tcx.maybe_lint_level_root_bounded(
- self.source_scopes[source_scope].local_data.as_ref().assert_crate_local().lint_root,
- self.hir_id,
- );
- let current_root = tcx.maybe_lint_level_root_bounded(current_hir_id, self.hir_id);
-
- if parent_root != current_root {
- self.source_scope = self.new_source_scope(
- region_scope.1.span,
- LintLevel::Explicit(current_root),
- None,
- );
- }
+ let parent_id =
+ self.source_scopes[source_scope].local_data.as_ref().assert_crate_local().lint_root;
+ self.maybe_new_source_scope(region_scope.1.span, None, current_hir_id, parent_id);
}
self.push_scope(region_scope);
let mut block;
@@ -758,6 +744,40 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
))
}
+ /// Possibly creates a new source scope if `current_root` and `parent_root`
+ /// are different, or if -Zmaximal-hir-to-mir-coverage is enabled.
+ pub(crate) fn maybe_new_source_scope(
+ &mut self,
+ span: Span,
+ safety: Option<Safety>,
+ current_id: HirId,
+ parent_id: HirId,
+ ) {
+ let (current_root, parent_root) =
+ if self.tcx.sess.opts.unstable_opts.maximal_hir_to_mir_coverage {
+ // Some consumers of rustc need to map MIR locations back to HIR nodes. Currently the
+ // the only part of rustc that tracks MIR -> HIR is the `SourceScopeLocalData::lint_root`
+ // field that tracks lint levels for MIR locations. Normally the number of source scopes
+ // is limited to the set of nodes with lint annotations. The -Zmaximal-hir-to-mir-coverage
+ // flag changes this behavior to maximize the number of source scopes, increasing the
+ // granularity of the MIR->HIR mapping.
+ (current_id, parent_id)
+ } else {
+ // Use `maybe_lint_level_root_bounded` with `self.hir_id` as a bound
+ // to avoid adding Hir dependencies on our parents.
+ // We estimate the true lint roots here to avoid creating a lot of source scopes.
+ (
+ self.tcx.maybe_lint_level_root_bounded(current_id, self.hir_id),
+ self.tcx.maybe_lint_level_root_bounded(parent_id, self.hir_id),
+ )
+ };
+
+ if current_root != parent_root {
+ let lint_level = LintLevel::Explicit(current_root);
+ self.source_scope = self.new_source_scope(span, lint_level, safety);
+ }
+ }
+
/// Creates a new source scope, nested in the current one.
pub(crate) fn new_source_scope(
&mut self,
diff --git a/compiler/rustc_mir_dataflow/src/value_analysis.rs b/compiler/rustc_mir_dataflow/src/value_analysis.rs
index cc69a1bb02d..7df01142264 100644
--- a/compiler/rustc_mir_dataflow/src/value_analysis.rs
+++ b/compiler/rustc_mir_dataflow/src/value_analysis.rs
@@ -406,7 +406,7 @@ impl<V: Clone> Clone for StateData<V> {
/// The dataflow state for an instance of [`ValueAnalysis`].
///
/// Every instance specifies a lattice that represents the possible values of a single tracked
-/// place. If we call this lattice `V` and set set of tracked places `P`, then a [`State`] is an
+/// place. If we call this lattice `V` and set of tracked places `P`, then a [`State`] is an
/// element of `{unreachable} ∪ (P -> V)`. This again forms a lattice, where the bottom element is
/// `unreachable` and the top element is the mapping `p ↦ ⊤`. Note that the mapping `p ↦ ⊥` is not
/// the bottom element (because joining an unreachable and any other reachable state yields a
diff --git a/compiler/rustc_mir_transform/src/dump_mir.rs b/compiler/rustc_mir_transform/src/dump_mir.rs
index 778ae63c5a4..594cbd8977e 100644
--- a/compiler/rustc_mir_transform/src/dump_mir.rs
+++ b/compiler/rustc_mir_transform/src/dump_mir.rs
@@ -7,7 +7,7 @@ use crate::MirPass;
use rustc_middle::mir::write_mir_pretty;
use rustc_middle::mir::Body;
use rustc_middle::ty::TyCtxt;
-use rustc_session::config::{OutputFilenames, OutputType};
+use rustc_session::config::OutputType;
pub struct Marker(pub &'static str);
@@ -19,8 +19,8 @@ impl<'tcx> MirPass<'tcx> for Marker {
fn run_pass(&self, _tcx: TyCtxt<'tcx>, _body: &mut Body<'tcx>) {}
}
-pub fn emit_mir(tcx: TyCtxt<'_>, outputs: &OutputFilenames) -> io::Result<()> {
- let path = outputs.path(OutputType::Mir);
+pub fn emit_mir(tcx: TyCtxt<'_>) -> io::Result<()> {
+ let path = tcx.output_filenames(()).path(OutputType::Mir);
let mut f = io::BufWriter::new(File::create(&path)?);
write_mir_pretty(tcx, None, &mut f)?;
Ok(())
diff --git a/compiler/rustc_mir_transform/src/inline.rs b/compiler/rustc_mir_transform/src/inline.rs
index bf670c5c26a..220cf7df9c6 100644
--- a/compiler/rustc_mir_transform/src/inline.rs
+++ b/compiler/rustc_mir_transform/src/inline.rs
@@ -8,7 +8,6 @@ use rustc_middle::mir::visit::*;
use rustc_middle::mir::*;
use rustc_middle::ty::{self, Instance, InstanceDef, ParamEnv, Ty, TyCtxt};
use rustc_session::config::OptLevel;
-use rustc_span::def_id::DefId;
use rustc_span::{hygiene::ExpnKind, ExpnData, LocalExpnId, Span};
use rustc_target::abi::VariantIdx;
use rustc_target::spec::abi::Abi;
@@ -87,13 +86,8 @@ fn inline<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) -> bool {
let param_env = tcx.param_env_reveal_all_normalized(def_id);
- let mut this = Inliner {
- tcx,
- param_env,
- codegen_fn_attrs: tcx.codegen_fn_attrs(def_id),
- history: Vec::new(),
- changed: false,
- };
+ let mut this =
+ Inliner { tcx, param_env, codegen_fn_attrs: tcx.codegen_fn_attrs(def_id), changed: false };
let blocks = BasicBlock::new(0)..body.basic_blocks.next_index();
this.process_blocks(body, blocks);
this.changed
@@ -104,12 +98,6 @@ struct Inliner<'tcx> {
param_env: ParamEnv<'tcx>,
/// Caller codegen attributes.
codegen_fn_attrs: &'tcx CodegenFnAttrs,
- /// Stack of inlined instances.
- /// We only check the `DefId` and not the substs because we want to
- /// avoid inlining cases of polymorphic recursion.
- /// The number of `DefId`s is finite, so checking history is enough
- /// to ensure that we do not loop endlessly while inlining.
- history: Vec<DefId>,
/// Indicates that the caller body has been modified.
changed: bool,
}
@@ -134,12 +122,12 @@ impl<'tcx> Inliner<'tcx> {
debug!("not-inlined {} [{}]", callsite.callee, reason);
continue;
}
- Ok(new_blocks) => {
+ Ok(_) => {
debug!("inlined {}", callsite.callee);
self.changed = true;
- self.history.push(callsite.callee.def_id());
- self.process_blocks(caller_body, new_blocks);
- self.history.pop();
+ // We could process the blocks returned by `try_inlining` here. However, that
+ // leads to exponential compile times due to the top-down nature of this kind
+ // of inlining.
}
}
}
@@ -313,10 +301,6 @@ impl<'tcx> Inliner<'tcx> {
return None;
}
- if self.history.contains(&callee.def_id()) {
- return None;
- }
-
let fn_sig = self.tcx.bound_fn_sig(def_id).subst(self.tcx, substs);
return Some(CallSite {
diff --git a/compiler/rustc_mir_transform/src/remove_zsts.rs b/compiler/rustc_mir_transform/src/remove_zsts.rs
index 40be4f146db..569e783fee8 100644
--- a/compiler/rustc_mir_transform/src/remove_zsts.rs
+++ b/compiler/rustc_mir_transform/src/remove_zsts.rs
@@ -1,8 +1,7 @@
//! Removes assignments to ZST places.
use crate::MirPass;
-use rustc_middle::mir::tcx::PlaceTy;
-use rustc_middle::mir::{Body, LocalDecls, Place, StatementKind};
+use rustc_middle::mir::{Body, StatementKind};
use rustc_middle::ty::{self, Ty, TyCtxt};
pub struct RemoveZsts;
@@ -35,9 +34,6 @@ impl<'tcx> MirPass<'tcx> for RemoveZsts {
if !layout.is_zst() {
continue;
}
- if involves_a_union(place, local_decls, tcx) {
- continue;
- }
if tcx.consider_optimizing(|| {
format!(
"RemoveZsts - Place: {:?} SourceInfo: {:?}",
@@ -63,24 +59,3 @@ fn maybe_zst(ty: Ty<'_>) -> bool {
_ => false,
}
}
-
-/// Miri lazily allocates memory for locals on assignment,
-/// so we must preserve writes to unions and union fields,
-/// or it will ICE on reads of those fields.
-fn involves_a_union<'tcx>(
- place: Place<'tcx>,
- local_decls: &LocalDecls<'tcx>,
- tcx: TyCtxt<'tcx>,
-) -> bool {
- let mut place_ty = PlaceTy::from_ty(local_decls[place.local].ty);
- if place_ty.ty.is_union() {
- return true;
- }
- for elem in place.projection {
- place_ty = place_ty.projection_ty(tcx, elem);
- if place_ty.ty.is_union() {
- return true;
- }
- }
- return false;
-}
diff --git a/compiler/rustc_parse/src/parser/expr.rs b/compiler/rustc_parse/src/parser/expr.rs
index fe3cfde2e63..f6a6ed379a2 100644
--- a/compiler/rustc_parse/src/parser/expr.rs
+++ b/compiler/rustc_parse/src/parser/expr.rs
@@ -390,20 +390,11 @@ impl<'a> Parser<'a> {
// want to keep their span info to improve diagnostics in these cases in a later stage.
(true, Some(AssocOp::Multiply)) | // `{ 42 } *foo = bar;` or `{ 42 } * 3`
(true, Some(AssocOp::Subtract)) | // `{ 42 } -5`
- (true, Some(AssocOp::Add)) // `{ 42 } + 42
- // If the next token is a keyword, then the tokens above *are* unambiguously incorrect:
- // `if x { a } else { b } && if y { c } else { d }`
- if !self.look_ahead(1, |t| t.is_used_keyword()) => {
- // These cases are ambiguous and can't be identified in the parser alone.
- let sp = self.sess.source_map().start_point(self.token.span);
- self.sess.ambiguous_block_expr_parse.borrow_mut().insert(sp, lhs.span);
- false
- }
- (true, Some(AssocOp::LAnd)) |
- (true, Some(AssocOp::LOr)) |
- (true, Some(AssocOp::BitOr)) => {
- // `{ 42 } &&x` (#61475) or `{ 42 } && if x { 1 } else { 0 }`. Separated from the
- // above due to #74233.
+ (true, Some(AssocOp::Add)) | // `{ 42 } + 42` (unary plus)
+ (true, Some(AssocOp::LAnd)) | // `{ 42 } &&x` (#61475) or `{ 42 } && if x { 1 } else { 0 }`
+ (true, Some(AssocOp::LOr)) | // `{ 42 } || 42` ("logical or" or closure)
+ (true, Some(AssocOp::BitOr)) // `{ 42 } | 42` or `{ 42 } |x| 42`
+ => {
// These cases are ambiguous and can't be identified in the parser alone.
//
// Bitwise AND is left out because guessing intent is hard. We can make
diff --git a/compiler/rustc_parse/src/parser/item.rs b/compiler/rustc_parse/src/parser/item.rs
index 84c63219920..03f25392a7c 100644
--- a/compiler/rustc_parse/src/parser/item.rs
+++ b/compiler/rustc_parse/src/parser/item.rs
@@ -1414,7 +1414,10 @@ impl<'a> Parser<'a> {
Ok((Some(vr), TrailingToken::MaybeComma))
},
- )
+ ).map_err(|mut err|{
+ err.help("enum variants can be `Variant`, `Variant = <integer>`, `Variant(Type, ..., TypeN)` or `Variant { fields: Types }`");
+ err
+ })
}
/// Parses `struct Foo { ... }`.
diff --git a/compiler/rustc_parse/src/parser/mod.rs b/compiler/rustc_parse/src/parser/mod.rs
index 4d8bff28b05..bebb012660a 100644
--- a/compiler/rustc_parse/src/parser/mod.rs
+++ b/compiler/rustc_parse/src/parser/mod.rs
@@ -943,6 +943,10 @@ impl<'a> Parser<'a> {
Err(e) => {
// Parsing failed, therefore it must be something more serious
// than just a missing separator.
+ for xx in &e.children {
+ // propagate the help message from sub error 'e' to main error 'expect_err;
+ expect_err.children.push(xx.clone());
+ }
expect_err.emit();
e.cancel();
diff --git a/compiler/rustc_passes/src/liveness.rs b/compiler/rustc_passes/src/liveness.rs
index 2234837050b..1f65cc8b609 100644
--- a/compiler/rustc_passes/src/liveness.rs
+++ b/compiler/rustc_passes/src/liveness.rs
@@ -1548,7 +1548,13 @@ impl<'tcx> Liveness<'_, 'tcx> {
.or_insert_with(|| (ln, var, vec![id_and_sp]));
});
- let can_remove = matches!(&pat.kind, hir::PatKind::Struct(_, _, true));
+ let can_remove = match pat.kind {
+ hir::PatKind::Struct(_, fields, true) => {
+ // if all fields are shorthand, remove the struct field, otherwise, mark with _ as prefix
+ fields.iter().all(|f| f.is_shorthand)
+ }
+ _ => false,
+ };
for (_, (ln, var, hir_ids_and_spans)) in vars {
if self.used_on_entry(ln, var) {
diff --git a/compiler/rustc_query_system/src/dep_graph/graph.rs b/compiler/rustc_query_system/src/dep_graph/graph.rs
index 30d28ff3455..38c7c6cce67 100644
--- a/compiler/rustc_query_system/src/dep_graph/graph.rs
+++ b/compiler/rustc_query_system/src/dep_graph/graph.rs
@@ -510,7 +510,7 @@ impl<K: DepKind> DepGraph<K> {
cx: Ctxt,
key: A,
result: &R,
- hash_result: fn(&mut StableHashingContext<'_>, &R) -> Fingerprint,
+ hash_result: Option<fn(&mut StableHashingContext<'_>, &R) -> Fingerprint>,
) -> DepNodeIndex {
if let Some(data) = self.data.as_ref() {
// The caller query has more dependencies than the node we are creating. We may
@@ -521,10 +521,12 @@ impl<K: DepKind> DepGraph<K> {
// For sanity, we still check that the loaded stable hash and the new one match.
if let Some(dep_node_index) = self.dep_node_index_of_opt(&node) {
let _current_fingerprint =
- crate::query::incremental_verify_ich(cx, result, &node, Some(hash_result));
+ crate::query::incremental_verify_ich(cx, result, &node, hash_result);
#[cfg(debug_assertions)]
- data.current.record_edge(dep_node_index, node, _current_fingerprint);
+ if hash_result.is_some() {
+ data.current.record_edge(dep_node_index, node, _current_fingerprint);
+ }
return dep_node_index;
}
@@ -539,8 +541,9 @@ impl<K: DepKind> DepGraph<K> {
});
let hashing_timer = cx.profiler().incr_result_hashing();
- let current_fingerprint =
- cx.with_stable_hashing_context(|mut hcx| hash_result(&mut hcx, result));
+ let current_fingerprint = hash_result.map(|hash_result| {
+ cx.with_stable_hashing_context(|mut hcx| hash_result(&mut hcx, result))
+ });
let print_status = cfg!(debug_assertions) && cx.sess().opts.unstable_opts.dep_tasks;
@@ -550,7 +553,7 @@ impl<K: DepKind> DepGraph<K> {
&data.previous,
node,
edges,
- Some(current_fingerprint),
+ current_fingerprint,
print_status,
);
diff --git a/compiler/rustc_resolve/src/late.rs b/compiler/rustc_resolve/src/late.rs
index 51a53f7b37c..cf3e5946053 100644
--- a/compiler/rustc_resolve/src/late.rs
+++ b/compiler/rustc_resolve/src/late.rs
@@ -1927,7 +1927,7 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
// We have a single lifetime => success.
elision_lifetime = Elision::Param(res)
} else {
- // We have have multiple lifetimes => error.
+ // We have multiple lifetimes => error.
elision_lifetime = Elision::Err;
}
}
@@ -2360,8 +2360,8 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
if let GenericParamKind::Lifetime = param.kind {
// Record lifetime res, so lowering knows there is something fishy.
self.record_lifetime_param(param.id, LifetimeRes::Error);
- continue;
}
+ continue;
}
Entry::Vacant(entry) => {
entry.insert(param.ident.span);
diff --git a/compiler/rustc_session/src/config.rs b/compiler/rustc_session/src/config.rs
index d8c4b0845d0..7a20100fd31 100644
--- a/compiler/rustc_session/src/config.rs
+++ b/compiler/rustc_session/src/config.rs
@@ -10,7 +10,7 @@ use crate::{lint, HashStableContext};
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
-use rustc_data_structures::stable_hasher::ToStableHashKey;
+use rustc_data_structures::stable_hasher::{StableOrd, ToStableHashKey};
use rustc_target::abi::Align;
use rustc_target::spec::{PanicStrategy, SanitizerSet, SplitDebuginfo};
use rustc_target::spec::{Target, TargetTriple, TargetWarnings, TARGETS};
@@ -288,6 +288,9 @@ pub enum OutputType {
DepInfo,
}
+// Safety: Trivial C-Style enums have a stable sort order across compilation sessions.
+unsafe impl StableOrd for OutputType {}
+
impl<HCX: HashStableContext> ToStableHashKey<HCX> for OutputType {
type KeyType = Self;
diff --git a/compiler/rustc_session/src/options.rs b/compiler/rustc_session/src/options.rs
index 01a9361e786..8e9198b79df 100644
--- a/compiler/rustc_session/src/options.rs
+++ b/compiler/rustc_session/src/options.rs
@@ -1382,6 +1382,9 @@ options! {
"list the symbols defined by a library crate (default: no)"),
macro_backtrace: bool = (false, parse_bool, [UNTRACKED],
"show macro backtraces (default: no)"),
+ maximal_hir_to_mir_coverage: bool = (false, parse_bool, [TRACKED],
+ "save as much information as possible about the correspondence between MIR and HIR \
+ as source scopes (default: no)"),
merge_functions: Option<MergeFunctions> = (None, parse_merge_functions, [TRACKED],
"control the operation of the MergeFunctions LLVM pass, taking \
the same values as the target option of the same name"),
diff --git a/compiler/rustc_span/src/def_id.rs b/compiler/rustc_span/src/def_id.rs
index f5555846d20..0ad1f1a0da7 100644
--- a/compiler/rustc_span/src/def_id.rs
+++ b/compiler/rustc_span/src/def_id.rs
@@ -274,7 +274,7 @@ impl Ord for DefId {
impl PartialOrd for DefId {
#[inline]
fn partial_cmp(&self, other: &DefId) -> Option<std::cmp::Ordering> {
- Some(Ord::cmp(self, other))
+ Some(self.cmp(other))
}
}
diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs
index 9e446c96db3..61253845497 100644
--- a/compiler/rustc_span/src/symbol.rs
+++ b/compiler/rustc_span/src/symbol.rs
@@ -165,6 +165,7 @@ symbols! {
Capture,
Center,
Clone,
+ Context,
Continue,
Copy,
Count,
@@ -264,7 +265,6 @@ symbols! {
Relaxed,
Release,
Result,
- ResumeTy,
Return,
Right,
Rust,
@@ -754,7 +754,6 @@ symbols! {
generic_associated_types_extended,
generic_const_exprs,
generic_param_attrs,
- get_context,
global_allocator,
global_asm,
globs,
diff --git a/compiler/rustc_trait_selection/src/traits/codegen.rs b/compiler/rustc_trait_selection/src/traits/codegen.rs
index 61743d78e9e..0102d268b42 100644
--- a/compiler/rustc_trait_selection/src/traits/codegen.rs
+++ b/compiler/rustc_trait_selection/src/traits/codegen.rs
@@ -70,7 +70,7 @@ pub fn codegen_select_candidate<'tcx>(
// `rustc_ty_utils::resolve_associated_item` doesn't return `None` post-monomorphization.
for err in errors {
if let FulfillmentErrorCode::CodeCycle(cycle) = err.code {
- infcx.err_ctxt().report_overflow_error_cycle(&cycle);
+ infcx.err_ctxt().report_overflow_obligation_cycle(&cycle);
}
}
return Err(CodegenObligationError::FulfillmentError);
diff --git a/compiler/rustc_trait_selection/src/traits/const_evaluatable.rs b/compiler/rustc_trait_selection/src/traits/const_evaluatable.rs
index e9e65336299..7cc0999478a 100644
--- a/compiler/rustc_trait_selection/src/traits/const_evaluatable.rs
+++ b/compiler/rustc_trait_selection/src/traits/const_evaluatable.rs
@@ -25,15 +25,13 @@ use crate::traits::ObligationCtxt;
#[instrument(skip(infcx), level = "debug")]
pub fn is_const_evaluatable<'tcx>(
infcx: &InferCtxt<'tcx>,
- ct: ty::Const<'tcx>,
+ unexpanded_ct: ty::Const<'tcx>,
param_env: ty::ParamEnv<'tcx>,
span: Span,
) -> Result<(), NotConstEvaluatable> {
let tcx = infcx.tcx;
- let uv = match ct.kind() {
- ty::ConstKind::Unevaluated(uv) => uv,
- // FIXME(generic_const_exprs): this seems wrong but I couldn't find a way to get this to trigger
- ty::ConstKind::Expr(_) => bug!("unexpected expr in `is_const_evaluatable: {ct:?}"),
+ match unexpanded_ct.kind() {
+ ty::ConstKind::Unevaluated(_) | ty::ConstKind::Expr(_) => (),
ty::ConstKind::Param(_)
| ty::ConstKind::Bound(_, _)
| ty::ConstKind::Placeholder(_)
@@ -43,7 +41,7 @@ pub fn is_const_evaluatable<'tcx>(
};
if tcx.features().generic_const_exprs {
- let ct = tcx.expand_abstract_consts(ct);
+ let ct = tcx.expand_abstract_consts(unexpanded_ct);
let is_anon_ct = if let ty::ConstKind::Unevaluated(uv) = ct.kind() {
tcx.def_kind(uv.def.did) == DefKind::AnonConst
@@ -62,18 +60,40 @@ pub fn is_const_evaluatable<'tcx>(
}
}
- let concrete = infcx.const_eval_resolve(param_env, uv, Some(span));
- match concrete {
- Err(ErrorHandled::TooGeneric) => Err(NotConstEvaluatable::Error(
- infcx
- .tcx
- .sess
- .delay_span_bug(span, "Missing value for constant, but no error reported?"),
- )),
- Err(ErrorHandled::Reported(e)) => Err(NotConstEvaluatable::Error(e)),
- Ok(_) => Ok(()),
+ match unexpanded_ct.kind() {
+ ty::ConstKind::Expr(_) => {
+ // FIXME(generic_const_exprs): we have a `ConstKind::Expr` which is fully concrete, but
+ // currently it is not possible to evaluate `ConstKind::Expr` so we are unable to tell if it
+ // is evaluatable or not. For now we just ICE until this is implemented.
+ Err(NotConstEvaluatable::Error(tcx.sess.delay_span_bug(
+ span,
+ "evaluating `ConstKind::Expr` is not currently supported",
+ )))
+ }
+ ty::ConstKind::Unevaluated(uv) => {
+ let concrete = infcx.const_eval_resolve(param_env, uv, Some(span));
+ match concrete {
+ Err(ErrorHandled::TooGeneric) => {
+ Err(NotConstEvaluatable::Error(infcx.tcx.sess.delay_span_bug(
+ span,
+ "Missing value for constant, but no error reported?",
+ )))
+ }
+ Err(ErrorHandled::Reported(e)) => Err(NotConstEvaluatable::Error(e)),
+ Ok(_) => Ok(()),
+ }
+ }
+ _ => bug!("unexpected constkind in `is_const_evalautable: {unexpanded_ct:?}`"),
}
} else {
+ let uv = match unexpanded_ct.kind() {
+ ty::ConstKind::Unevaluated(uv) => uv,
+ ty::ConstKind::Expr(_) => {
+ bug!("`ConstKind::Expr` without `feature(generic_const_exprs)` enabled")
+ }
+ _ => bug!("unexpected constkind in `is_const_evalautable: {unexpanded_ct:?}`"),
+ };
+
// FIXME: We should only try to evaluate a given constant here if it is fully concrete
// as we don't want to allow things like `[u8; std::mem::size_of::<*mut T>()]`.
//
@@ -92,7 +112,7 @@ pub fn is_const_evaluatable<'tcx>(
&& satisfied_from_param_env(
tcx,
infcx,
- tcx.expand_abstract_consts(ct),
+ tcx.expand_abstract_consts(unexpanded_ct),
param_env,
) =>
{
@@ -152,6 +172,7 @@ fn satisfied_from_param_env<'tcx>(
impl<'a, 'tcx> TypeVisitor<'tcx> for Visitor<'a, 'tcx> {
type BreakTy = ();
fn visit_const(&mut self, c: ty::Const<'tcx>) -> ControlFlow<Self::BreakTy> {
+ debug!("is_const_evaluatable: candidate={:?}", c);
if let Ok(()) = self.infcx.commit_if_ok(|_| {
let ocx = ObligationCtxt::new_in_snapshot(self.infcx);
if let Ok(()) = ocx.eq(&ObligationCause::dummy(), self.param_env, c.ty(), self.ct.ty())
@@ -187,7 +208,7 @@ fn satisfied_from_param_env<'tcx>(
let result = b_ct.visit_with(&mut v);
if let ControlFlow::Break(()) = result {
- debug!("is_const_evaluatable: abstract_const ~~> ok");
+ debug!("is_const_evaluatable: yes");
return true;
}
}
@@ -195,5 +216,6 @@ fn satisfied_from_param_env<'tcx>(
}
}
+ debug!("is_const_evaluatable: no");
false
}
diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs
index 3379279dd15..dda7b2b2fa5 100644
--- a/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs
+++ b/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs
@@ -99,26 +99,36 @@ pub trait InferCtxtExt<'tcx> {
}
pub trait TypeErrCtxtExt<'tcx> {
+ fn report_overflow_error<T>(
+ &self,
+ predicate: &T,
+ span: Span,
+ suggest_increasing_limit: bool,
+ mutate: impl FnOnce(&mut Diagnostic),
+ ) -> !
+ where
+ T: fmt::Display
+ + TypeFoldable<'tcx>
+ + Print<'tcx, FmtPrinter<'tcx, 'tcx>, Output = FmtPrinter<'tcx, 'tcx>>,
+ <T as Print<'tcx, FmtPrinter<'tcx, 'tcx>>>::Error: std::fmt::Debug;
+
fn report_fulfillment_errors(
&self,
errors: &[FulfillmentError<'tcx>],
body_id: Option<hir::BodyId>,
) -> ErrorGuaranteed;
- fn report_overflow_error<T>(
+ fn report_overflow_obligation<T>(
&self,
obligation: &Obligation<'tcx, T>,
suggest_increasing_limit: bool,
) -> !
where
- T: fmt::Display
- + TypeFoldable<'tcx>
- + Print<'tcx, FmtPrinter<'tcx, 'tcx>, Output = FmtPrinter<'tcx, 'tcx>>,
- <T as Print<'tcx, FmtPrinter<'tcx, 'tcx>>>::Error: std::fmt::Debug;
+ T: ToPredicate<'tcx> + Clone;
fn suggest_new_overflow_limit(&self, err: &mut Diagnostic);
- fn report_overflow_error_cycle(&self, cycle: &[PredicateObligation<'tcx>]) -> !;
+ fn report_overflow_obligation_cycle(&self, cycle: &[PredicateObligation<'tcx>]) -> !;
/// The `root_obligation` parameter should be the `root_obligation` field
/// from a `FulfillmentError`. If no `FulfillmentError` is available,
@@ -458,8 +468,10 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
/// occurrences in any case.
fn report_overflow_error<T>(
&self,
- obligation: &Obligation<'tcx, T>,
+ predicate: &T,
+ span: Span,
suggest_increasing_limit: bool,
+ mutate: impl FnOnce(&mut Diagnostic),
) -> !
where
T: fmt::Display
@@ -467,8 +479,9 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
+ Print<'tcx, FmtPrinter<'tcx, 'tcx>, Output = FmtPrinter<'tcx, 'tcx>>,
<T as Print<'tcx, FmtPrinter<'tcx, 'tcx>>>::Error: std::fmt::Debug,
{
- let predicate = self.resolve_vars_if_possible(obligation.predicate.clone());
+ let predicate = self.resolve_vars_if_possible(predicate.clone());
let mut pred_str = predicate.to_string();
+
if pred_str.len() > 50 {
// We don't need to save the type to a file, we will be talking about this type already
// in a separate note when we explain the obligation, so it will be available that way.
@@ -483,7 +496,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
}
let mut err = struct_span_err!(
self.tcx.sess,
- obligation.cause.span,
+ span,
E0275,
"overflow evaluating the requirement `{}`",
pred_str,
@@ -493,20 +506,46 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
self.suggest_new_overflow_limit(&mut err);
}
- self.note_obligation_cause_code(
- &mut err,
- &obligation.predicate,
- obligation.param_env,
- obligation.cause.code(),
- &mut vec![],
- &mut Default::default(),
- );
+ mutate(&mut err);
err.emit();
self.tcx.sess.abort_if_errors();
bug!();
}
+ /// Reports that an overflow has occurred and halts compilation. We
+ /// halt compilation unconditionally because it is important that
+ /// overflows never be masked -- they basically represent computations
+ /// whose result could not be truly determined and thus we can't say
+ /// if the program type checks or not -- and they are unusual
+ /// occurrences in any case.
+ fn report_overflow_obligation<T>(
+ &self,
+ obligation: &Obligation<'tcx, T>,
+ suggest_increasing_limit: bool,
+ ) -> !
+ where
+ T: ToPredicate<'tcx> + Clone,
+ {
+ let predicate = obligation.predicate.clone().to_predicate(self.tcx);
+ let predicate = self.resolve_vars_if_possible(predicate);
+ self.report_overflow_error(
+ &predicate,
+ obligation.cause.span,
+ suggest_increasing_limit,
+ |err| {
+ self.note_obligation_cause_code(
+ err,
+ &predicate,
+ obligation.param_env,
+ obligation.cause.code(),
+ &mut vec![],
+ &mut Default::default(),
+ );
+ },
+ );
+ }
+
fn suggest_new_overflow_limit(&self, err: &mut Diagnostic) {
let suggested_limit = match self.tcx.recursion_limit() {
Limit(0) => Limit(2),
@@ -521,11 +560,11 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
}
/// Reports that a cycle was detected which led to overflow and halts
- /// compilation. This is equivalent to `report_overflow_error` except
+ /// compilation. This is equivalent to `report_overflow_obligation` except
/// that we can give a more helpful error message (and, in particular,
/// we do not suggest increasing the overflow limit, which is not
/// going to help).
- fn report_overflow_error_cycle(&self, cycle: &[PredicateObligation<'tcx>]) -> ! {
+ fn report_overflow_obligation_cycle(&self, cycle: &[PredicateObligation<'tcx>]) -> ! {
let cycle = self.resolve_vars_if_possible(cycle.to_owned());
assert!(!cycle.is_empty());
@@ -533,7 +572,10 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
// The 'deepest' obligation is most likely to have a useful
// cause 'backtrace'
- self.report_overflow_error(cycle.iter().max_by_key(|p| p.recursion_depth).unwrap(), false);
+ self.report_overflow_obligation(
+ cycle.iter().max_by_key(|p| p.recursion_depth).unwrap(),
+ false,
+ );
}
fn report_selection_error(
@@ -1554,7 +1596,7 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
diag.emit();
}
FulfillmentErrorCode::CodeCycle(ref cycle) => {
- self.report_overflow_error_cycle(cycle);
+ self.report_overflow_obligation_cycle(cycle);
}
}
}
@@ -1607,7 +1649,7 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
| ObligationCauseCode::ObjectCastObligation(..)
| ObligationCauseCode::OpaqueType
);
- let expected_ty = data.term.ty().unwrap();
+ let expected_ty = data.term.ty().unwrap_or_else(|| self.tcx.ty_error());
// constrain inference variables a bit more to nested obligations from normalize so
// we can have more helpful errors.
@@ -1810,7 +1852,8 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
&self,
trait_pred: ty::PolyTraitPredicate<'tcx>,
) -> Vec<ImplCandidate<'tcx>> {
- self.tcx
+ let mut candidates: Vec<_> = self
+ .tcx
.all_impls(trait_pred.def_id())
.filter_map(|def_id| {
if self.tcx.impl_polarity(def_id) == ty::ImplPolarity::Negative
@@ -1826,7 +1869,14 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
self.fuzzy_match_tys(trait_pred.skip_binder().self_ty(), imp.self_ty(), false)
.map(|similarity| ImplCandidate { trait_ref: imp, similarity })
})
- .collect()
+ .collect();
+ if candidates.iter().any(|c| matches!(c.similarity, CandidateSimilarity::Exact { .. })) {
+ // If any of the candidates is a perfect match, we don't want to show all of them.
+ // This is particularly relevant for the case of numeric types (as they all have the
+ // same cathegory).
+ candidates.retain(|c| matches!(c.similarity, CandidateSimilarity::Exact { .. }));
+ }
+ candidates
}
fn report_similar_impl_candidates(
diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs
index 1740128727a..6ea54b625bb 100644
--- a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs
+++ b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs
@@ -298,7 +298,7 @@ pub trait TypeErrCtxtExt<'tcx> {
obligated_types: &mut Vec<Ty<'tcx>>,
seen_requirements: &mut FxHashSet<DefId>,
) where
- T: fmt::Display + ToPredicate<'tcx, T>;
+ T: fmt::Display + ToPredicate<'tcx>;
/// Suggest to await before try: future? => future.await?
fn suggest_await_before_try(
@@ -2353,7 +2353,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
obligated_types: &mut Vec<Ty<'tcx>>,
seen_requirements: &mut FxHashSet<DefId>,
) where
- T: fmt::Display,
+ T: fmt::Display + ToPredicate<'tcx>,
{
let tcx = self.tcx;
match *cause_code {
diff --git a/compiler/rustc_trait_selection/src/traits/mod.rs b/compiler/rustc_trait_selection/src/traits/mod.rs
index c6818a4e57d..d3cfd61e195 100644
--- a/compiler/rustc_trait_selection/src/traits/mod.rs
+++ b/compiler/rustc_trait_selection/src/traits/mod.rs
@@ -150,7 +150,7 @@ pub fn type_known_to_meet_bound_modulo_regions<'tcx>(
fn pred_known_to_hold_modulo_regions<'tcx>(
infcx: &InferCtxt<'tcx>,
param_env: ty::ParamEnv<'tcx>,
- pred: impl ToPredicate<'tcx, ty::Predicate<'tcx>> + TypeVisitable<'tcx>,
+ pred: impl ToPredicate<'tcx> + TypeVisitable<'tcx>,
span: Span,
) -> bool {
let has_non_region_infer = pred.has_non_region_infer();
diff --git a/compiler/rustc_trait_selection/src/traits/project.rs b/compiler/rustc_trait_selection/src/traits/project.rs
index 051660be9c4..5789754e4fc 100644
--- a/compiler/rustc_trait_selection/src/traits/project.rs
+++ b/compiler/rustc_trait_selection/src/traits/project.rs
@@ -504,14 +504,12 @@ impl<'a, 'b, 'tcx> TypeFolder<'tcx> for AssocTypeNormalizer<'a, 'b, 'tcx> {
Reveal::All => {
let recursion_limit = self.tcx().recursion_limit();
if !recursion_limit.value_within_limit(self.depth) {
- let obligation = Obligation::with_depth(
- self.tcx(),
- self.cause.clone(),
- recursion_limit.0,
- self.param_env,
- ty,
+ self.selcx.infcx.err_ctxt().report_overflow_error(
+ &ty,
+ self.cause.span,
+ true,
+ |_| {},
);
- self.selcx.infcx.err_ctxt().report_overflow_error(&obligation, true);
}
let substs = substs.fold_with(self);
@@ -2321,11 +2319,10 @@ fn assoc_ty_own_obligations<'cx, 'tcx>(
nested: &mut Vec<PredicateObligation<'tcx>>,
) {
let tcx = selcx.tcx();
- for predicate in tcx
+ let own = tcx
.predicates_of(obligation.predicate.item_def_id)
- .instantiate_own(tcx, obligation.predicate.substs)
- .predicates
- {
+ .instantiate_own(tcx, obligation.predicate.substs);
+ for (predicate, span) in std::iter::zip(own.predicates, own.spans) {
let normalized = normalize_with_depth_to(
selcx,
obligation.param_env,
@@ -2334,9 +2331,30 @@ fn assoc_ty_own_obligations<'cx, 'tcx>(
predicate,
nested,
);
+
+ let nested_cause = if matches!(
+ obligation.cause.code(),
+ super::CompareImplItemObligation { .. }
+ | super::CheckAssociatedTypeBounds { .. }
+ | super::AscribeUserTypeProvePredicate(..)
+ ) {
+ obligation.cause.clone()
+ } else if span.is_dummy() {
+ ObligationCause::new(
+ obligation.cause.span,
+ obligation.cause.body_id,
+ super::ItemObligation(obligation.predicate.item_def_id),
+ )
+ } else {
+ ObligationCause::new(
+ obligation.cause.span,
+ obligation.cause.body_id,
+ super::BindingObligation(obligation.predicate.item_def_id, span),
+ )
+ };
nested.push(Obligation::with_depth(
tcx,
- obligation.cause.clone(),
+ nested_cause,
obligation.recursion_depth + 1,
obligation.param_env,
normalized,
diff --git a/compiler/rustc_trait_selection/src/traits/query/normalize.rs b/compiler/rustc_trait_selection/src/traits/query/normalize.rs
index f899321fc01..7ad532d8a34 100644
--- a/compiler/rustc_trait_selection/src/traits/query/normalize.rs
+++ b/compiler/rustc_trait_selection/src/traits/query/normalize.rs
@@ -7,7 +7,7 @@ use crate::infer::canonical::OriginalQueryValues;
use crate::infer::{InferCtxt, InferOk};
use crate::traits::error_reporting::TypeErrCtxtExt;
use crate::traits::project::{needs_normalization, BoundVarReplacer, PlaceholderReplacer};
-use crate::traits::{Obligation, ObligationCause, PredicateObligation, Reveal};
+use crate::traits::{ObligationCause, PredicateObligation, Reveal};
use rustc_data_structures::sso::SsoHashMap;
use rustc_data_structures::stack::ensure_sufficient_stack;
use rustc_infer::traits::Normalized;
@@ -214,14 +214,12 @@ impl<'cx, 'tcx> FallibleTypeFolder<'tcx> for QueryNormalizer<'cx, 'tcx> {
let substs = substs.try_fold_with(self)?;
let recursion_limit = self.tcx().recursion_limit();
if !recursion_limit.value_within_limit(self.anon_depth) {
- let obligation = Obligation::with_depth(
- self.tcx(),
- self.cause.clone(),
- recursion_limit.0,
- self.param_env,
- ty,
+ self.infcx.err_ctxt().report_overflow_error(
+ &ty,
+ self.cause.span,
+ true,
+ |_| {},
);
- self.infcx.err_ctxt().report_overflow_error(&obligation, true);
}
let generic_ty = self.tcx().bound_type_of(def_id);
diff --git a/compiler/rustc_trait_selection/src/traits/select/mod.rs b/compiler/rustc_trait_selection/src/traits/select/mod.rs
index 8835f2cc1b9..035deb61639 100644
--- a/compiler/rustc_trait_selection/src/traits/select/mod.rs
+++ b/compiler/rustc_trait_selection/src/traits/select/mod.rs
@@ -43,7 +43,6 @@ use rustc_middle::mir::interpret::ErrorHandled;
use rustc_middle::ty::abstract_const::NotConstEvaluatable;
use rustc_middle::ty::fast_reject::{DeepRejectCtxt, TreatParams};
use rustc_middle::ty::fold::BottomUpFolder;
-use rustc_middle::ty::print::{FmtPrinter, Print};
use rustc_middle::ty::relate::TypeRelation;
use rustc_middle::ty::SubstsRef;
use rustc_middle::ty::{self, EarlyBinder, PolyProjectionPredicate, ToPolyTraitRef, ToPredicate};
@@ -1313,10 +1312,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
error_obligation: &Obligation<'tcx, T>,
) -> Result<(), OverflowError>
where
- T: fmt::Display
- + TypeFoldable<'tcx>
- + Print<'tcx, FmtPrinter<'tcx, 'tcx>, Output = FmtPrinter<'tcx, 'tcx>>,
- <T as Print<'tcx, FmtPrinter<'tcx, 'tcx>>>::Error: std::fmt::Debug,
+ T: ToPredicate<'tcx> + Clone,
{
if !self.infcx.tcx.recursion_limit().value_within_limit(depth) {
match self.query_mode {
@@ -1324,7 +1320,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
if let Some(e) = self.infcx.tainted_by_errors() {
return Err(OverflowError::Error(e));
}
- self.infcx.err_ctxt().report_overflow_error(error_obligation, true);
+ self.infcx.err_ctxt().report_overflow_obligation(error_obligation, true);
}
TraitQueryMode::Canonical => {
return Err(OverflowError::Canonical);
@@ -1345,10 +1341,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
error_obligation: &Obligation<'tcx, V>,
) -> Result<(), OverflowError>
where
- V: fmt::Display
- + TypeFoldable<'tcx>
- + Print<'tcx, FmtPrinter<'tcx, 'tcx>, Output = FmtPrinter<'tcx, 'tcx>>,
- <V as Print<'tcx, FmtPrinter<'tcx, 'tcx>>>::Error: std::fmt::Debug,
+ V: ToPredicate<'tcx> + Clone,
{
self.check_recursion_depth(obligation.recursion_depth, error_obligation)
}
diff --git a/compiler/rustc_trait_selection/src/traits/wf.rs b/compiler/rustc_trait_selection/src/traits/wf.rs
index 0855d6d1973..e47ba64245f 100644
--- a/compiler/rustc_trait_selection/src/traits/wf.rs
+++ b/compiler/rustc_trait_selection/src/traits/wf.rs
@@ -476,9 +476,24 @@ impl<'tcx> WfPredicates<'tcx> {
ty::Binder::dummy(ty::PredicateKind::WellFormed(ct.into())),
));
}
- // FIXME(generic_const_exprs): This seems wrong but I could not find a way to get this to trigger
ty::ConstKind::Expr(_) => {
- bug!("checking wfness of `ConstKind::Expr` is unsupported")
+ // FIXME(generic_const_exprs): this doesnt verify that given `Expr(N + 1)` the
+ // trait bound `typeof(N): Add<typeof(1)>` holds. This is currently unnecessary
+ // as `ConstKind::Expr` is only produced via normalization of `ConstKind::Unevaluated`
+ // which means that the `DefId` would have been typeck'd elsewhere. However in
+ // the future we may allow directly lowering to `ConstKind::Expr` in which case
+ // we would not be proving bounds we should.
+
+ let predicate =
+ ty::Binder::dummy(ty::PredicateKind::ConstEvaluatable(ct));
+ let cause = self.cause(traits::WellFormed(None));
+ self.out.push(traits::Obligation::with_depth(
+ self.tcx(),
+ cause,
+ self.recursion_depth,
+ self.param_env,
+ predicate,
+ ));
}
ty::ConstKind::Error(_)
diff --git a/compiler/rustc_type_ir/src/lib.rs b/compiler/rustc_type_ir/src/lib.rs
index 581993ba7d8..e3f7a1bd033 100644
--- a/compiler/rustc_type_ir/src/lib.rs
+++ b/compiler/rustc_type_ir/src/lib.rs
@@ -19,9 +19,11 @@ use std::mem::discriminant;
pub mod codec;
pub mod sty;
+pub mod ty_info;
pub use codec::*;
pub use sty::*;
+pub use ty_info::*;
/// Needed so we can use #[derive(HashStable_Generic)]
pub trait HashStableContext {}
diff --git a/compiler/rustc_type_ir/src/sty.rs b/compiler/rustc_type_ir/src/sty.rs
index 02cbb2e858f..3ed616d709b 100644
--- a/compiler/rustc_type_ir/src/sty.rs
+++ b/compiler/rustc_type_ir/src/sty.rs
@@ -301,61 +301,44 @@ impl<I: Interner> Clone for TyKind<I> {
impl<I: Interner> PartialEq for TyKind<I> {
#[inline]
fn eq(&self, other: &TyKind<I>) -> bool {
- let __self_vi = tykind_discriminant(self);
- let __arg_1_vi = tykind_discriminant(other);
- if __self_vi == __arg_1_vi {
- match (&*self, &*other) {
- (&Int(ref __self_0), &Int(ref __arg_1_0)) => __self_0 == __arg_1_0,
- (&Uint(ref __self_0), &Uint(ref __arg_1_0)) => __self_0 == __arg_1_0,
- (&Float(ref __self_0), &Float(ref __arg_1_0)) => __self_0 == __arg_1_0,
- (&Adt(ref __self_0, ref __self_1), &Adt(ref __arg_1_0, ref __arg_1_1)) => {
- __self_0 == __arg_1_0 && __self_1 == __arg_1_1
+ tykind_discriminant(self) == tykind_discriminant(other)
+ && match (self, other) {
+ (Int(a_i), Int(b_i)) => a_i == b_i,
+ (Uint(a_u), Uint(b_u)) => a_u == b_u,
+ (Float(a_f), Float(b_f)) => a_f == b_f,
+ (Adt(a_d, a_s), Adt(b_d, b_s)) => a_d == b_d && a_s == b_s,
+ (Foreign(a_d), Foreign(b_d)) => a_d == b_d,
+ (Array(a_t, a_c), Array(b_t, b_c)) => a_t == b_t && a_c == b_c,
+ (Slice(a_t), Slice(b_t)) => a_t == b_t,
+ (RawPtr(a_t), RawPtr(b_t)) => a_t == b_t,
+ (Ref(a_r, a_t, a_m), Ref(b_r, b_t, b_m)) => a_r == b_r && a_t == b_t && a_m == b_m,
+ (FnDef(a_d, a_s), FnDef(b_d, b_s)) => a_d == b_d && a_s == b_s,
+ (FnPtr(a_s), FnPtr(b_s)) => a_s == b_s,
+ (Dynamic(a_p, a_r, a_repr), Dynamic(b_p, b_r, b_repr)) => {
+ a_p == b_p && a_r == b_r && a_repr == b_repr
}
- (&Foreign(ref __self_0), &Foreign(ref __arg_1_0)) => __self_0 == __arg_1_0,
- (&Array(ref __self_0, ref __self_1), &Array(ref __arg_1_0, ref __arg_1_1)) => {
- __self_0 == __arg_1_0 && __self_1 == __arg_1_1
+ (Closure(a_d, a_s), Closure(b_d, b_s)) => a_d == b_d && a_s == b_s,
+ (Generator(a_d, a_s, a_m), Generator(b_d, b_s, b_m)) => {
+ a_d == b_d && a_s == b_s && a_m == b_m
}
- (&Slice(ref __self_0), &Slice(ref __arg_1_0)) => __self_0 == __arg_1_0,
- (&RawPtr(ref __self_0), &RawPtr(ref __arg_1_0)) => __self_0 == __arg_1_0,
- (
- &Ref(ref __self_0, ref __self_1, ref __self_2),
- &Ref(ref __arg_1_0, ref __arg_1_1, ref __arg_1_2),
- ) => __self_0 == __arg_1_0 && __self_1 == __arg_1_1 && __self_2 == __arg_1_2,
- (&FnDef(ref __self_0, ref __self_1), &FnDef(ref __arg_1_0, ref __arg_1_1)) => {
- __self_0 == __arg_1_0 && __self_1 == __arg_1_1
+ (GeneratorWitness(a_g), GeneratorWitness(b_g)) => a_g == b_g,
+ (Tuple(a_t), Tuple(b_t)) => a_t == b_t,
+ (Projection(a_p), Projection(b_p)) => a_p == b_p,
+ (Opaque(a_d, a_s), Opaque(b_d, b_s)) => a_d == b_d && a_s == b_s,
+ (Param(a_p), Param(b_p)) => a_p == b_p,
+ (Bound(a_d, a_b), Bound(b_d, b_b)) => a_d == b_d && a_b == b_b,
+ (Placeholder(a_p), Placeholder(b_p)) => a_p == b_p,
+ (Infer(a_t), Infer(b_t)) => a_t == b_t,
+ (Error(a_e), Error(b_e)) => a_e == b_e,
+ (Bool, Bool) | (Char, Char) | (Str, Str) | (Never, Never) => true,
+ _ => {
+ debug_assert!(
+ false,
+ "This branch must be unreachable, maybe the match is missing an arm? self = self = {self:?}, other = {other:?}"
+ );
+ true
}
- (&FnPtr(ref __self_0), &FnPtr(ref __arg_1_0)) => __self_0 == __arg_1_0,
- (
- &Dynamic(ref __self_0, ref __self_1, ref self_repr),
- &Dynamic(ref __arg_1_0, ref __arg_1_1, ref arg_repr),
- ) => __self_0 == __arg_1_0 && __self_1 == __arg_1_1 && self_repr == arg_repr,
- (&Closure(ref __self_0, ref __self_1), &Closure(ref __arg_1_0, ref __arg_1_1)) => {
- __self_0 == __arg_1_0 && __self_1 == __arg_1_1
- }
- (
- &Generator(ref __self_0, ref __self_1, ref __self_2),
- &Generator(ref __arg_1_0, ref __arg_1_1, ref __arg_1_2),
- ) => __self_0 == __arg_1_0 && __self_1 == __arg_1_1 && __self_2 == __arg_1_2,
- (&GeneratorWitness(ref __self_0), &GeneratorWitness(ref __arg_1_0)) => {
- __self_0 == __arg_1_0
- }
- (&Tuple(ref __self_0), &Tuple(ref __arg_1_0)) => __self_0 == __arg_1_0,
- (&Projection(ref __self_0), &Projection(ref __arg_1_0)) => __self_0 == __arg_1_0,
- (&Opaque(ref __self_0, ref __self_1), &Opaque(ref __arg_1_0, ref __arg_1_1)) => {
- __self_0 == __arg_1_0 && __self_1 == __arg_1_1
- }
- (&Param(ref __self_0), &Param(ref __arg_1_0)) => __self_0 == __arg_1_0,
- (&Bound(ref __self_0, ref __self_1), &Bound(ref __arg_1_0, ref __arg_1_1)) => {
- __self_0 == __arg_1_0 && __self_1 == __arg_1_1
- }
- (&Placeholder(ref __self_0), &Placeholder(ref __arg_1_0)) => __self_0 == __arg_1_0,
- (&Infer(ref __self_0), &Infer(ref __arg_1_0)) => __self_0 == __arg_1_0,
- (&Error(ref __self_0), &Error(ref __arg_1_0)) => __self_0 == __arg_1_0,
- _ => true,
}
- } else {
- false
- }
}
}
@@ -366,7 +349,7 @@ impl<I: Interner> Eq for TyKind<I> {}
impl<I: Interner> PartialOrd for TyKind<I> {
#[inline]
fn partial_cmp(&self, other: &TyKind<I>) -> Option<Ordering> {
- Some(Ord::cmp(self, other))
+ Some(self.cmp(other))
}
}
@@ -374,213 +357,106 @@ impl<I: Interner> PartialOrd for TyKind<I> {
impl<I: Interner> Ord for TyKind<I> {
#[inline]
fn cmp(&self, other: &TyKind<I>) -> Ordering {
- let __self_vi = tykind_discriminant(self);
- let __arg_1_vi = tykind_discriminant(other);
- if __self_vi == __arg_1_vi {
- match (&*self, &*other) {
- (&Int(ref __self_0), &Int(ref __arg_1_0)) => Ord::cmp(__self_0, __arg_1_0),
- (&Uint(ref __self_0), &Uint(ref __arg_1_0)) => Ord::cmp(__self_0, __arg_1_0),
- (&Float(ref __self_0), &Float(ref __arg_1_0)) => Ord::cmp(__self_0, __arg_1_0),
- (&Adt(ref __self_0, ref __self_1), &Adt(ref __arg_1_0, ref __arg_1_1)) => {
- match Ord::cmp(__self_0, __arg_1_0) {
- Ordering::Equal => Ord::cmp(__self_1, __arg_1_1),
- cmp => cmp,
- }
- }
- (&Foreign(ref __self_0), &Foreign(ref __arg_1_0)) => Ord::cmp(__self_0, __arg_1_0),
- (&Array(ref __self_0, ref __self_1), &Array(ref __arg_1_0, ref __arg_1_1)) => {
- match Ord::cmp(__self_0, __arg_1_0) {
- Ordering::Equal => Ord::cmp(__self_1, __arg_1_1),
- cmp => cmp,
- }
- }
- (&Slice(ref __self_0), &Slice(ref __arg_1_0)) => Ord::cmp(__self_0, __arg_1_0),
- (&RawPtr(ref __self_0), &RawPtr(ref __arg_1_0)) => Ord::cmp(__self_0, __arg_1_0),
- (
- &Ref(ref __self_0, ref __self_1, ref __self_2),
- &Ref(ref __arg_1_0, ref __arg_1_1, ref __arg_1_2),
- ) => match Ord::cmp(__self_0, __arg_1_0) {
- Ordering::Equal => match Ord::cmp(__self_1, __arg_1_1) {
- Ordering::Equal => Ord::cmp(__self_2, __arg_1_2),
- cmp => cmp,
- },
- cmp => cmp,
- },
- (&FnDef(ref __self_0, ref __self_1), &FnDef(ref __arg_1_0, ref __arg_1_1)) => {
- match Ord::cmp(__self_0, __arg_1_0) {
- Ordering::Equal => Ord::cmp(__self_1, __arg_1_1),
- cmp => cmp,
- }
+ tykind_discriminant(self).cmp(&tykind_discriminant(other)).then_with(|| {
+ match (self, other) {
+ (Int(a_i), Int(b_i)) => a_i.cmp(b_i),
+ (Uint(a_u), Uint(b_u)) => a_u.cmp(b_u),
+ (Float(a_f), Float(b_f)) => a_f.cmp(b_f),
+ (Adt(a_d, a_s), Adt(b_d, b_s)) => a_d.cmp(b_d).then_with(|| a_s.cmp(b_s)),
+ (Foreign(a_d), Foreign(b_d)) => a_d.cmp(b_d),
+ (Array(a_t, a_c), Array(b_t, b_c)) => a_t.cmp(b_t).then_with(|| a_c.cmp(b_c)),
+ (Slice(a_t), Slice(b_t)) => a_t.cmp(b_t),
+ (RawPtr(a_t), RawPtr(b_t)) => a_t.cmp(b_t),
+ (Ref(a_r, a_t, a_m), Ref(b_r, b_t, b_m)) => {
+ a_r.cmp(b_r).then_with(|| a_t.cmp(b_t).then_with(|| a_m.cmp(b_m)))
}
- (&FnPtr(ref __self_0), &FnPtr(ref __arg_1_0)) => Ord::cmp(__self_0, __arg_1_0),
- (
- &Dynamic(ref __self_0, ref __self_1, ref self_repr),
- &Dynamic(ref __arg_1_0, ref __arg_1_1, ref arg_repr),
- ) => match Ord::cmp(__self_0, __arg_1_0) {
- Ordering::Equal => match Ord::cmp(__self_1, __arg_1_1) {
- Ordering::Equal => Ord::cmp(self_repr, arg_repr),
- cmp => cmp,
- },
- cmp => cmp,
- },
- (&Closure(ref __self_0, ref __self_1), &Closure(ref __arg_1_0, ref __arg_1_1)) => {
- match Ord::cmp(__self_0, __arg_1_0) {
- Ordering::Equal => Ord::cmp(__self_1, __arg_1_1),
- cmp => cmp,
- }
+ (FnDef(a_d, a_s), FnDef(b_d, b_s)) => a_d.cmp(b_d).then_with(|| a_s.cmp(b_s)),
+ (FnPtr(a_s), FnPtr(b_s)) => a_s.cmp(b_s),
+ (Dynamic(a_p, a_r, a_repr), Dynamic(b_p, b_r, b_repr)) => {
+ a_p.cmp(b_p).then_with(|| a_r.cmp(b_r).then_with(|| a_repr.cmp(b_repr)))
}
- (
- &Generator(ref __self_0, ref __self_1, ref __self_2),
- &Generator(ref __arg_1_0, ref __arg_1_1, ref __arg_1_2),
- ) => match Ord::cmp(__self_0, __arg_1_0) {
- Ordering::Equal => match Ord::cmp(__self_1, __arg_1_1) {
- Ordering::Equal => Ord::cmp(__self_2, __arg_1_2),
- cmp => cmp,
- },
- cmp => cmp,
- },
- (&GeneratorWitness(ref __self_0), &GeneratorWitness(ref __arg_1_0)) => {
- Ord::cmp(__self_0, __arg_1_0)
+ (Closure(a_p, a_s), Closure(b_p, b_s)) => a_p.cmp(b_p).then_with(|| a_s.cmp(b_s)),
+ (Generator(a_d, a_s, a_m), Generator(b_d, b_s, b_m)) => {
+ a_d.cmp(b_d).then_with(|| a_s.cmp(b_s).then_with(|| a_m.cmp(b_m)))
}
- (&Tuple(ref __self_0), &Tuple(ref __arg_1_0)) => Ord::cmp(__self_0, __arg_1_0),
- (&Projection(ref __self_0), &Projection(ref __arg_1_0)) => {
- Ord::cmp(__self_0, __arg_1_0)
+ (GeneratorWitness(a_g), GeneratorWitness(b_g)) => a_g.cmp(b_g),
+ (Tuple(a_t), Tuple(b_t)) => a_t.cmp(b_t),
+ (Projection(a_p), Projection(b_p)) => a_p.cmp(b_p),
+ (Opaque(a_d, a_s), Opaque(b_d, b_s)) => a_d.cmp(b_d).then_with(|| a_s.cmp(b_s)),
+ (Param(a_p), Param(b_p)) => a_p.cmp(b_p),
+ (Bound(a_d, a_b), Bound(b_d, b_b)) => a_d.cmp(b_d).then_with(|| a_b.cmp(b_b)),
+ (Placeholder(a_p), Placeholder(b_p)) => a_p.cmp(b_p),
+ (Infer(a_t), Infer(b_t)) => a_t.cmp(b_t),
+ (Error(a_e), Error(b_e)) => a_e.cmp(b_e),
+ (Bool, Bool) | (Char, Char) | (Str, Str) | (Never, Never) => Ordering::Equal,
+ _ => {
+ debug_assert!(false, "This branch must be unreachable, maybe the match is missing an arm? self = self = {self:?}, other = {other:?}");
+ Ordering::Equal
}
- (&Opaque(ref __self_0, ref __self_1), &Opaque(ref __arg_1_0, ref __arg_1_1)) => {
- match Ord::cmp(__self_0, __arg_1_0) {
- Ordering::Equal => Ord::cmp(__self_1, __arg_1_1),
- cmp => cmp,
- }
- }
- (&Param(ref __self_0), &Param(ref __arg_1_0)) => Ord::cmp(__self_0, __arg_1_0),
- (&Bound(ref __self_0, ref __self_1), &Bound(ref __arg_1_0, ref __arg_1_1)) => {
- match Ord::cmp(__self_0, __arg_1_0) {
- Ordering::Equal => Ord::cmp(__self_1, __arg_1_1),
- cmp => cmp,
- }
- }
- (&Placeholder(ref __self_0), &Placeholder(ref __arg_1_0)) => {
- Ord::cmp(__self_0, __arg_1_0)
- }
- (&Infer(ref __self_0), &Infer(ref __arg_1_0)) => Ord::cmp(__self_0, __arg_1_0),
- (&Error(ref __self_0), &Error(ref __arg_1_0)) => Ord::cmp(__self_0, __arg_1_0),
- _ => Ordering::Equal,
}
- } else {
- Ord::cmp(&__self_vi, &__arg_1_vi)
- }
+ })
}
}
// This is manually implemented because a derive would require `I: Hash`
impl<I: Interner> hash::Hash for TyKind<I> {
fn hash<__H: hash::Hasher>(&self, state: &mut __H) -> () {
- match (&*self,) {
- (&Int(ref __self_0),) => {
- hash::Hash::hash(&tykind_discriminant(self), state);
- hash::Hash::hash(__self_0, state)
- }
- (&Uint(ref __self_0),) => {
- hash::Hash::hash(&tykind_discriminant(self), state);
- hash::Hash::hash(__self_0, state)
- }
- (&Float(ref __self_0),) => {
- hash::Hash::hash(&tykind_discriminant(self), state);
- hash::Hash::hash(__self_0, state)
- }
- (&Adt(ref __self_0, ref __self_1),) => {
- hash::Hash::hash(&tykind_discriminant(self), state);
- hash::Hash::hash(__self_0, state);
- hash::Hash::hash(__self_1, state)
- }
- (&Foreign(ref __self_0),) => {
- hash::Hash::hash(&tykind_discriminant(self), state);
- hash::Hash::hash(__self_0, state)
- }
- (&Array(ref __self_0, ref __self_1),) => {
- hash::Hash::hash(&tykind_discriminant(self), state);
- hash::Hash::hash(__self_0, state);
- hash::Hash::hash(__self_1, state)
- }
- (&Slice(ref __self_0),) => {
- hash::Hash::hash(&tykind_discriminant(self), state);
- hash::Hash::hash(__self_0, state)
- }
- (&RawPtr(ref __self_0),) => {
- hash::Hash::hash(&tykind_discriminant(self), state);
- hash::Hash::hash(__self_0, state)
- }
- (&Ref(ref __self_0, ref __self_1, ref __self_2),) => {
- hash::Hash::hash(&tykind_discriminant(self), state);
- hash::Hash::hash(__self_0, state);
- hash::Hash::hash(__self_1, state);
- hash::Hash::hash(__self_2, state)
- }
- (&FnDef(ref __self_0, ref __self_1),) => {
- hash::Hash::hash(&tykind_discriminant(self), state);
- hash::Hash::hash(__self_0, state);
- hash::Hash::hash(__self_1, state)
- }
- (&FnPtr(ref __self_0),) => {
- hash::Hash::hash(&tykind_discriminant(self), state);
- hash::Hash::hash(__self_0, state)
- }
- (&Dynamic(ref __self_0, ref __self_1, ref repr),) => {
- hash::Hash::hash(&tykind_discriminant(self), state);
- hash::Hash::hash(__self_0, state);
- hash::Hash::hash(__self_1, state);
- hash::Hash::hash(repr, state)
- }
- (&Closure(ref __self_0, ref __self_1),) => {
- hash::Hash::hash(&tykind_discriminant(self), state);
- hash::Hash::hash(__self_0, state);
- hash::Hash::hash(__self_1, state)
- }
- (&Generator(ref __self_0, ref __self_1, ref __self_2),) => {
- hash::Hash::hash(&tykind_discriminant(self), state);
- hash::Hash::hash(__self_0, state);
- hash::Hash::hash(__self_1, state);
- hash::Hash::hash(__self_2, state)
- }
- (&GeneratorWitness(ref __self_0),) => {
- hash::Hash::hash(&tykind_discriminant(self), state);
- hash::Hash::hash(__self_0, state)
- }
- (&Tuple(ref __self_0),) => {
- hash::Hash::hash(&tykind_discriminant(self), state);
- hash::Hash::hash(__self_0, state)
- }
- (&Projection(ref __self_0),) => {
- hash::Hash::hash(&tykind_discriminant(self), state);
- hash::Hash::hash(__self_0, state)
- }
- (&Opaque(ref __self_0, ref __self_1),) => {
- hash::Hash::hash(&tykind_discriminant(self), state);
- hash::Hash::hash(__self_0, state);
- hash::Hash::hash(__self_1, state)
- }
- (&Param(ref __self_0),) => {
- hash::Hash::hash(&tykind_discriminant(self), state);
- hash::Hash::hash(__self_0, state)
- }
- (&Bound(ref __self_0, ref __self_1),) => {
- hash::Hash::hash(&tykind_discriminant(self), state);
- hash::Hash::hash(__self_0, state);
- hash::Hash::hash(__self_1, state)
- }
- (&Placeholder(ref __self_0),) => {
- hash::Hash::hash(&tykind_discriminant(self), state);
- hash::Hash::hash(__self_0, state)
- }
- (&Infer(ref __self_0),) => {
- hash::Hash::hash(&tykind_discriminant(self), state);
- hash::Hash::hash(__self_0, state)
+ tykind_discriminant(self).hash(state);
+ match self {
+ Int(i) => i.hash(state),
+ Uint(u) => u.hash(state),
+ Float(f) => f.hash(state),
+ Adt(d, s) => {
+ d.hash(state);
+ s.hash(state)
+ }
+ Foreign(d) => d.hash(state),
+ Array(t, c) => {
+ t.hash(state);
+ c.hash(state)
}
- (&Error(ref __self_0),) => {
- hash::Hash::hash(&tykind_discriminant(self), state);
- hash::Hash::hash(__self_0, state)
+ Slice(t) => t.hash(state),
+ RawPtr(t) => t.hash(state),
+ Ref(r, t, m) => {
+ r.hash(state);
+ t.hash(state);
+ m.hash(state)
+ }
+ FnDef(d, s) => {
+ d.hash(state);
+ s.hash(state)
+ }
+ FnPtr(s) => s.hash(state),
+ Dynamic(p, r, repr) => {
+ p.hash(state);
+ r.hash(state);
+ repr.hash(state)
+ }
+ Closure(d, s) => {
+ d.hash(state);
+ s.hash(state)
+ }
+ Generator(d, s, m) => {
+ d.hash(state);
+ s.hash(state);
+ m.hash(state)
+ }
+ GeneratorWitness(g) => g.hash(state),
+ Tuple(t) => t.hash(state),
+ Projection(p) => p.hash(state),
+ Opaque(d, s) => {
+ d.hash(state);
+ s.hash(state)
+ }
+ Param(p) => p.hash(state),
+ Bound(d, b) => {
+ d.hash(state);
+ b.hash(state)
}
- _ => hash::Hash::hash(&tykind_discriminant(self), state),
+ Placeholder(p) => p.hash(state),
+ Infer(t) => t.hash(state),
+ Error(e) => e.hash(state),
+ Bool | Char | Str | Never => (),
}
}
}
@@ -588,37 +464,34 @@ impl<I: Interner> hash::Hash for TyKind<I> {
// This is manually implemented because a derive would require `I: Debug`
impl<I: Interner> fmt::Debug for TyKind<I> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
- use std::fmt::*;
match self {
- Bool => Formatter::write_str(f, "Bool"),
- Char => Formatter::write_str(f, "Char"),
- Int(f0) => Formatter::debug_tuple_field1_finish(f, "Int", f0),
- Uint(f0) => Formatter::debug_tuple_field1_finish(f, "Uint", f0),
- Float(f0) => Formatter::debug_tuple_field1_finish(f, "Float", f0),
- Adt(f0, f1) => Formatter::debug_tuple_field2_finish(f, "Adt", f0, f1),
- Foreign(f0) => Formatter::debug_tuple_field1_finish(f, "Foreign", f0),
- Str => Formatter::write_str(f, "Str"),
- Array(f0, f1) => Formatter::debug_tuple_field2_finish(f, "Array", f0, f1),
- Slice(f0) => Formatter::debug_tuple_field1_finish(f, "Slice", f0),
- RawPtr(f0) => Formatter::debug_tuple_field1_finish(f, "RawPtr", f0),
- Ref(f0, f1, f2) => Formatter::debug_tuple_field3_finish(f, "Ref", f0, f1, f2),
- FnDef(f0, f1) => Formatter::debug_tuple_field2_finish(f, "FnDef", f0, f1),
- FnPtr(f0) => Formatter::debug_tuple_field1_finish(f, "FnPtr", f0),
- Dynamic(f0, f1, f2) => Formatter::debug_tuple_field3_finish(f, "Dynamic", f0, f1, f2),
- Closure(f0, f1) => Formatter::debug_tuple_field2_finish(f, "Closure", f0, f1),
- Generator(f0, f1, f2) => {
- Formatter::debug_tuple_field3_finish(f, "Generator", f0, f1, f2)
- }
- GeneratorWitness(f0) => Formatter::debug_tuple_field1_finish(f, "GeneratorWitness", f0),
- Never => Formatter::write_str(f, "Never"),
- Tuple(f0) => Formatter::debug_tuple_field1_finish(f, "Tuple", f0),
- Projection(f0) => Formatter::debug_tuple_field1_finish(f, "Projection", f0),
- Opaque(f0, f1) => Formatter::debug_tuple_field2_finish(f, "Opaque", f0, f1),
- Param(f0) => Formatter::debug_tuple_field1_finish(f, "Param", f0),
- Bound(f0, f1) => Formatter::debug_tuple_field2_finish(f, "Bound", f0, f1),
- Placeholder(f0) => Formatter::debug_tuple_field1_finish(f, "Placeholder", f0),
- Infer(f0) => Formatter::debug_tuple_field1_finish(f, "Infer", f0),
- TyKind::Error(f0) => Formatter::debug_tuple_field1_finish(f, "Error", f0),
+ Bool => f.write_str("Bool"),
+ Char => f.write_str("Char"),
+ Int(i) => f.debug_tuple_field1_finish("Int", i),
+ Uint(u) => f.debug_tuple_field1_finish("Uint", u),
+ Float(float) => f.debug_tuple_field1_finish("Float", float),
+ Adt(d, s) => f.debug_tuple_field2_finish("Adt", d, s),
+ Foreign(d) => f.debug_tuple_field1_finish("Foreign", d),
+ Str => f.write_str("Str"),
+ Array(t, c) => f.debug_tuple_field2_finish("Array", t, c),
+ Slice(t) => f.debug_tuple_field1_finish("Slice", t),
+ RawPtr(t) => f.debug_tuple_field1_finish("RawPtr", t),
+ Ref(r, t, m) => f.debug_tuple_field3_finish("Ref", r, t, m),
+ FnDef(d, s) => f.debug_tuple_field2_finish("FnDef", d, s),
+ FnPtr(s) => f.debug_tuple_field1_finish("FnPtr", s),
+ Dynamic(p, r, repr) => f.debug_tuple_field3_finish("Dynamic", p, r, repr),
+ Closure(d, s) => f.debug_tuple_field2_finish("Closure", d, s),
+ Generator(d, s, m) => f.debug_tuple_field3_finish("Generator", d, s, m),
+ GeneratorWitness(g) => f.debug_tuple_field1_finish("GeneratorWitness", g),
+ Never => f.write_str("Never"),
+ Tuple(t) => f.debug_tuple_field1_finish("Tuple", t),
+ Projection(p) => f.debug_tuple_field1_finish("Projection", p),
+ Opaque(d, s) => f.debug_tuple_field2_finish("Opaque", d, s),
+ Param(p) => f.debug_tuple_field1_finish("Param", p),
+ Bound(d, b) => f.debug_tuple_field2_finish("Bound", d, b),
+ Placeholder(p) => f.debug_tuple_field1_finish("Placeholder", p),
+ Infer(t) => f.debug_tuple_field1_finish("Infer", t),
+ TyKind::Error(e) => f.debug_tuple_field1_finish("Error", e),
}
}
}
@@ -1091,12 +964,12 @@ where
impl<I: Interner> Clone for RegionKind<I> {
fn clone(&self) -> Self {
match self {
- ReEarlyBound(a) => ReEarlyBound(a.clone()),
- ReLateBound(a, b) => ReLateBound(a.clone(), b.clone()),
- ReFree(a) => ReFree(a.clone()),
+ ReEarlyBound(r) => ReEarlyBound(r.clone()),
+ ReLateBound(d, r) => ReLateBound(d.clone(), r.clone()),
+ ReFree(r) => ReFree(r.clone()),
ReStatic => ReStatic,
- ReVar(a) => ReVar(a.clone()),
- RePlaceholder(a) => RePlaceholder(a.clone()),
+ ReVar(r) => ReVar(r.clone()),
+ RePlaceholder(r) => RePlaceholder(r.clone()),
ReErased => ReErased,
}
}
@@ -1106,29 +979,23 @@ impl<I: Interner> Clone for RegionKind<I> {
impl<I: Interner> PartialEq for RegionKind<I> {
#[inline]
fn eq(&self, other: &RegionKind<I>) -> bool {
- let __self_vi = regionkind_discriminant(self);
- let __arg_1_vi = regionkind_discriminant(other);
- if __self_vi == __arg_1_vi {
- match (&*self, &*other) {
- (&ReEarlyBound(ref __self_0), &ReEarlyBound(ref __arg_1_0)) => {
- __self_0 == __arg_1_0
+ regionkind_discriminant(self) == regionkind_discriminant(other)
+ && match (self, other) {
+ (ReEarlyBound(a_r), ReEarlyBound(b_r)) => a_r == b_r,
+ (ReLateBound(a_d, a_r), ReLateBound(b_d, b_r)) => a_d == b_d && a_r == b_r,
+ (ReFree(a_r), ReFree(b_r)) => a_r == b_r,
+ (ReStatic, ReStatic) => true,
+ (ReVar(a_r), ReVar(b_r)) => a_r == b_r,
+ (RePlaceholder(a_r), RePlaceholder(b_r)) => a_r == b_r,
+ (ReErased, ReErased) => true,
+ _ => {
+ debug_assert!(
+ false,
+ "This branch must be unreachable, maybe the match is missing an arm? self = self = {self:?}, other = {other:?}"
+ );
+ true
}
- (
- &ReLateBound(ref __self_0, ref __self_1),
- &ReLateBound(ref __arg_1_0, ref __arg_1_1),
- ) => __self_0 == __arg_1_0 && __self_1 == __arg_1_1,
- (&ReFree(ref __self_0), &ReFree(ref __arg_1_0)) => __self_0 == __arg_1_0,
- (&ReStatic, &ReStatic) => true,
- (&ReVar(ref __self_0), &ReVar(ref __arg_1_0)) => __self_0 == __arg_1_0,
- (&RePlaceholder(ref __self_0), &RePlaceholder(ref __arg_1_0)) => {
- __self_0 == __arg_1_0
- }
- (&ReErased, &ReErased) => true,
- _ => true,
}
- } else {
- false
- }
}
}
@@ -1139,7 +1006,7 @@ impl<I: Interner> Eq for RegionKind<I> {}
impl<I: Interner> PartialOrd for RegionKind<I> {
#[inline]
fn partial_cmp(&self, other: &RegionKind<I>) -> Option<Ordering> {
- Some(Ord::cmp(self, other))
+ Some(self.cmp(other))
}
}
@@ -1147,66 +1014,41 @@ impl<I: Interner> PartialOrd for RegionKind<I> {
impl<I: Interner> Ord for RegionKind<I> {
#[inline]
fn cmp(&self, other: &RegionKind<I>) -> Ordering {
- let __self_vi = regionkind_discriminant(self);
- let __arg_1_vi = regionkind_discriminant(other);
- if __self_vi == __arg_1_vi {
- match (&*self, &*other) {
- (&ReEarlyBound(ref __self_0), &ReEarlyBound(ref __arg_1_0)) => {
- Ord::cmp(__self_0, __arg_1_0)
+ regionkind_discriminant(self).cmp(&regionkind_discriminant(other)).then_with(|| {
+ match (self, other) {
+ (ReEarlyBound(a_r), ReEarlyBound(b_r)) => a_r.cmp(b_r),
+ (ReLateBound(a_d, a_r), ReLateBound(b_d, b_r)) => {
+ a_d.cmp(b_d).then_with(|| a_r.cmp(b_r))
}
- (
- &ReLateBound(ref __self_0, ref __self_1),
- &ReLateBound(ref __arg_1_0, ref __arg_1_1),
- ) => match Ord::cmp(__self_0, __arg_1_0) {
- Ordering::Equal => Ord::cmp(__self_1, __arg_1_1),
- cmp => cmp,
- },
- (&ReFree(ref __self_0), &ReFree(ref __arg_1_0)) => Ord::cmp(__self_0, __arg_1_0),
- (&ReStatic, &ReStatic) => Ordering::Equal,
- (&ReVar(ref __self_0), &ReVar(ref __arg_1_0)) => Ord::cmp(__self_0, __arg_1_0),
- (&RePlaceholder(ref __self_0), &RePlaceholder(ref __arg_1_0)) => {
- Ord::cmp(__self_0, __arg_1_0)
+ (ReFree(a_r), ReFree(b_r)) => a_r.cmp(b_r),
+ (ReStatic, ReStatic) => Ordering::Equal,
+ (ReVar(a_r), ReVar(b_r)) => a_r.cmp(b_r),
+ (RePlaceholder(a_r), RePlaceholder(b_r)) => a_r.cmp(b_r),
+ (ReErased, ReErased) => Ordering::Equal,
+ _ => {
+ debug_assert!(false, "This branch must be unreachable, maybe the match is missing an arm? self = self = {self:?}, other = {other:?}");
+ Ordering::Equal
}
- (&ReErased, &ReErased) => Ordering::Equal,
- _ => Ordering::Equal,
}
- } else {
- Ord::cmp(&__self_vi, &__arg_1_vi)
- }
+ })
}
}
// This is manually implemented because a derive would require `I: Hash`
impl<I: Interner> hash::Hash for RegionKind<I> {
- fn hash<__H: hash::Hasher>(&self, state: &mut __H) -> () {
- match (&*self,) {
- (&ReEarlyBound(ref __self_0),) => {
- hash::Hash::hash(&regionkind_discriminant(self), state);
- hash::Hash::hash(__self_0, state)
- }
- (&ReLateBound(ref __self_0, ref __self_1),) => {
- hash::Hash::hash(&regionkind_discriminant(self), state);
- hash::Hash::hash(__self_0, state);
- hash::Hash::hash(__self_1, state)
- }
- (&ReFree(ref __self_0),) => {
- hash::Hash::hash(&regionkind_discriminant(self), state);
- hash::Hash::hash(__self_0, state)
- }
- (&ReStatic,) => {
- hash::Hash::hash(&regionkind_discriminant(self), state);
- }
- (&ReVar(ref __self_0),) => {
- hash::Hash::hash(&regionkind_discriminant(self), state);
- hash::Hash::hash(__self_0, state)
- }
- (&RePlaceholder(ref __self_0),) => {
- hash::Hash::hash(&regionkind_discriminant(self), state);
- hash::Hash::hash(__self_0, state)
- }
- (&ReErased,) => {
- hash::Hash::hash(&regionkind_discriminant(self), state);
- }
+ fn hash<H: hash::Hasher>(&self, state: &mut H) -> () {
+ regionkind_discriminant(self).hash(state);
+ match self {
+ ReEarlyBound(r) => r.hash(state),
+ ReLateBound(d, r) => {
+ d.hash(state);
+ r.hash(state)
+ }
+ ReFree(r) => r.hash(state),
+ ReStatic => (),
+ ReVar(r) => r.hash(state),
+ RePlaceholder(r) => r.hash(state),
+ ReErased => (),
}
}
}
@@ -1215,21 +1057,21 @@ impl<I: Interner> hash::Hash for RegionKind<I> {
impl<I: Interner> fmt::Debug for RegionKind<I> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
- ReEarlyBound(ref data) => write!(f, "ReEarlyBound({:?})", data),
+ ReEarlyBound(data) => write!(f, "ReEarlyBound({:?})", data),
- ReLateBound(binder_id, ref bound_region) => {
+ ReLateBound(binder_id, bound_region) => {
write!(f, "ReLateBound({:?}, {:?})", binder_id, bound_region)
}
- ReFree(ref fr) => fr.fmt(f),
+ ReFree(fr) => fr.fmt(f),
- ReStatic => write!(f, "ReStatic"),
+ ReStatic => f.write_str("ReStatic"),
- ReVar(ref vid) => vid.fmt(f),
+ ReVar(vid) => vid.fmt(f),
RePlaceholder(placeholder) => write!(f, "RePlaceholder({:?})", placeholder),
- ReErased => write!(f, "ReErased"),
+ ReErased => f.write_str("ReErased"),
}
}
}
@@ -1317,18 +1159,18 @@ where
ReErased | ReStatic => {
// No variant fields to hash for these ...
}
- ReLateBound(db, br) => {
- db.hash_stable(hcx, hasher);
- br.hash_stable(hcx, hasher);
+ ReLateBound(d, r) => {
+ d.hash_stable(hcx, hasher);
+ r.hash_stable(hcx, hasher);
}
- ReEarlyBound(eb) => {
- eb.hash_stable(hcx, hasher);
+ ReEarlyBound(r) => {
+ r.hash_stable(hcx, hasher);
}
- ReFree(ref free_region) => {
- free_region.hash_stable(hcx, hasher);
+ ReFree(r) => {
+ r.hash_stable(hcx, hasher);
}
- RePlaceholder(p) => {
- p.hash_stable(hcx, hasher);
+ RePlaceholder(r) => {
+ r.hash_stable(hcx, hasher);
}
ReVar(_) => {
panic!("region variables should not be hashed: {self:?}")
diff --git a/compiler/rustc_type_ir/src/ty_info.rs b/compiler/rustc_type_ir/src/ty_info.rs
new file mode 100644
index 00000000000..4e5d424886a
--- /dev/null
+++ b/compiler/rustc_type_ir/src/ty_info.rs
@@ -0,0 +1,122 @@
+use std::{
+ cmp::Ordering,
+ hash::{Hash, Hasher},
+ ops::Deref,
+};
+
+use rustc_data_structures::{
+ fingerprint::Fingerprint,
+ stable_hasher::{HashStable, StableHasher},
+};
+
+use crate::{DebruijnIndex, TypeFlags};
+
+/// A helper type that you can wrap round your own type in order to automatically
+/// cache the stable hash, type flags and debruijn index on creation and
+/// not recompute it whenever the information is needed.
+/// This is only done in incremental mode. You can also opt out of caching by using
+/// StableHash::ZERO for the hash, in which case the hash gets computed each time.
+/// This is useful if you have values that you intern but never (can?) use for stable
+/// hashing.
+#[derive(Copy, Clone)]
+pub struct WithCachedTypeInfo<T> {
+ pub internee: T,
+ pub stable_hash: Fingerprint,
+
+ /// This field provides fast access to information that is also contained
+ /// in `kind`.
+ ///
+ /// This field shouldn't be used directly and may be removed in the future.
+ /// Use `Ty::flags()` instead.
+ pub flags: TypeFlags,
+
+ /// This field provides fast access to information that is also contained
+ /// in `kind`.
+ ///
+ /// This is a kind of confusing thing: it stores the smallest
+ /// binder such that
+ ///
+ /// (a) the binder itself captures nothing but
+ /// (b) all the late-bound things within the type are captured
+ /// by some sub-binder.
+ ///
+ /// So, for a type without any late-bound things, like `u32`, this
+ /// will be *innermost*, because that is the innermost binder that
+ /// captures nothing. But for a type `&'D u32`, where `'D` is a
+ /// late-bound region with De Bruijn index `D`, this would be `D + 1`
+ /// -- the binder itself does not capture `D`, but `D` is captured
+ /// by an inner binder.
+ ///
+ /// We call this concept an "exclusive" binder `D` because all
+ /// De Bruijn indices within the type are contained within `0..D`
+ /// (exclusive).
+ pub outer_exclusive_binder: DebruijnIndex,
+}
+
+impl<T: PartialEq> PartialEq for WithCachedTypeInfo<T> {
+ #[inline]
+ fn eq(&self, other: &Self) -> bool {
+ self.internee.eq(&other.internee)
+ }
+}
+
+impl<T: Eq> Eq for WithCachedTypeInfo<T> {}
+
+impl<T: Ord> PartialOrd for WithCachedTypeInfo<T> {
+ fn partial_cmp(&self, other: &WithCachedTypeInfo<T>) -> Option<Ordering> {
+ Some(self.internee.cmp(&other.internee))
+ }
+}
+
+impl<T: Ord> Ord for WithCachedTypeInfo<T> {
+ fn cmp(&self, other: &WithCachedTypeInfo<T>) -> Ordering {
+ self.internee.cmp(&other.internee)
+ }
+}
+
+impl<T> Deref for WithCachedTypeInfo<T> {
+ type Target = T;
+
+ #[inline]
+ fn deref(&self) -> &T {
+ &self.internee
+ }
+}
+
+impl<T: Hash> Hash for WithCachedTypeInfo<T> {
+ #[inline]
+ fn hash<H: Hasher>(&self, s: &mut H) {
+ if self.stable_hash != Fingerprint::ZERO {
+ self.stable_hash.hash(s)
+ } else {
+ self.internee.hash(s)
+ }
+ }
+}
+
+impl<T: HashStable<CTX>, CTX> HashStable<CTX> for WithCachedTypeInfo<T> {
+ fn hash_stable(&self, hcx: &mut CTX, hasher: &mut StableHasher) {
+ if self.stable_hash == Fingerprint::ZERO || cfg!(debug_assertions) {
+ // No cached hash available. This can only mean that incremental is disabled.
+ // We don't cache stable hashes in non-incremental mode, because they are used
+ // so rarely that the performance actually suffers.
+
+ // We need to build the hash as if we cached it and then hash that hash, as
+ // otherwise the hashes will differ between cached and non-cached mode.
+ let stable_hash: Fingerprint = {
+ let mut hasher = StableHasher::new();
+ self.internee.hash_stable(hcx, &mut hasher);
+ hasher.finish()
+ };
+ if cfg!(debug_assertions) && self.stable_hash != Fingerprint::ZERO {
+ assert_eq!(
+ stable_hash, self.stable_hash,
+ "cached stable hash does not match freshly computed stable hash"
+ );
+ }
+ stable_hash.hash_stable(hcx, hasher);
+ } else {
+ self.stable_hash.hash_stable(hcx, hasher);
+ }
+ }
+}
diff --git a/config.toml.example b/config.toml.example
index c94a27b12a3..ca54cbd2d68 100644
--- a/config.toml.example
+++ b/config.toml.example
@@ -255,6 +255,16 @@ changelog-seen = 2
# Defaults to the Python interpreter used to execute x.py
#python = "python"
+# The path to the REUSE executable to use. Note that REUSE is not required in
+# most cases, as our tooling relies on a cached (and shrinked) copy of the
+# REUSE output present in the git repository and in our source tarballs.
+#
+# REUSE is only needed if your changes caused the overral licensing of the
+# repository to change, and the cached copy has to be regenerated.
+#
+# Defaults to the "reuse" command in the system path.
+#reuse = "reuse"
+
# Force Cargo to check that Cargo.lock describes the precise dependency
# set that all the Cargo.toml files create, instead of updating it.
#locked-deps = false
diff --git a/library/alloc/src/collections/vec_deque/mod.rs b/library/alloc/src/collections/vec_deque/mod.rs
index ee8032ad6f0..4866c53e7d5 100644
--- a/library/alloc/src/collections/vec_deque/mod.rs
+++ b/library/alloc/src/collections/vec_deque/mod.rs
@@ -2699,12 +2699,18 @@ impl<T, A: Allocator> IndexMut<usize> for VecDeque<T, A> {
#[stable(feature = "rust1", since = "1.0.0")]
impl<T> FromIterator<T> for VecDeque<T> {
+ #[inline]
fn from_iter<I: IntoIterator<Item = T>>(iter: I) -> VecDeque<T> {
- let iterator = iter.into_iter();
- let (lower, _) = iterator.size_hint();
- let mut deq = VecDeque::with_capacity(lower);
- deq.extend(iterator);
- deq
+ // Since converting is O(1) now, might as well re-use that logic
+ // (including things like the `vec::IntoIter`→`Vec` specialization)
+ // especially as that could save us some monomorphiziation work
+ // if one uses the same iterators (like slice ones) with both.
+ return from_iter_via_vec(iter.into_iter());
+
+ #[inline]
+ fn from_iter_via_vec<U>(iter: impl Iterator<Item = U>) -> VecDeque<U> {
+ Vec::from_iter(iter).into()
+ }
}
}
@@ -2791,6 +2797,7 @@ impl<T, A: Allocator> From<Vec<T, A>> for VecDeque<T, A> {
/// In its current implementation, this is a very cheap
/// conversion. This isn't yet a guarantee though, and
/// shouldn't be relied on.
+ #[inline]
fn from(other: Vec<T, A>) -> Self {
let (ptr, len, cap, alloc) = other.into_raw_parts_with_alloc();
Self { head: 0, len, buf: unsafe { RawVec::from_raw_parts_in(ptr, cap, alloc) } }
diff --git a/library/core/src/cmp.rs b/library/core/src/cmp.rs
index 5db5cbfc3df..949896e5748 100644
--- a/library/core/src/cmp.rs
+++ b/library/core/src/cmp.rs
@@ -29,8 +29,7 @@ use crate::marker::StructuralPartialEq;
use self::Ordering::*;
-/// Trait for equality comparisons which are [partial equivalence
-/// relations](https://en.wikipedia.org/wiki/Partial_equivalence_relation).
+/// Trait for equality comparisons.
///
/// `x.eq(y)` can also be written `x == y`, and `x.ne(y)` can be written `x != y`.
/// We use the easier-to-read infix notation in the remainder of this documentation.
@@ -38,6 +37,8 @@ use self::Ordering::*;
/// This trait allows for partial equality, for types that do not have a full
/// equivalence relation. For example, in floating point numbers `NaN != NaN`,
/// so floating point types implement `PartialEq` but not [`trait@Eq`].
+/// Formally speaking, when `Rhs == Self`, this trait corresponds to a [partial equivalence
+/// relation](https://en.wikipedia.org/wiki/Partial_equivalence_relation).
///
/// Implementations must ensure that `eq` and `ne` are consistent with each other:
///
diff --git a/library/core/src/convert/num.rs b/library/core/src/convert/num.rs
index 4fa5d129bc6..9c0d7e9a1e8 100644
--- a/library/core/src/convert/num.rs
+++ b/library/core/src/convert/num.rs
@@ -49,7 +49,7 @@ macro_rules! impl_from {
// Rustdocs on the impl block show a "[+] show undocumented items" toggle.
// Rustdocs on functions do not.
#[doc = $doc]
- #[inline]
+ #[inline(always)]
fn from(small: $Small) -> Self {
small as Self
}
diff --git a/library/core/src/future/mod.rs b/library/core/src/future/mod.rs
index f2b961d62e0..2a8e12fd4cf 100644
--- a/library/core/src/future/mod.rs
+++ b/library/core/src/future/mod.rs
@@ -44,7 +44,7 @@ pub use poll_fn::{poll_fn, PollFn};
/// non-Send/Sync as well, and we don't want that.
///
/// It also simplifies the HIR lowering of `.await`.
-#[cfg_attr(not(bootstrap), lang = "ResumeTy")]
+// FIXME(swatinem): This type can be removed when bumping the bootstrap compiler
#[doc(hidden)]
#[unstable(feature = "gen_future", issue = "50547")]
#[derive(Debug, Copy, Clone)]
@@ -61,6 +61,7 @@ unsafe impl Sync for ResumeTy {}
/// This function returns a `GenFuture` underneath, but hides it in `impl Trait` to give
/// better error messages (`impl Future` rather than `GenFuture<[closure.....]>`).
// This is `const` to avoid extra errors after we recover from `const async fn`
+// FIXME(swatinem): This fn can be removed when bumping the bootstrap compiler
#[cfg_attr(bootstrap, lang = "from_generator")]
#[doc(hidden)]
#[unstable(feature = "gen_future", issue = "50547")]
@@ -102,7 +103,8 @@ where
GenFuture(gen)
}
-#[lang = "get_context"]
+// FIXME(swatinem): This fn can be removed when bumping the bootstrap compiler
+#[cfg_attr(bootstrap, lang = "get_context")]
#[doc(hidden)]
#[unstable(feature = "gen_future", issue = "50547")]
#[must_use]
@@ -113,6 +115,10 @@ pub unsafe fn get_context<'a, 'b>(cx: ResumeTy) -> &'a mut Context<'b> {
unsafe { &mut *cx.0.as_ptr().cast() }
}
+// FIXME(swatinem): This fn is currently needed to work around shortcomings
+// in type and lifetime inference.
+// See the comment at the bottom of `LoweringContext::make_async_expr` and
+// <https://github.com/rust-lang/rust/issues/104826>.
#[cfg_attr(not(bootstrap), lang = "identity_future")]
#[doc(hidden)]
#[unstable(feature = "gen_future", issue = "50547")]
diff --git a/library/core/src/iter/sources/repeat_n.rs b/library/core/src/iter/sources/repeat_n.rs
index dc69bf4df59..fd8d25ce1a5 100644
--- a/library/core/src/iter/sources/repeat_n.rs
+++ b/library/core/src/iter/sources/repeat_n.rs
@@ -20,7 +20,7 @@ use crate::mem::ManuallyDrop;
/// #![feature(iter_repeat_n)]
/// use std::iter;
///
-/// // four of the the number four:
+/// // four of the number four:
/// let mut four_fours = iter::repeat_n(4, 4);
///
/// assert_eq!(Some(4), four_fours.next());
diff --git a/library/core/src/str/pattern.rs b/library/core/src/str/pattern.rs
index d76d6f8b2a2..19da6d2fbec 100644
--- a/library/core/src/str/pattern.rs
+++ b/library/core/src/str/pattern.rs
@@ -1894,7 +1894,7 @@ unsafe fn small_slice_eq(x: &[u8], y: &[u8]) -> bool {
// Thus, derefencing both `px` and `py` in the loop below is safe.
//
// Moreover, we set `pxend` and `pyend` to be 4 bytes before the actual
- // end of of `px` and `py`. Thus, the final dereference outside of the
+ // end of `px` and `py`. Thus, the final dereference outside of the
// loop is guaranteed to be valid. (The final comparison will overlap with
// the last comparison done in the loop for lengths that aren't multiples
// of four.)
diff --git a/library/core/src/task/wake.rs b/library/core/src/task/wake.rs
index 0cff972df3a..9ab9b0ba1c7 100644
--- a/library/core/src/task/wake.rs
+++ b/library/core/src/task/wake.rs
@@ -174,6 +174,7 @@ impl RawWakerVTable {
/// Currently, `Context` only serves to provide access to a [`&Waker`](Waker)
/// which can be used to wake the current task.
#[stable(feature = "futures_api", since = "1.36.0")]
+#[cfg_attr(not(bootstrap), lang = "Context")]
pub struct Context<'a> {
waker: &'a Waker,
// Ensure we future-proof against variance changes by forcing
diff --git a/library/std/Cargo.toml b/library/std/Cargo.toml
index c10bfde4ddf..a7aefc26b97 100644
--- a/library/std/Cargo.toml
+++ b/library/std/Cargo.toml
@@ -15,7 +15,7 @@ cfg-if = { version = "1.0", features = ['rustc-dep-of-std'] }
panic_unwind = { path = "../panic_unwind", optional = true }
panic_abort = { path = "../panic_abort" }
core = { path = "../core" }
-libc = { version = "0.2.135", default-features = false, features = ['rustc-dep-of-std'] }
+libc = { version = "0.2.138", default-features = false, features = ['rustc-dep-of-std'] }
compiler_builtins = { version = "0.1.82" }
profiler_builtins = { path = "../profiler_builtins", optional = true }
unwind = { path = "../unwind" }
diff --git a/library/std/src/sync/mpmc/array.rs b/library/std/src/sync/mpmc/array.rs
index 4db7b4990b9..f71edc6c525 100644
--- a/library/std/src/sync/mpmc/array.rs
+++ b/library/std/src/sync/mpmc/array.rs
@@ -225,7 +225,7 @@ impl<T> Channel<T> {
let slot = unsafe { self.buffer.get_unchecked(index) };
let stamp = slot.stamp.load(Ordering::Acquire);
- // If the the stamp is ahead of the head by 1, we may attempt to pop.
+ // If the stamp is ahead of the head by 1, we may attempt to pop.
if head + 1 == stamp {
let new = if index + 1 < self.cap {
// Same lap, incremented index.
diff --git a/library/std/src/sync/mpsc/mod.rs b/library/std/src/sync/mpsc/mod.rs
index 27fba761ada..adb488d4378 100644
--- a/library/std/src/sync/mpsc/mod.rs
+++ b/library/std/src/sync/mpsc/mod.rs
@@ -629,9 +629,7 @@ impl<T> Clone for Sender<T> {
#[stable(feature = "rust1", since = "1.0.0")]
impl<T> Drop for Sender<T> {
- fn drop(&mut self) {
- let _ = self.inner;
- }
+ fn drop(&mut self) {}
}
#[stable(feature = "mpsc_debug", since = "1.8.0")]
@@ -751,9 +749,7 @@ impl<T> Clone for SyncSender<T> {
#[stable(feature = "rust1", since = "1.0.0")]
impl<T> Drop for SyncSender<T> {
- fn drop(&mut self) {
- let _ = self.inner;
- }
+ fn drop(&mut self) {}
}
#[stable(feature = "mpsc_debug", since = "1.8.0")]
@@ -1094,9 +1090,7 @@ impl<T> IntoIterator for Receiver<T> {
#[stable(feature = "rust1", since = "1.0.0")]
impl<T> Drop for Receiver<T> {
- fn drop(&mut self) {
- let _ = self.inner;
- }
+ fn drop(&mut self) {}
}
#[stable(feature = "mpsc_debug", since = "1.8.0")]
diff --git a/library/std/src/thread/scoped.rs b/library/std/src/thread/scoped.rs
index e6dbf35bd02..ada69aa8269 100644
--- a/library/std/src/thread/scoped.rs
+++ b/library/std/src/thread/scoped.rs
@@ -46,7 +46,7 @@ impl ScopeData {
// We check for 'overflow' with usize::MAX / 2, to make sure there's no
// chance it overflows to 0, which would result in unsoundness.
if self.num_running_threads.fetch_add(1, Ordering::Relaxed) > usize::MAX / 2 {
- // This can only reasonably happen by mem::forget()'ing many many ScopedJoinHandles.
+ // This can only reasonably happen by mem::forget()'ing a lot of ScopedJoinHandles.
self.decrement_num_running_threads(false);
panic!("too many running threads in thread scope");
}
diff --git a/src/bootstrap/builder.rs b/src/bootstrap/builder.rs
index cff5fd8c5b0..8ee6d49da8f 100644
--- a/src/bootstrap/builder.rs
+++ b/src/bootstrap/builder.rs
@@ -754,6 +754,8 @@ impl<'a> Builder<'a> {
run::BumpStage0,
run::ReplaceVersionPlaceholder,
run::Miri,
+ run::CollectLicenseMetadata,
+ run::GenerateCopyright,
),
// These commands either don't use paths, or they're special-cased in Build::build()
Kind::Clean | Kind::Format | Kind::Setup => vec![],
diff --git a/src/bootstrap/config.rs b/src/bootstrap/config.rs
index babf09d2b93..d8c15c76e2d 100644
--- a/src/bootstrap/config.rs
+++ b/src/bootstrap/config.rs
@@ -213,6 +213,7 @@ pub struct Config {
pub npm: Option<PathBuf>,
pub gdb: Option<PathBuf>,
pub python: Option<PathBuf>,
+ pub reuse: Option<PathBuf>,
pub cargo_native_static: bool,
pub configure_args: Vec<String>,
@@ -611,6 +612,7 @@ define_config! {
nodejs: Option<String> = "nodejs",
npm: Option<String> = "npm",
python: Option<String> = "python",
+ reuse: Option<String> = "reuse",
locked_deps: Option<bool> = "locked-deps",
vendor: Option<bool> = "vendor",
full_bootstrap: Option<bool> = "full-bootstrap",
@@ -1004,6 +1006,7 @@ impl Config {
config.npm = build.npm.map(PathBuf::from);
config.gdb = build.gdb.map(PathBuf::from);
config.python = build.python.map(PathBuf::from);
+ config.reuse = build.reuse.map(PathBuf::from);
config.submodules = build.submodules;
set(&mut config.low_priority, build.low_priority);
set(&mut config.compiler_docs, build.compiler_docs);
diff --git a/src/bootstrap/flags.rs b/src/bootstrap/flags.rs
index 2001e29bd2e..37a8eb884ef 100644
--- a/src/bootstrap/flags.rs
+++ b/src/bootstrap/flags.rs
@@ -143,7 +143,7 @@ pub enum Subcommand {
args: Vec<String>,
},
Setup {
- profile: Profile,
+ profile: Option<Profile>,
},
}
@@ -628,14 +628,15 @@ Arguments:
|path| format!("{} is not a valid UTF8 string", path.to_string_lossy())
));
- profile_string.parse().unwrap_or_else(|err| {
+ let profile = profile_string.parse().unwrap_or_else(|err| {
eprintln!("error: {}", err);
eprintln!("help: the available profiles are:");
eprint!("{}", Profile::all_for_help("- "));
crate::detail_exit(1);
- })
+ });
+ Some(profile)
} else {
- t!(crate::setup::interactive_path())
+ None
};
Subcommand::Setup { profile }
}
diff --git a/src/bootstrap/lib.rs b/src/bootstrap/lib.rs
index d69bced0b28..3ed53452309 100644
--- a/src/bootstrap/lib.rs
+++ b/src/bootstrap/lib.rs
@@ -542,16 +542,6 @@ impl Build {
metrics: metrics::BuildMetrics::init(),
};
- build.verbose("finding compilers");
- cc_detect::find(&mut build);
- // When running `setup`, the profile is about to change, so any requirements we have now may
- // be different on the next invocation. Don't check for them until the next time x.py is
- // run. This is ok because `setup` never runs any build commands, so it won't fail if commands are missing.
- if !matches!(build.config.cmd, Subcommand::Setup { .. }) {
- build.verbose("running sanity check");
- sanity::check(&mut build);
- }
-
// If local-rust is the same major.minor as the current version, then force a
// local-rebuild
let local_version_verbose =
@@ -567,16 +557,34 @@ impl Build {
build.local_rebuild = true;
}
- // Make sure we update these before gathering metadata so we don't get an error about missing
- // Cargo.toml files.
- let rust_submodules =
- ["src/tools/rust-installer", "src/tools/cargo", "library/backtrace", "library/stdarch"];
- for s in rust_submodules {
- build.update_submodule(Path::new(s));
- }
+ build.verbose("finding compilers");
+ cc_detect::find(&mut build);
+ // When running `setup`, the profile is about to change, so any requirements we have now may
+ // be different on the next invocation. Don't check for them until the next time x.py is
+ // run. This is ok because `setup` never runs any build commands, so it won't fail if commands are missing.
+ //
+ // Similarly, for `setup` we don't actually need submodules or cargo metadata.
+ if !matches!(build.config.cmd, Subcommand::Setup { .. }) {
+ build.verbose("running sanity check");
+ sanity::check(&mut build);
+
+ // Make sure we update these before gathering metadata so we don't get an error about missing
+ // Cargo.toml files.
+ let rust_submodules = [
+ "src/tools/rust-installer",
+ "src/tools/cargo",
+ "library/backtrace",
+ "library/stdarch",
+ ];
+ for s in rust_submodules {
+ build.update_submodule(Path::new(s));
+ }
+ // Now, update all existing submodules.
+ build.update_existing_submodules();
- build.verbose("learning about cargo");
- metadata::build(&mut build);
+ build.verbose("learning about cargo");
+ metadata::build(&mut build);
+ }
build
}
@@ -668,7 +676,7 @@ impl Build {
/// If any submodule has been initialized already, sync it unconditionally.
/// This avoids contributors checking in a submodule change by accident.
- pub fn maybe_update_submodules(&self) {
+ pub fn update_existing_submodules(&self) {
// Avoid running git when there isn't a git checkout.
if !self.config.submodules(&self.rust_info()) {
return;
@@ -697,8 +705,6 @@ impl Build {
job::setup(self);
}
- self.maybe_update_submodules();
-
if let Subcommand::Format { check, paths } = &self.config.cmd {
return format::format(&builder::Builder::new(&self), *check, &paths);
}
diff --git a/src/bootstrap/run.rs b/src/bootstrap/run.rs
index d49b41c5132..05de51f8cc5 100644
--- a/src/bootstrap/run.rs
+++ b/src/bootstrap/run.rs
@@ -1,3 +1,4 @@
+use std::path::PathBuf;
use std::process::Command;
use crate::builder::{Builder, RunConfig, ShouldRun, Step};
@@ -189,3 +190,65 @@ impl Step for Miri {
builder.run(&mut miri);
}
}
+
+#[derive(Debug, PartialOrd, Ord, Copy, Clone, Hash, PartialEq, Eq)]
+pub struct CollectLicenseMetadata;
+
+impl Step for CollectLicenseMetadata {
+ type Output = PathBuf;
+ const ONLY_HOSTS: bool = true;
+
+ fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
+ run.path("src/tools/collect-license-metadata")
+ }
+
+ fn make_run(run: RunConfig<'_>) {
+ run.builder.ensure(CollectLicenseMetadata);
+ }
+
+ fn run(self, builder: &Builder<'_>) -> Self::Output {
+ let Some(reuse) = &builder.config.reuse else {
+ panic!("REUSE is required to collect the license metadata");
+ };
+
+ // Temporary location, it will be moved to src/etc once it's accurate.
+ let dest = builder.out.join("license-metadata.json");
+
+ let mut cmd = builder.tool_cmd(Tool::CollectLicenseMetadata);
+ cmd.env("REUSE_EXE", reuse);
+ cmd.env("DEST", &dest);
+ builder.run(&mut cmd);
+
+ dest
+ }
+}
+
+#[derive(Debug, PartialOrd, Ord, Copy, Clone, Hash, PartialEq, Eq)]
+pub struct GenerateCopyright;
+
+impl Step for GenerateCopyright {
+ type Output = PathBuf;
+ const ONLY_HOSTS: bool = true;
+
+ fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
+ run.path("src/tools/generate-copyright")
+ }
+
+ fn make_run(run: RunConfig<'_>) {
+ run.builder.ensure(GenerateCopyright);
+ }
+
+ fn run(self, builder: &Builder<'_>) -> Self::Output {
+ let license_metadata = builder.ensure(CollectLicenseMetadata);
+
+ // Temporary location, it will be moved to the proper one once it's accurate.
+ let dest = builder.out.join("COPYRIGHT.md");
+
+ let mut cmd = builder.tool_cmd(Tool::GenerateCopyright);
+ cmd.env("LICENSE_METADATA", &license_metadata);
+ cmd.env("DEST", &dest);
+ builder.run(&mut cmd);
+
+ dest
+ }
+}
diff --git a/src/bootstrap/sanity.rs b/src/bootstrap/sanity.rs
index 631d42acb93..8a40b0f64f4 100644
--- a/src/bootstrap/sanity.rs
+++ b/src/bootstrap/sanity.rs
@@ -140,6 +140,13 @@ than building it.
.map(|p| cmd_finder.must_have(p))
.or_else(|| cmd_finder.maybe_have("gdb"));
+ build.config.reuse = build
+ .config
+ .reuse
+ .take()
+ .map(|p| cmd_finder.must_have(p))
+ .or_else(|| cmd_finder.maybe_have("reuse"));
+
// We're gonna build some custom C code here and there, host triples
// also build some C++ shims for LLVM so we need a C++ compiler.
for target in &build.targets {
diff --git a/src/bootstrap/setup.rs b/src/bootstrap/setup.rs
index 04480277fe0..c7f98a7d0d1 100644
--- a/src/bootstrap/setup.rs
+++ b/src/bootstrap/setup.rs
@@ -1,15 +1,13 @@
+use crate::Config;
use crate::{t, VERSION};
-use crate::{Config, TargetSelection};
use std::env::consts::EXE_SUFFIX;
use std::fmt::Write as _;
use std::fs::File;
+use std::io::Write;
use std::path::{Path, PathBuf, MAIN_SEPARATOR};
use std::process::Command;
use std::str::FromStr;
-use std::{
- env, fmt, fs,
- io::{self, Write},
-};
+use std::{fmt, fs, io};
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub enum Profile {
@@ -81,38 +79,10 @@ impl fmt::Display for Profile {
}
}
-pub fn setup(config: &Config, profile: Profile) {
- let path = &config.config.clone().unwrap_or(PathBuf::from("config.toml"));
-
- if path.exists() {
- eprintln!(
- "error: you asked `x.py` to setup a new config file, but one already exists at `{}`",
- path.display()
- );
- eprintln!("help: try adding `profile = \"{}\"` at the top of {}", profile, path.display());
- eprintln!(
- "note: this will use the configuration in {}",
- profile.include_path(&config.src).display()
- );
- crate::detail_exit(1);
- }
-
- let settings = format!(
- "# Includes one of the default files in src/bootstrap/defaults\n\
- profile = \"{}\"\n\
- changelog-seen = {}\n",
- profile, VERSION
- );
- t!(fs::write(path, settings));
-
- let include_path = profile.include_path(&config.src);
- println!("`x.py` will now use the configuration at {}", include_path.display());
-
- let build = TargetSelection::from_user(&env!("BUILD_TRIPLE"));
+pub fn setup(config: &Config, profile: Option<Profile>) {
+ let profile = profile.unwrap_or_else(|| t!(interactive_path()));
let stage_path =
- ["build", build.rustc_target_arg(), "stage1"].join(&MAIN_SEPARATOR.to_string());
-
- println!();
+ ["build", config.build.rustc_target_arg(), "stage1"].join(&MAIN_SEPARATOR.to_string());
if !rustup_installed() && profile != Profile::User {
eprintln!("`rustup` is not installed; cannot link `stage1` toolchain");
@@ -134,8 +104,6 @@ pub fn setup(config: &Config, profile: Profile) {
Profile::User => &["dist", "build"],
};
- println!();
-
t!(install_git_hook_maybe(&config));
println!();
@@ -150,6 +118,36 @@ pub fn setup(config: &Config, profile: Profile) {
"For more suggestions, see https://rustc-dev-guide.rust-lang.org/building/suggested.html"
);
}
+
+ let path = &config.config.clone().unwrap_or(PathBuf::from("config.toml"));
+ setup_config_toml(path, profile, config);
+}
+
+fn setup_config_toml(path: &PathBuf, profile: Profile, config: &Config) {
+ if path.exists() {
+ eprintln!();
+ eprintln!(
+ "error: you asked `x.py` to setup a new config file, but one already exists at `{}`",
+ path.display()
+ );
+ eprintln!("help: try adding `profile = \"{}\"` at the top of {}", profile, path.display());
+ eprintln!(
+ "note: this will use the configuration in {}",
+ profile.include_path(&config.src).display()
+ );
+ crate::detail_exit(1);
+ }
+
+ let settings = format!(
+ "# Includes one of the default files in src/bootstrap/defaults\n\
+ profile = \"{}\"\n\
+ changelog-seen = {}\n",
+ profile, VERSION
+ );
+ t!(fs::write(path, settings));
+
+ let include_path = profile.include_path(&config.src);
+ println!("`x.py` will now use the configuration at {}", include_path.display());
}
fn rustup_installed() -> bool {
@@ -303,7 +301,18 @@ pub fn interactive_path() -> io::Result<Profile> {
// install a git hook to automatically run tidy --bless, if they want
fn install_git_hook_maybe(config: &Config) -> io::Result<()> {
+ let git = t!(config.git().args(&["rev-parse", "--git-common-dir"]).output().map(|output| {
+ assert!(output.status.success(), "failed to run `git`");
+ PathBuf::from(t!(String::from_utf8(output.stdout)).trim())
+ }));
+ let dst = git.join("hooks").join("pre-push");
+ if dst.exists() {
+ // The git hook has already been set up, or the user already has a custom hook.
+ return Ok(());
+ }
+
let mut input = String::new();
+ println!();
println!(
"Rust's CI will automatically fail if it doesn't pass `tidy`, the internal tool for ensuring code quality.
If you'd like, x.py can install a git hook for you that will automatically run `tidy --bless` before
@@ -329,12 +338,6 @@ undesirable, simply delete the `pre-push` file from .git/hooks."
if should_install {
let src = config.src.join("src").join("etc").join("pre-push.sh");
- let git =
- t!(config.git().args(&["rev-parse", "--git-common-dir"]).output().map(|output| {
- assert!(output.status.success(), "failed to run `git`");
- PathBuf::from(t!(String::from_utf8(output.stdout)).trim())
- }));
- let dst = git.join("hooks").join("pre-push");
match fs::hard_link(src, &dst) {
Err(e) => eprintln!(
"error: could not create hook {}: do you already have the git hook installed?\n{}",
diff --git a/src/bootstrap/tool.rs b/src/bootstrap/tool.rs
index ba329ea6c75..e0be4c432f1 100644
--- a/src/bootstrap/tool.rs
+++ b/src/bootstrap/tool.rs
@@ -380,6 +380,8 @@ bootstrap_tool!(
HtmlChecker, "src/tools/html-checker", "html-checker";
BumpStage0, "src/tools/bump-stage0", "bump-stage0";
ReplaceVersionPlaceholder, "src/tools/replace-version-placeholder", "replace-version-placeholder";
+ CollectLicenseMetadata, "src/tools/collect-license-metadata", "collect-license-metadata";
+ GenerateCopyright, "src/tools/generate-copyright", "generate-copyright";
);
#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq, Ord, PartialOrd)]
diff --git a/src/ci/docker/host-aarch64/aarch64-gnu/Dockerfile b/src/ci/docker/host-aarch64/aarch64-gnu/Dockerfile
index e54d0eafb40..699938c3718 100644
--- a/src/ci/docker/host-aarch64/aarch64-gnu/Dockerfile
+++ b/src/ci/docker/host-aarch64/aarch64-gnu/Dockerfile
@@ -14,7 +14,8 @@ RUN apt-get update && DEBIAN_FRONTEND=noninteractive apt-get install -y --no-ins
gdb \
libssl-dev \
pkg-config \
- xz-utils
+ xz-utils \
+ && rm -rf /var/lib/apt/lists/*
COPY scripts/sccache.sh /scripts/
RUN sh /scripts/sccache.sh
diff --git a/src/ci/docker/host-x86_64/dist-i686-linux/Dockerfile b/src/ci/docker/host-x86_64/dist-i686-linux/Dockerfile
index cd86d9fb584..ea4a2a2427d 100644
--- a/src/ci/docker/host-x86_64/dist-i686-linux/Dockerfile
+++ b/src/ci/docker/host-x86_64/dist-i686-linux/Dockerfile
@@ -32,7 +32,8 @@ RUN yum upgrade -y && \
wget \
xz \
zlib-devel.i686 \
- zlib-devel.x86_64
+ zlib-devel.x86_64 \
+ && yum clean all
RUN mkdir -p /rustroot/bin && ln -s /usr/bin/cmake3 /rustroot/bin/cmake
diff --git a/src/ci/docker/host-x86_64/dist-x86_64-freebsd/Dockerfile b/src/ci/docker/host-x86_64/dist-x86_64-freebsd/Dockerfile
index f9b1fa8951a..377d4a9ce5e 100644
--- a/src/ci/docker/host-x86_64/dist-x86_64-freebsd/Dockerfile
+++ b/src/ci/docker/host-x86_64/dist-x86_64-freebsd/Dockerfile
@@ -15,7 +15,8 @@ RUN apt-get update && apt-get install -y --no-install-recommends \
xz-utils \
wget \
libssl-dev \
- pkg-config
+ pkg-config \
+ && rm -rf /var/lib/apt/lists/*
COPY scripts/freebsd-toolchain.sh /tmp/
RUN /tmp/freebsd-toolchain.sh x86_64
diff --git a/src/ci/docker/host-x86_64/dist-x86_64-illumos/Dockerfile b/src/ci/docker/host-x86_64/dist-x86_64-illumos/Dockerfile
index c2e44ead51e..4e46bdee5ac 100644
--- a/src/ci/docker/host-x86_64/dist-x86_64-illumos/Dockerfile
+++ b/src/ci/docker/host-x86_64/dist-x86_64-illumos/Dockerfile
@@ -11,7 +11,8 @@ RUN apt-get update && \
apt-get install -y --no-install-recommends \
libgmp-dev \
libmpfr-dev \
- libmpc-dev
+ libmpc-dev \
+ && rm -rf /var/lib/apt/lists/*
COPY scripts/illumos-toolchain.sh /tmp/
diff --git a/src/ci/docker/host-x86_64/dist-x86_64-linux/Dockerfile b/src/ci/docker/host-x86_64/dist-x86_64-linux/Dockerfile
index 423aba06cca..6bdc88e18f5 100644
--- a/src/ci/docker/host-x86_64/dist-x86_64-linux/Dockerfile
+++ b/src/ci/docker/host-x86_64/dist-x86_64-linux/Dockerfile
@@ -32,7 +32,8 @@ RUN yum upgrade -y && \
wget \
xz \
zlib-devel.i686 \
- zlib-devel.x86_64
+ zlib-devel.x86_64 \
+ && yum clean all
RUN mkdir -p /rustroot/bin && ln -s /usr/bin/cmake3 /rustroot/bin/cmake
diff --git a/src/ci/docker/host-x86_64/dist-x86_64-musl/Dockerfile b/src/ci/docker/host-x86_64/dist-x86_64-musl/Dockerfile
index 51645a81853..13eaf7fce8c 100644
--- a/src/ci/docker/host-x86_64/dist-x86_64-musl/Dockerfile
+++ b/src/ci/docker/host-x86_64/dist-x86_64-musl/Dockerfile
@@ -16,7 +16,8 @@ RUN apt-get update && DEBIAN_FRONTEND=noninteractive apt-get install -y --no-ins
gdb \
patch \
libssl-dev \
- pkg-config
+ pkg-config \
+ && rm -rf /var/lib/apt/lists/*
WORKDIR /build/
diff --git a/src/ci/docker/host-x86_64/i686-gnu-nopt/Dockerfile b/src/ci/docker/host-x86_64/i686-gnu-nopt/Dockerfile
index dd74726f856..e2b66c2cff1 100644
--- a/src/ci/docker/host-x86_64/i686-gnu-nopt/Dockerfile
+++ b/src/ci/docker/host-x86_64/i686-gnu-nopt/Dockerfile
@@ -15,7 +15,8 @@ RUN apt-get update && apt-get install -y --no-install-recommends \
gdb \
zlib1g-dev \
lib32z1-dev \
- xz-utils
+ xz-utils \
+ && rm -rf /var/lib/apt/lists/*
COPY scripts/sccache.sh /scripts/
diff --git a/src/ci/docker/host-x86_64/i686-gnu/Dockerfile b/src/ci/docker/host-x86_64/i686-gnu/Dockerfile
index 0c36cfd66bd..cb6559707d9 100644
--- a/src/ci/docker/host-x86_64/i686-gnu/Dockerfile
+++ b/src/ci/docker/host-x86_64/i686-gnu/Dockerfile
@@ -15,7 +15,8 @@ RUN apt-get update && apt-get install -y --no-install-recommends \
gdb \
zlib1g-dev \
lib32z1-dev \
- xz-utils
+ xz-utils \
+ && rm -rf /var/lib/apt/lists/*
COPY scripts/sccache.sh /scripts/
diff --git a/src/ci/docker/host-x86_64/mingw-check/Dockerfile b/src/ci/docker/host-x86_64/mingw-check/Dockerfile
index 52a7776153d..40caa7c5013 100644
--- a/src/ci/docker/host-x86_64/mingw-check/Dockerfile
+++ b/src/ci/docker/host-x86_64/mingw-check/Dockerfile
@@ -20,20 +20,20 @@ RUN apt-get update && apt-get install -y --no-install-recommends \
xz-utils \
libssl-dev \
pkg-config \
- mingw-w64
+ mingw-w64 \
+ && rm -rf /var/lib/apt/lists/*
RUN curl -sL https://nodejs.org/dist/v16.9.0/node-v16.9.0-linux-x64.tar.xz | tar -xJ
ENV PATH="/node-v16.9.0-linux-x64/bin:${PATH}"
# Install es-check
# Pin its version to prevent unrelated CI failures due to future es-check versions.
-RUN npm install es-check@6.1.1 -g
-RUN npm install eslint@8.6.0 -g
+RUN npm install es-check@6.1.1 eslint@8.6.0 -g
COPY scripts/sccache.sh /scripts/
RUN sh /scripts/sccache.sh
COPY host-x86_64/mingw-check/reuse-requirements.txt /tmp/
-RUN pip3 install --no-deps --require-hashes -r /tmp/reuse-requirements.txt
+RUN pip3 install --no-deps --no-cache-dir --require-hashes -r /tmp/reuse-requirements.txt
COPY host-x86_64/mingw-check/validate-toolstate.sh /scripts/
COPY host-x86_64/mingw-check/validate-error-codes.sh /scripts/
diff --git a/src/ci/docker/host-x86_64/test-various/Dockerfile b/src/ci/docker/host-x86_64/test-various/Dockerfile
index 7c09e3a582f..cf4451f8b33 100644
--- a/src/ci/docker/host-x86_64/test-various/Dockerfile
+++ b/src/ci/docker/host-x86_64/test-various/Dockerfile
@@ -21,7 +21,8 @@ RUN apt-get update && DEBIAN_FRONTEND=noninteractive apt-get install -y --no-ins
ovmf \
qemu-efi-aarch64 \
qemu-system-arm \
- qemu-system-x86
+ qemu-system-x86 \
+ && rm -rf /var/lib/apt/lists/*
RUN curl -sL https://nodejs.org/dist/v15.14.0/node-v15.14.0-linux-x64.tar.xz | \
tar -xJ
diff --git a/src/ci/docker/host-x86_64/wasm32/Dockerfile b/src/ci/docker/host-x86_64/wasm32/Dockerfile
index 9e37c2822e8..ef1fde1c3b9 100644
--- a/src/ci/docker/host-x86_64/wasm32/Dockerfile
+++ b/src/ci/docker/host-x86_64/wasm32/Dockerfile
@@ -13,7 +13,8 @@ RUN apt-get update && DEBIAN_FRONTEND=noninteractive apt-get install -y --no-ins
sudo \
gdb \
xz-utils \
- bzip2
+ bzip2 \
+ && rm -rf /var/lib/apt/lists/*
COPY scripts/emscripten.sh /scripts/
RUN bash /scripts/emscripten.sh
diff --git a/src/ci/docker/host-x86_64/x86_64-gnu-aux/Dockerfile b/src/ci/docker/host-x86_64/x86_64-gnu-aux/Dockerfile
index d55d5b56ad3..e08c4e1e8b7 100644
--- a/src/ci/docker/host-x86_64/x86_64-gnu-aux/Dockerfile
+++ b/src/ci/docker/host-x86_64/x86_64-gnu-aux/Dockerfile
@@ -19,7 +19,8 @@ RUN apt-get update && apt-get install -y --no-install-recommends \
llvm-dev \
libfreetype6-dev \
libexpat1-dev \
- tidy
+ tidy \
+ && rm -rf /var/lib/apt/lists/*
COPY scripts/sccache.sh /scripts/
RUN sh /scripts/sccache.sh
diff --git a/src/ci/docker/host-x86_64/x86_64-gnu-debug/Dockerfile b/src/ci/docker/host-x86_64/x86_64-gnu-debug/Dockerfile
index 739045248fe..c2b002055a8 100644
--- a/src/ci/docker/host-x86_64/x86_64-gnu-debug/Dockerfile
+++ b/src/ci/docker/host-x86_64/x86_64-gnu-debug/Dockerfile
@@ -23,7 +23,8 @@ RUN apt-get update && apt-get install -y --no-install-recommends \
pkg-config \
xz-utils \
lld \
- clang
+ clang \
+ && rm -rf /var/lib/apt/lists/*
COPY scripts/sccache.sh /scripts/
RUN sh /scripts/sccache.sh
diff --git a/src/ci/docker/host-x86_64/x86_64-gnu-distcheck/Dockerfile b/src/ci/docker/host-x86_64/x86_64-gnu-distcheck/Dockerfile
index 80a004501a8..7e640c49f01 100644
--- a/src/ci/docker/host-x86_64/x86_64-gnu-distcheck/Dockerfile
+++ b/src/ci/docker/host-x86_64/x86_64-gnu-distcheck/Dockerfile
@@ -15,7 +15,8 @@ RUN apt-get update && apt-get install -y --no-install-recommends \
gdb \
xz-utils \
libssl-dev \
- pkg-config
+ pkg-config \
+ && rm -rf /var/lib/apt/lists/*
COPY scripts/sccache.sh /scripts/
RUN sh /scripts/sccache.sh
diff --git a/src/ci/docker/host-x86_64/x86_64-gnu-llvm-13-stage1/Dockerfile b/src/ci/docker/host-x86_64/x86_64-gnu-llvm-13-stage1/Dockerfile
index 23f2215c2d9..16976a9428e 100644
--- a/src/ci/docker/host-x86_64/x86_64-gnu-llvm-13-stage1/Dockerfile
+++ b/src/ci/docker/host-x86_64/x86_64-gnu-llvm-13-stage1/Dockerfile
@@ -21,7 +21,8 @@ RUN apt-get update && apt-get install -y --no-install-recommends \
pkg-config \
zlib1g-dev \
xz-utils \
- nodejs
+ nodejs \
+ && rm -rf /var/lib/apt/lists/*
COPY scripts/sccache.sh /scripts/
RUN sh /scripts/sccache.sh
diff --git a/src/ci/docker/host-x86_64/x86_64-gnu-llvm-13/Dockerfile b/src/ci/docker/host-x86_64/x86_64-gnu-llvm-13/Dockerfile
index 8f6831bc54e..c3b47c3510d 100644
--- a/src/ci/docker/host-x86_64/x86_64-gnu-llvm-13/Dockerfile
+++ b/src/ci/docker/host-x86_64/x86_64-gnu-llvm-13/Dockerfile
@@ -24,15 +24,15 @@ RUN apt-get update && apt-get install -y --no-install-recommends \
pkg-config \
zlib1g-dev \
xz-utils \
- nodejs
+ nodejs \
# Install powershell so we can test x.ps1 on Linux
-RUN apt-get update && \
- apt-get install -y apt-transport-https software-properties-common && \
+ apt-transport-https software-properties-common && \
curl -s "https://packages.microsoft.com/config/ubuntu/$(lsb_release -rs)/packages-microsoft-prod.deb" > packages-microsoft-prod.deb && \
dpkg -i packages-microsoft-prod.deb && \
apt-get update && \
- apt-get install -y powershell
+ apt-get install -y powershell \
+ && rm -rf /var/lib/apt/lists/*
COPY scripts/sccache.sh /scripts/
RUN sh /scripts/sccache.sh
diff --git a/src/ci/docker/host-x86_64/x86_64-gnu-nopt/Dockerfile b/src/ci/docker/host-x86_64/x86_64-gnu-nopt/Dockerfile
index 77510d7ac62..9fdc78406fb 100644
--- a/src/ci/docker/host-x86_64/x86_64-gnu-nopt/Dockerfile
+++ b/src/ci/docker/host-x86_64/x86_64-gnu-nopt/Dockerfile
@@ -15,7 +15,8 @@ RUN apt-get update && DEBIAN_FRONTEND=noninteractive apt-get install -y --no-ins
gdb \
libssl-dev \
pkg-config \
- xz-utils
+ xz-utils \
+ && rm -rf /var/lib/apt/lists/*
COPY scripts/sccache.sh /scripts/
RUN sh /scripts/sccache.sh
diff --git a/src/ci/docker/host-x86_64/x86_64-gnu-tools/Dockerfile b/src/ci/docker/host-x86_64/x86_64-gnu-tools/Dockerfile
index 4350ca20586..501d2781646 100644
--- a/src/ci/docker/host-x86_64/x86_64-gnu-tools/Dockerfile
+++ b/src/ci/docker/host-x86_64/x86_64-gnu-tools/Dockerfile
@@ -14,10 +14,9 @@ RUN apt-get update && apt-get install -y --no-install-recommends \
libssl-dev \
sudo \
xz-utils \
- tidy
+ tidy \
# Install dependencies for chromium browser
-RUN apt-get install -y \
gconf-service \
libasound2 \
libatk1.0-0 \
@@ -56,7 +55,8 @@ RUN apt-get install -y \
libnss3 \
lsb-release \
xdg-utils \
- wget
+ wget \
+ && rm -rf /var/lib/apt/lists/*
COPY scripts/sccache.sh /scripts/
RUN sh /scripts/sccache.sh
diff --git a/src/ci/docker/host-x86_64/x86_64-gnu/Dockerfile b/src/ci/docker/host-x86_64/x86_64-gnu/Dockerfile
index 88c182a4d43..5b9581f72a6 100644
--- a/src/ci/docker/host-x86_64/x86_64-gnu/Dockerfile
+++ b/src/ci/docker/host-x86_64/x86_64-gnu/Dockerfile
@@ -15,7 +15,8 @@ RUN apt-get update && apt-get install -y --no-install-recommends \
gdb \
libssl-dev \
pkg-config \
- xz-utils
+ xz-utils \
+ && rm -rf /var/lib/apt/lists/*
COPY scripts/sccache.sh /scripts/
RUN sh /scripts/sccache.sh
diff --git a/src/ci/docker/scripts/freebsd-toolchain.sh b/src/ci/docker/scripts/freebsd-toolchain.sh
index 4a4cac1b723..17cd456b995 100755
--- a/src/ci/docker/scripts/freebsd-toolchain.sh
+++ b/src/ci/docker/scripts/freebsd-toolchain.sh
@@ -53,7 +53,7 @@ files_to_extract=(
for lib in c cxxrt gcc_s m thr util; do
files_to_extract=("${files_to_extract[@]}" "./lib/lib${lib}.*" "./usr/lib/lib${lib}.*")
done
-for lib in c++ c_nonshared compiler_rt execinfo gcc pthread rt ssp_nonshared procstat devstat kvm; do
+for lib in c++ c_nonshared compiler_rt execinfo gcc pthread rt ssp_nonshared procstat devstat kvm memstat; do
files_to_extract=("${files_to_extract[@]}" "./usr/lib/lib${lib}.*")
done
diff --git a/src/doc/book b/src/doc/book
-Subproject 3f64052c048c6def93b94a2b514ee88bba91874
+Subproject a60f4316ec923a5ac2ed6a2eba6960edb832d85
diff --git a/src/doc/embedded-book b/src/doc/embedded-book
-Subproject c533348edd69f11a8f4225d633a05d7093fddbf
+Subproject 19f798d448835a4888e3b3eae7fe69f1d61d868
diff --git a/src/doc/nomicon b/src/doc/nomicon
-Subproject 05532356e7a4dbea2330aabb77611f5179493bb
+Subproject ae406aa5287a9e025abb72343aaceec98458c11
diff --git a/src/doc/reference b/src/doc/reference
-Subproject 9f0cc13ffcd27c1fbe1ab766a9491e15ddcf4d1
+Subproject 3ae62681ff236d5528ef7c8c28ba7c6b2ecc673
diff --git a/src/doc/rust-by-example b/src/doc/rust-by-example
-Subproject 2b15c0abf2bada6e00553814336bc3e2d839909
+Subproject a9869b4a3c4cac3bc6099b41f088679e268400b
diff --git a/src/doc/rustc-dev-guide b/src/doc/rustc-dev-guide
-Subproject d0dc6c97a6486f68bac782fff135086eae6d77e
+Subproject e269950a57fa6fcda356426545fb5aa3691a7ce
diff --git a/src/doc/unstable-book/src/language-features/abi-efiapi.md b/src/doc/unstable-book/src/language-features/abi-efiapi.md
index 11ef0cfdb14..b492da88474 100644
--- a/src/doc/unstable-book/src/language-features/abi-efiapi.md
+++ b/src/doc/unstable-book/src/language-features/abi-efiapi.md
@@ -12,7 +12,7 @@ Specification].
Example:
-```rust
+```rust,ignore (not-all-targets-support-uefi)
#![feature(abi_efiapi)]
extern "efiapi" { fn f1(); }
diff --git a/src/librustdoc/html/static/css/rustdoc.css b/src/librustdoc/html/static/css/rustdoc.css
index f44797fe55f..5ebc545d10c 100644
--- a/src/librustdoc/html/static/css/rustdoc.css
+++ b/src/librustdoc/html/static/css/rustdoc.css
@@ -195,8 +195,7 @@ h1, h2, h3, h4, h5, h6,
span.since,
a.srclink,
#help-button > a,
-details.rustdoc-toggle.top-doc > summary,
-details.rustdoc-toggle.non-exhaustive > summary,
+summary.hideme,
.scraped-example-list,
/* This selector is for the items listed in the "all items" page. */
ul.all-items {
@@ -1015,7 +1014,6 @@ so that we can apply CSS-filters to change the arrow color in themes */
.import-item .stab {
border-radius: 3px;
display: inline-block;
- font-size: 0.875rem;
line-height: 1.2;
margin-bottom: 0;
margin-left: 0.3125em;
@@ -1484,6 +1482,7 @@ details.rustdoc-toggle {
"Expand description" or "Show methods". */
details.rustdoc-toggle > summary.hideme {
cursor: pointer;
+ font-size: 1rem;
}
details.rustdoc-toggle > summary {
@@ -1546,13 +1545,6 @@ details.rustdoc-toggle > summary:focus-visible::before {
outline-offset: 1px;
}
-details.rustdoc-toggle.top-doc > summary,
-details.rustdoc-toggle.top-doc > summary::before,
-details.rustdoc-toggle.non-exhaustive > summary,
-details.rustdoc-toggle.non-exhaustive > summary::before {
- font-size: 1rem;
-}
-
details.non-exhaustive {
margin-bottom: 8px;
}
@@ -1660,8 +1652,6 @@ in storage.js
/* Hide the sidebar offscreen while not in use. Doing this instead of display: none means
the sidebar stays visible for screen readers, which is useful for navigation. */
left: -1000px;
- margin: 0;
- padding: 0;
z-index: 11;
/* Reduce height slightly to account for mobile topbar. */
height: calc(100vh - 45px);
@@ -1978,7 +1968,9 @@ in storage.js
}
.scraped-example .code-wrapper .example-wrap {
- flex: 1;
+ display: grid;
+ grid-template-columns: max-content auto;
+ width: 100%;
overflow-x: auto;
overflow-y: hidden;
margin-bottom: 0;
diff --git a/src/librustdoc/html/static/js/scrape-examples.js b/src/librustdoc/html/static/js/scrape-examples.js
index d0fd115fd15..e328e656edd 100644
--- a/src/librustdoc/html/static/js/scrape-examples.js
+++ b/src/librustdoc/html/static/js/scrape-examples.js
@@ -57,7 +57,7 @@
});
});
- example.querySelector("next")
+ example.querySelector(".next")
.addEventListener("click", () => {
onChangeLoc(() => {
locIndex = (locIndex + 1) % locs.length;
diff --git a/src/librustdoc/html/static_files.rs b/src/librustdoc/html/static_files.rs
index 1f87f95563a..b48b82307eb 100644
--- a/src/librustdoc/html/static_files.rs
+++ b/src/librustdoc/html/static_files.rs
@@ -130,4 +130,4 @@ static_files! {
nanum_barun_gothic_license => "static/fonts/NanumBarunGothic-LICENSE.txt",
}
-pub(crate) static SCRAPE_EXAMPLES_HELP_MD: &str = include_str!("static/js/scrape-examples.js");
+pub(crate) static SCRAPE_EXAMPLES_HELP_MD: &str = include_str!("static/scrape-examples-help.md");
diff --git a/src/test/mir-opt/inline/cycle.g.Inline.diff b/src/test/mir-opt/inline/cycle.g.Inline.diff
index 5f3ee467c88..afe157ccd7f 100644
--- a/src/test/mir-opt/inline/cycle.g.Inline.diff
+++ b/src/test/mir-opt/inline/cycle.g.Inline.diff
@@ -10,8 +10,6 @@
+ let _3: (); // in scope 1 at $DIR/cycle.rs:6:5: 6:8
+ let mut _4: &fn() {main}; // in scope 1 at $DIR/cycle.rs:6:5: 6:6
+ let mut _5: (); // in scope 1 at $DIR/cycle.rs:6:5: 6:8
-+ scope 2 (inlined <fn() {main} as Fn<()>>::call - shim(fn() {main})) { // at $DIR/cycle.rs:6:5: 6:8
-+ }
+ }
bb0: {
@@ -29,7 +27,10 @@
+ StorageLive(_4); // scope 1 at $DIR/cycle.rs:6:5: 6:6
+ _4 = &_2; // scope 1 at $DIR/cycle.rs:6:5: 6:6
+ StorageLive(_5); // scope 1 at $DIR/cycle.rs:6:5: 6:8
-+ _3 = move (*_4)() -> [return: bb4, unwind: bb2]; // scope 2 at $SRC_DIR/core/src/ops/function.rs:LL:COL
++ _3 = <fn() {main} as Fn<()>>::call(move _4, move _5) -> [return: bb2, unwind: bb3]; // scope 1 at $DIR/cycle.rs:6:5: 6:8
++ // mir::Constant
++ // + span: $DIR/cycle.rs:6:5: 6:6
++ // + literal: Const { ty: for<'a> extern "rust-call" fn(&'a fn() {main}, ()) -> <fn() {main} as FnOnce<()>>::Output {<fn() {main} as Fn<()>>::call}, val: Value(<ZST>) }
}
bb1: {
@@ -39,19 +40,19 @@
return; // scope 0 at $DIR/cycle.rs:+2:2: +2:2
+ }
+
-+ bb2 (cleanup): {
-+ drop(_2) -> bb3; // scope 1 at $DIR/cycle.rs:7:1: 7:2
++ bb2: {
++ StorageDead(_5); // scope 1 at $DIR/cycle.rs:6:7: 6:8
++ StorageDead(_4); // scope 1 at $DIR/cycle.rs:6:7: 6:8
++ StorageDead(_3); // scope 1 at $DIR/cycle.rs:6:8: 6:9
++ drop(_2) -> bb1; // scope 1 at $DIR/cycle.rs:7:1: 7:2
+ }
+
+ bb3 (cleanup): {
-+ resume; // scope 1 at $DIR/cycle.rs:5:1: 7:2
++ drop(_2) -> bb4; // scope 1 at $DIR/cycle.rs:7:1: 7:2
+ }
+
-+ bb4: {
-+ StorageDead(_5); // scope 1 at $DIR/cycle.rs:6:7: 6:8
-+ StorageDead(_4); // scope 1 at $DIR/cycle.rs:6:7: 6:8
-+ StorageDead(_3); // scope 1 at $DIR/cycle.rs:6:8: 6:9
-+ drop(_2) -> bb1; // scope 1 at $DIR/cycle.rs:7:1: 7:2
++ bb4 (cleanup): {
++ resume; // scope 1 at $DIR/cycle.rs:5:1: 7:2
}
}
diff --git a/src/test/mir-opt/inline/cycle.main.Inline.diff b/src/test/mir-opt/inline/cycle.main.Inline.diff
index 8b4099b9d9f..bd89e09ecd1 100644
--- a/src/test/mir-opt/inline/cycle.main.Inline.diff
+++ b/src/test/mir-opt/inline/cycle.main.Inline.diff
@@ -10,18 +10,6 @@
+ let _3: (); // in scope 1 at $DIR/cycle.rs:6:5: 6:8
+ let mut _4: &fn() {g}; // in scope 1 at $DIR/cycle.rs:6:5: 6:6
+ let mut _5: (); // in scope 1 at $DIR/cycle.rs:6:5: 6:8
-+ scope 2 (inlined <fn() {g} as Fn<()>>::call - shim(fn() {g})) { // at $DIR/cycle.rs:6:5: 6:8
-+ scope 3 (inlined g) { // at $SRC_DIR/core/src/ops/function.rs:LL:COL
-+ let mut _6: fn() {main}; // in scope 3 at $DIR/cycle.rs:12:5: 12:12
-+ scope 4 (inlined f::<fn() {main}>) { // at $DIR/cycle.rs:12:5: 12:12
-+ debug g => _6; // in scope 4 at $DIR/cycle.rs:5:6: 5:7
-+ let _7: (); // in scope 4 at $DIR/cycle.rs:6:5: 6:8
-+ let mut _8: &fn() {main}; // in scope 4 at $DIR/cycle.rs:6:5: 6:6
-+ scope 5 (inlined <fn() {main} as Fn<()>>::call - shim(fn() {main})) { // at $DIR/cycle.rs:6:5: 6:8
-+ }
-+ }
-+ }
-+ }
+ }
bb0: {
@@ -39,11 +27,10 @@
+ StorageLive(_4); // scope 1 at $DIR/cycle.rs:6:5: 6:6
+ _4 = &_2; // scope 1 at $DIR/cycle.rs:6:5: 6:6
+ StorageLive(_5); // scope 1 at $DIR/cycle.rs:6:5: 6:8
-+ StorageLive(_6); // scope 3 at $DIR/cycle.rs:12:5: 12:12
-+ StorageLive(_7); // scope 4 at $DIR/cycle.rs:6:5: 6:8
-+ StorageLive(_8); // scope 4 at $DIR/cycle.rs:6:5: 6:6
-+ _8 = &_6; // scope 4 at $DIR/cycle.rs:6:5: 6:6
-+ _7 = move (*_8)() -> [return: bb4, unwind: bb2]; // scope 5 at $SRC_DIR/core/src/ops/function.rs:LL:COL
++ _3 = <fn() {g} as Fn<()>>::call(move _4, move _5) -> [return: bb2, unwind: bb3]; // scope 1 at $DIR/cycle.rs:6:5: 6:8
++ // mir::Constant
++ // + span: $DIR/cycle.rs:6:5: 6:6
++ // + literal: Const { ty: for<'a> extern "rust-call" fn(&'a fn() {g}, ()) -> <fn() {g} as FnOnce<()>>::Output {<fn() {g} as Fn<()>>::call}, val: Value(<ZST>) }
}
bb1: {
@@ -53,22 +40,19 @@
return; // scope 0 at $DIR/cycle.rs:+2:2: +2:2
+ }
+
-+ bb2 (cleanup): {
-+ drop(_2) -> bb3; // scope 1 at $DIR/cycle.rs:7:1: 7:2
++ bb2: {
++ StorageDead(_5); // scope 1 at $DIR/cycle.rs:6:7: 6:8
++ StorageDead(_4); // scope 1 at $DIR/cycle.rs:6:7: 6:8
++ StorageDead(_3); // scope 1 at $DIR/cycle.rs:6:8: 6:9
++ drop(_2) -> bb1; // scope 1 at $DIR/cycle.rs:7:1: 7:2
+ }
+
+ bb3 (cleanup): {
-+ resume; // scope 1 at $DIR/cycle.rs:5:1: 7:2
++ drop(_2) -> bb4; // scope 1 at $DIR/cycle.rs:7:1: 7:2
+ }
+
-+ bb4: {
-+ StorageDead(_8); // scope 4 at $DIR/cycle.rs:6:7: 6:8
-+ StorageDead(_7); // scope 4 at $DIR/cycle.rs:6:8: 6:9
-+ StorageDead(_6); // scope 3 at $DIR/cycle.rs:12:5: 12:12
-+ StorageDead(_5); // scope 1 at $DIR/cycle.rs:6:7: 6:8
-+ StorageDead(_4); // scope 1 at $DIR/cycle.rs:6:7: 6:8
-+ StorageDead(_3); // scope 1 at $DIR/cycle.rs:6:8: 6:9
-+ drop(_2) -> bb1; // scope 1 at $DIR/cycle.rs:7:1: 7:2
++ bb4 (cleanup): {
++ resume; // scope 1 at $DIR/cycle.rs:5:1: 7:2
}
}
diff --git a/src/test/mir-opt/inline/exponential_runtime.main.Inline.diff b/src/test/mir-opt/inline/exponential_runtime.main.Inline.diff
new file mode 100644
index 00000000000..d9fd7b324c7
--- /dev/null
+++ b/src/test/mir-opt/inline/exponential_runtime.main.Inline.diff
@@ -0,0 +1,50 @@
+- // MIR for `main` before Inline
++ // MIR for `main` after Inline
+
+ fn main() -> () {
+ let mut _0: (); // return place in scope 0 at $DIR/exponential_runtime.rs:+0:11: +0:11
+ let _1: (); // in scope 0 at $DIR/exponential_runtime.rs:+1:5: +1:22
++ scope 1 (inlined <() as G>::call) { // at $DIR/exponential_runtime.rs:86:5: 86:22
++ let _2: (); // in scope 1 at $DIR/exponential_runtime.rs:73:9: 73:25
++ let _3: (); // in scope 1 at $DIR/exponential_runtime.rs:74:9: 74:25
++ let _4: (); // in scope 1 at $DIR/exponential_runtime.rs:75:9: 75:25
++ }
+
+ bb0: {
+ StorageLive(_1); // scope 0 at $DIR/exponential_runtime.rs:+1:5: +1:22
+- _1 = <() as G>::call() -> bb1; // scope 0 at $DIR/exponential_runtime.rs:+1:5: +1:22
++ StorageLive(_2); // scope 1 at $DIR/exponential_runtime.rs:73:9: 73:25
++ _2 = <() as F>::call() -> bb1; // scope 1 at $DIR/exponential_runtime.rs:73:9: 73:25
+ // mir::Constant
+- // + span: $DIR/exponential_runtime.rs:86:5: 86:20
+- // + literal: Const { ty: fn() {<() as G>::call}, val: Value(<ZST>) }
++ // + span: $DIR/exponential_runtime.rs:73:9: 73:23
++ // + literal: Const { ty: fn() {<() as F>::call}, val: Value(<ZST>) }
+ }
+
+ bb1: {
++ StorageDead(_2); // scope 1 at $DIR/exponential_runtime.rs:73:25: 73:26
++ StorageLive(_3); // scope 1 at $DIR/exponential_runtime.rs:74:9: 74:25
++ _3 = <() as F>::call() -> bb2; // scope 1 at $DIR/exponential_runtime.rs:74:9: 74:25
++ // mir::Constant
++ // + span: $DIR/exponential_runtime.rs:74:9: 74:23
++ // + literal: Const { ty: fn() {<() as F>::call}, val: Value(<ZST>) }
++ }
++
++ bb2: {
++ StorageDead(_3); // scope 1 at $DIR/exponential_runtime.rs:74:25: 74:26
++ StorageLive(_4); // scope 1 at $DIR/exponential_runtime.rs:75:9: 75:25
++ _4 = <() as F>::call() -> bb3; // scope 1 at $DIR/exponential_runtime.rs:75:9: 75:25
++ // mir::Constant
++ // + span: $DIR/exponential_runtime.rs:75:9: 75:23
++ // + literal: Const { ty: fn() {<() as F>::call}, val: Value(<ZST>) }
++ }
++
++ bb3: {
++ StorageDead(_4); // scope 1 at $DIR/exponential_runtime.rs:75:25: 75:26
+ StorageDead(_1); // scope 0 at $DIR/exponential_runtime.rs:+1:22: +1:23
+ _0 = const (); // scope 0 at $DIR/exponential_runtime.rs:+0:11: +2:2
+ return; // scope 0 at $DIR/exponential_runtime.rs:+2:2: +2:2
+ }
+ }
+
diff --git a/src/test/mir-opt/inline/exponential_runtime.rs b/src/test/mir-opt/inline/exponential_runtime.rs
new file mode 100644
index 00000000000..d9219d76a98
--- /dev/null
+++ b/src/test/mir-opt/inline/exponential_runtime.rs
@@ -0,0 +1,87 @@
+// Checks that code with exponential runtime does not have exponential behavior in inlining.
+
+trait A {
+ fn call();
+}
+
+trait B {
+ fn call();
+}
+impl<T: A> B for T {
+ #[inline]
+ fn call() {
+ <T as A>::call();
+ <T as A>::call();
+ <T as A>::call();
+ }
+}
+
+trait C {
+ fn call();
+}
+impl<T: B> C for T {
+ #[inline]
+ fn call() {
+ <T as B>::call();
+ <T as B>::call();
+ <T as B>::call();
+ }
+}
+
+trait D {
+ fn call();
+}
+impl<T: C> D for T {
+ #[inline]
+ fn call() {
+ <T as C>::call();
+ <T as C>::call();
+ <T as C>::call();
+ }
+}
+
+trait E {
+ fn call();
+}
+impl<T: D> E for T {
+ #[inline]
+ fn call() {
+ <T as D>::call();
+ <T as D>::call();
+ <T as D>::call();
+ }
+}
+
+trait F {
+ fn call();
+}
+impl<T: E> F for T {
+ #[inline]
+ fn call() {
+ <T as E>::call();
+ <T as E>::call();
+ <T as E>::call();
+ }
+}
+
+trait G {
+ fn call();
+}
+impl<T: F> G for T {
+ #[inline]
+ fn call() {
+ <T as F>::call();
+ <T as F>::call();
+ <T as F>::call();
+ }
+}
+
+impl A for () {
+ #[inline(never)]
+ fn call() {}
+}
+
+// EMIT_MIR exponential_runtime.main.Inline.diff
+fn main() {
+ <() as G>::call();
+}
diff --git a/src/test/mir-opt/inline/inline_cycle.one.Inline.diff b/src/test/mir-opt/inline/inline_cycle.one.Inline.diff
index 5510cd7bc8c..f54a1a747d4 100644
--- a/src/test/mir-opt/inline/inline_cycle.one.Inline.diff
+++ b/src/test/mir-opt/inline/inline_cycle.one.Inline.diff
@@ -5,20 +5,17 @@
let mut _0: (); // return place in scope 0 at $DIR/inline_cycle.rs:+0:10: +0:10
let _1: (); // in scope 0 at $DIR/inline_cycle.rs:+1:5: +1:24
+ scope 1 (inlined <C as Call>::call) { // at $DIR/inline_cycle.rs:14:5: 14:24
-+ scope 2 (inlined <A<C> as Call>::call) { // at $DIR/inline_cycle.rs:43:9: 43:23
-+ scope 3 (inlined <B<C> as Call>::call) { // at $DIR/inline_cycle.rs:28:9: 28:31
-+ }
-+ }
+ }
bb0: {
StorageLive(_1); // scope 0 at $DIR/inline_cycle.rs:+1:5: +1:24
- _1 = <C as Call>::call() -> bb1; // scope 0 at $DIR/inline_cycle.rs:+1:5: +1:24
-+ _1 = <C as Call>::call() -> bb1; // scope 3 at $DIR/inline_cycle.rs:36:9: 36:28
++ _1 = <A<C> as Call>::call() -> bb1; // scope 1 at $DIR/inline_cycle.rs:43:9: 43:23
// mir::Constant
- // + span: $DIR/inline_cycle.rs:14:5: 14:22
-+ // + span: $DIR/inline_cycle.rs:36:9: 36:26
- // + literal: Const { ty: fn() {<C as Call>::call}, val: Value(<ZST>) }
+- // + literal: Const { ty: fn() {<C as Call>::call}, val: Value(<ZST>) }
++ // + span: $DIR/inline_cycle.rs:43:9: 43:21
++ // + literal: Const { ty: fn() {<A<C> as Call>::call}, val: Value(<ZST>) }
}
bb1: {
diff --git a/src/test/mir-opt/inline/inline_cycle.two.Inline.diff b/src/test/mir-opt/inline/inline_cycle.two.Inline.diff
index ab1ea0e3b2c..a940848c269 100644
--- a/src/test/mir-opt/inline/inline_cycle.two.Inline.diff
+++ b/src/test/mir-opt/inline/inline_cycle.two.Inline.diff
@@ -9,11 +9,6 @@
+ debug f => _2; // in scope 1 at $DIR/inline_cycle.rs:53:22: 53:23
+ let _3: (); // in scope 1 at $DIR/inline_cycle.rs:54:5: 54:8
+ let mut _4: (); // in scope 1 at $DIR/inline_cycle.rs:54:5: 54:8
-+ scope 2 (inlined <fn() {f} as FnOnce<()>>::call_once - shim(fn() {f})) { // at $DIR/inline_cycle.rs:54:5: 54:8
-+ scope 3 (inlined f) { // at $SRC_DIR/core/src/ops/function.rs:LL:COL
-+ let _5: (); // in scope 3 at $DIR/inline_cycle.rs:59:5: 59:12
-+ }
-+ }
+ }
bb0: {
@@ -23,23 +18,19 @@
+ _2 = f; // scope 0 at $DIR/inline_cycle.rs:+1:5: +1:12
// mir::Constant
- // + span: $DIR/inline_cycle.rs:49:5: 49:9
-+ // + span: $DIR/inline_cycle.rs:49:10: 49:11
-+ // + literal: Const { ty: fn() {f}, val: Value(<ZST>) }
+- // + literal: Const { ty: fn(fn() {f}) {call::<fn() {f}>}, val: Value(<ZST>) }
+- // mir::Constant
+ // + span: $DIR/inline_cycle.rs:49:10: 49:11
+ // + literal: Const { ty: fn() {f}, val: Value(<ZST>) }
+ StorageLive(_3); // scope 1 at $DIR/inline_cycle.rs:54:5: 54:8
+ StorageLive(_4); // scope 1 at $DIR/inline_cycle.rs:54:5: 54:8
-+ StorageLive(_5); // scope 3 at $DIR/inline_cycle.rs:59:5: 59:12
-+ _5 = call::<fn() {f}>(f) -> bb1; // scope 3 at $DIR/inline_cycle.rs:59:5: 59:12
++ _3 = <fn() {f} as FnOnce<()>>::call_once(move _2, move _4) -> bb1; // scope 1 at $DIR/inline_cycle.rs:54:5: 54:8
+ // mir::Constant
-+ // + span: $DIR/inline_cycle.rs:59:5: 59:9
- // + literal: Const { ty: fn(fn() {f}) {call::<fn() {f}>}, val: Value(<ZST>) }
- // mir::Constant
-- // + span: $DIR/inline_cycle.rs:49:10: 49:11
-+ // + span: $DIR/inline_cycle.rs:59:10: 59:11
- // + literal: Const { ty: fn() {f}, val: Value(<ZST>) }
++ // + span: $DIR/inline_cycle.rs:54:5: 54:6
++ // + literal: Const { ty: extern "rust-call" fn(fn() {f}, ()) -> <fn() {f} as FnOnce<()>>::Output {<fn() {f} as FnOnce<()>>::call_once}, val: Value(<ZST>) }
}
bb1: {
-+ StorageDead(_5); // scope 3 at $DIR/inline_cycle.rs:59:12: 59:13
+ StorageDead(_4); // scope 1 at $DIR/inline_cycle.rs:54:7: 54:8
+ StorageDead(_3); // scope 1 at $DIR/inline_cycle.rs:54:8: 54:9
+ StorageDead(_2); // scope 0 at $DIR/inline_cycle.rs:+1:5: +1:12
diff --git a/src/test/mir-opt/inline/inline_cycle_generic.main.Inline.diff b/src/test/mir-opt/inline/inline_cycle_generic.main.Inline.diff
index 52debab4dd1..04de3e61e5f 100644
--- a/src/test/mir-opt/inline/inline_cycle_generic.main.Inline.diff
+++ b/src/test/mir-opt/inline/inline_cycle_generic.main.Inline.diff
@@ -6,21 +6,18 @@
let _1: (); // in scope 0 at $DIR/inline_cycle_generic.rs:+1:5: +1:24
+ scope 1 (inlined <C as Call>::call) { // at $DIR/inline_cycle_generic.rs:9:5: 9:24
+ scope 2 (inlined <B<A> as Call>::call) { // at $DIR/inline_cycle_generic.rs:38:9: 38:31
-+ scope 3 (inlined <A as Call>::call) { // at $DIR/inline_cycle_generic.rs:31:9: 31:28
-+ scope 4 (inlined <B<C> as Call>::call) { // at $DIR/inline_cycle_generic.rs:23:9: 23:31
-+ }
-+ }
+ }
+ }
bb0: {
StorageLive(_1); // scope 0 at $DIR/inline_cycle_generic.rs:+1:5: +1:24
- _1 = <C as Call>::call() -> bb1; // scope 0 at $DIR/inline_cycle_generic.rs:+1:5: +1:24
-+ _1 = <C as Call>::call() -> bb1; // scope 4 at $DIR/inline_cycle_generic.rs:31:9: 31:28
++ _1 = <A as Call>::call() -> bb1; // scope 2 at $DIR/inline_cycle_generic.rs:31:9: 31:28
// mir::Constant
- // + span: $DIR/inline_cycle_generic.rs:9:5: 9:22
+- // + literal: Const { ty: fn() {<C as Call>::call}, val: Value(<ZST>) }
+ // + span: $DIR/inline_cycle_generic.rs:31:9: 31:26
- // + literal: Const { ty: fn() {<C as Call>::call}, val: Value(<ZST>) }
++ // + literal: Const { ty: fn() {<A as Call>::call}, val: Value(<ZST>) }
}
bb1: {
diff --git a/src/test/mir-opt/inline/inline_diverging.h.Inline.diff b/src/test/mir-opt/inline/inline_diverging.h.Inline.diff
index 75a6ab37008..a01bcf1645b 100644
--- a/src/test/mir-opt/inline/inline_diverging.h.Inline.diff
+++ b/src/test/mir-opt/inline/inline_diverging.h.Inline.diff
@@ -19,14 +19,6 @@
+ scope 3 {
+ debug b => _9; // in scope 3 at $DIR/inline_diverging.rs:28:9: 28:10
+ }
-+ scope 6 (inlined <fn() -> ! {sleep} as Fn<()>>::call - shim(fn() -> ! {sleep})) { // at $DIR/inline_diverging.rs:28:13: 28:16
-+ scope 7 (inlined sleep) { // at $SRC_DIR/core/src/ops/function.rs:LL:COL
-+ }
-+ }
-+ }
-+ scope 4 (inlined <fn() -> ! {sleep} as Fn<()>>::call - shim(fn() -> ! {sleep})) { // at $DIR/inline_diverging.rs:27:13: 27:16
-+ scope 5 (inlined sleep) { // at $SRC_DIR/core/src/ops/function.rs:LL:COL
-+ }
+ }
+ }
@@ -46,11 +38,51 @@
+ StorageLive(_4); // scope 1 at $DIR/inline_diverging.rs:27:13: 27:14
+ _4 = &_2; // scope 1 at $DIR/inline_diverging.rs:27:13: 27:14
+ StorageLive(_5); // scope 1 at $DIR/inline_diverging.rs:27:13: 27:16
-+ goto -> bb1; // scope 5 at $DIR/inline_diverging.rs:39:5: 39:12
++ _3 = <fn() -> ! {sleep} as Fn<()>>::call(move _4, move _5) -> [return: bb1, unwind: bb5]; // scope 1 at $DIR/inline_diverging.rs:27:13: 27:16
++ // mir::Constant
++ // + span: $DIR/inline_diverging.rs:27:13: 27:14
++ // + literal: Const { ty: for<'a> extern "rust-call" fn(&'a fn() -> ! {sleep}, ()) -> <fn() -> ! {sleep} as FnOnce<()>>::Output {<fn() -> ! {sleep} as Fn<()>>::call}, val: Value(<ZST>) }
+ }
+
+ bb1: {
-+ goto -> bb1; // scope 5 at $DIR/inline_diverging.rs:39:5: 39:12
++ StorageDead(_5); // scope 1 at $DIR/inline_diverging.rs:27:15: 27:16
++ StorageDead(_4); // scope 1 at $DIR/inline_diverging.rs:27:15: 27:16
++ StorageLive(_6); // scope 2 at $DIR/inline_diverging.rs:28:13: 28:14
++ _6 = &_2; // scope 2 at $DIR/inline_diverging.rs:28:13: 28:14
++ StorageLive(_7); // scope 2 at $DIR/inline_diverging.rs:28:13: 28:16
++ _9 = <fn() -> ! {sleep} as Fn<()>>::call(move _6, move _7) -> [return: bb2, unwind: bb4]; // scope 2 at $DIR/inline_diverging.rs:28:13: 28:16
++ // mir::Constant
++ // + span: $DIR/inline_diverging.rs:28:13: 28:14
++ // + literal: Const { ty: for<'a> extern "rust-call" fn(&'a fn() -> ! {sleep}, ()) -> <fn() -> ! {sleep} as FnOnce<()>>::Output {<fn() -> ! {sleep} as Fn<()>>::call}, val: Value(<ZST>) }
++ }
++
++ bb2: {
++ StorageDead(_7); // scope 2 at $DIR/inline_diverging.rs:28:15: 28:16
++ StorageDead(_6); // scope 2 at $DIR/inline_diverging.rs:28:15: 28:16
++ StorageLive(_8); // scope 3 at $DIR/inline_diverging.rs:29:6: 29:7
++ _8 = move _3; // scope 3 at $DIR/inline_diverging.rs:29:6: 29:7
++ Deinit(_1); // scope 3 at $DIR/inline_diverging.rs:29:5: 29:11
++ (_1.0: !) = move _8; // scope 3 at $DIR/inline_diverging.rs:29:5: 29:11
++ (_1.1: !) = move _9; // scope 3 at $DIR/inline_diverging.rs:29:5: 29:11
++ StorageDead(_8); // scope 3 at $DIR/inline_diverging.rs:29:10: 29:11
++ StorageDead(_3); // scope 1 at $DIR/inline_diverging.rs:30:1: 30:2
++ drop(_2) -> bb3; // scope 1 at $DIR/inline_diverging.rs:30:1: 30:2
++ }
++
++ bb3: {
++ unreachable; // scope 0 at $DIR/inline_diverging.rs:30:2: 30:2
++ }
++
++ bb4 (cleanup): {
++ drop(_3) -> bb5; // scope 1 at $DIR/inline_diverging.rs:30:1: 30:2
++ }
++
++ bb5 (cleanup): {
++ drop(_2) -> bb6; // scope 1 at $DIR/inline_diverging.rs:30:1: 30:2
++ }
++
++ bb6 (cleanup): {
++ resume; // scope 1 at $DIR/inline_diverging.rs:26:1: 30:2
}
}
diff --git a/src/test/mir-opt/remove_zsts.get_union.PreCodegen.after.mir b/src/test/mir-opt/remove_zsts.get_union.PreCodegen.after.mir
new file mode 100644
index 00000000000..12e914e25e0
--- /dev/null
+++ b/src/test/mir-opt/remove_zsts.get_union.PreCodegen.after.mir
@@ -0,0 +1,10 @@
+// MIR for `get_union` after PreCodegen
+
+fn get_union() -> Foo {
+ let mut _0: Foo; // return place in scope 0 at $DIR/remove_zsts.rs:+0:19: +0:22
+
+ bb0: {
+ Deinit(_0); // scope 0 at $DIR/remove_zsts.rs:+1:5: +1:18
+ return; // scope 0 at $DIR/remove_zsts.rs:+2:2: +2:2
+ }
+}
diff --git a/src/test/mir-opt/remove_zsts.get_union.RemoveZsts.diff b/src/test/mir-opt/remove_zsts.get_union.RemoveZsts.diff
new file mode 100644
index 00000000000..169b7b1054b
--- /dev/null
+++ b/src/test/mir-opt/remove_zsts.get_union.RemoveZsts.diff
@@ -0,0 +1,19 @@
+- // MIR for `get_union` before RemoveZsts
++ // MIR for `get_union` after RemoveZsts
+
+ fn get_union() -> Foo {
+ let mut _0: Foo; // return place in scope 0 at $DIR/remove_zsts.rs:+0:19: +0:22
+ let mut _1: (); // in scope 0 at $DIR/remove_zsts.rs:+1:14: +1:16
+
+ bb0: {
+ StorageLive(_1); // scope 0 at $DIR/remove_zsts.rs:+1:14: +1:16
+- Deinit(_1); // scope 0 at $DIR/remove_zsts.rs:+1:14: +1:16
++ nop; // scope 0 at $DIR/remove_zsts.rs:+1:14: +1:16
+ Deinit(_0); // scope 0 at $DIR/remove_zsts.rs:+1:5: +1:18
+- (_0.0: ()) = move _1; // scope 0 at $DIR/remove_zsts.rs:+1:5: +1:18
++ nop; // scope 0 at $DIR/remove_zsts.rs:+1:5: +1:18
+ StorageDead(_1); // scope 0 at $DIR/remove_zsts.rs:+1:17: +1:18
+ return; // scope 0 at $DIR/remove_zsts.rs:+2:2: +2:2
+ }
+ }
+
diff --git a/src/test/mir-opt/remove_zsts.rs b/src/test/mir-opt/remove_zsts.rs
new file mode 100644
index 00000000000..1cf7ad6e366
--- /dev/null
+++ b/src/test/mir-opt/remove_zsts.rs
@@ -0,0 +1,14 @@
+union Foo {
+ x: (),
+ y: u64,
+}
+
+// EMIT_MIR remove_zsts.get_union.RemoveZsts.diff
+// EMIT_MIR remove_zsts.get_union.PreCodegen.after.mir
+fn get_union() -> Foo {
+ Foo { x: () }
+}
+
+fn main() {
+ get_union();
+}
diff --git a/src/test/mir-opt/remove_zsts_dont_touch_unions.get_union.RemoveZsts.after.mir b/src/test/mir-opt/remove_zsts_dont_touch_unions.get_union.RemoveZsts.after.mir
deleted file mode 100644
index 7d9e6046202..00000000000
--- a/src/test/mir-opt/remove_zsts_dont_touch_unions.get_union.RemoveZsts.after.mir
+++ /dev/null
@@ -1,15 +0,0 @@
-// MIR for `get_union` after RemoveZsts
-
-fn get_union() -> Foo {
- let mut _0: Foo; // return place in scope 0 at $DIR/remove_zsts_dont_touch_unions.rs:+0:19: +0:22
- let mut _1: (); // in scope 0 at $DIR/remove_zsts_dont_touch_unions.rs:+1:14: +1:16
-
- bb0: {
- StorageLive(_1); // scope 0 at $DIR/remove_zsts_dont_touch_unions.rs:+1:14: +1:16
- nop; // scope 0 at $DIR/remove_zsts_dont_touch_unions.rs:+1:14: +1:16
- Deinit(_0); // scope 0 at $DIR/remove_zsts_dont_touch_unions.rs:+1:5: +1:18
- (_0.0: ()) = move _1; // scope 0 at $DIR/remove_zsts_dont_touch_unions.rs:+1:5: +1:18
- StorageDead(_1); // scope 0 at $DIR/remove_zsts_dont_touch_unions.rs:+1:17: +1:18
- return; // scope 0 at $DIR/remove_zsts_dont_touch_unions.rs:+2:2: +2:2
- }
-}
diff --git a/src/test/mir-opt/remove_zsts_dont_touch_unions.rs b/src/test/mir-opt/remove_zsts_dont_touch_unions.rs
deleted file mode 100644
index 8b9de9b4d65..00000000000
--- a/src/test/mir-opt/remove_zsts_dont_touch_unions.rs
+++ /dev/null
@@ -1,19 +0,0 @@
-// unit-test: RemoveZsts
-
-// Ensure RemoveZsts doesn't remove ZST assignments to union fields,
-// which causes problems in Miri.
-
-union Foo {
- x: (),
- y: u64,
-}
-
-// EMIT_MIR remove_zsts_dont_touch_unions.get_union.RemoveZsts.after.mir
-fn get_union() -> Foo {
- Foo { x: () }
-}
-
-
-fn main() {
- get_union();
-}
diff --git a/src/test/mir-opt/separate_const_switch.identity.SeparateConstSwitch.diff b/src/test/mir-opt/separate_const_switch.identity.SeparateConstSwitch.diff
index f25b3ce724b..b28c6f687f7 100644
--- a/src/test/mir-opt/separate_const_switch.identity.SeparateConstSwitch.diff
+++ b/src/test/mir-opt/separate_const_switch.identity.SeparateConstSwitch.diff
@@ -22,9 +22,6 @@
let mut _18: i32; // in scope 8 at $SRC_DIR/core/src/result.rs:LL:COL
scope 9 {
debug e => _16; // in scope 9 at $SRC_DIR/core/src/result.rs:LL:COL
- scope 10 (inlined <i32 as From<i32>>::from) { // at $SRC_DIR/core/src/result.rs:LL:COL
- debug t => _18; // in scope 10 at $SRC_DIR/core/src/convert/mod.rs:LL:COL
- }
}
}
}
@@ -95,18 +92,11 @@
StorageLive(_17); // scope 9 at $SRC_DIR/core/src/result.rs:LL:COL
StorageLive(_18); // scope 9 at $SRC_DIR/core/src/result.rs:LL:COL
_18 = move _16; // scope 9 at $SRC_DIR/core/src/result.rs:LL:COL
- _17 = move _18; // scope 10 at $SRC_DIR/core/src/convert/mod.rs:LL:COL
- StorageDead(_18); // scope 9 at $SRC_DIR/core/src/result.rs:LL:COL
- Deinit(_0); // scope 9 at $SRC_DIR/core/src/result.rs:LL:COL
- ((_0 as Err).0: i32) = move _17; // scope 9 at $SRC_DIR/core/src/result.rs:LL:COL
- discriminant(_0) = 1; // scope 9 at $SRC_DIR/core/src/result.rs:LL:COL
- StorageDead(_17); // scope 9 at $SRC_DIR/core/src/result.rs:LL:COL
- StorageDead(_16); // scope 8 at $SRC_DIR/core/src/result.rs:LL:COL
- StorageDead(_8); // scope 2 at $DIR/separate_const_switch.rs:+1:9: +1:10
- StorageDead(_6); // scope 0 at $DIR/separate_const_switch.rs:+1:9: +1:10
- StorageDead(_2); // scope 0 at $DIR/separate_const_switch.rs:+1:10: +1:11
- StorageDead(_3); // scope 0 at $DIR/separate_const_switch.rs:+2:1: +2:2
- return; // scope 0 at $DIR/separate_const_switch.rs:+2:2: +2:2
+- _17 = <i32 as From<i32>>::from(move _18) -> bb8; // scope 9 at $SRC_DIR/core/src/result.rs:LL:COL
++ _17 = <i32 as From<i32>>::from(move _18) -> bb7; // scope 9 at $SRC_DIR/core/src/result.rs:LL:COL
+ // mir::Constant
+ // + span: $SRC_DIR/core/src/result.rs:LL:COL
+ // + literal: Const { ty: fn(i32) -> i32 {<i32 as From<i32>>::from}, val: Value(<ZST>) }
}
- bb5: {
@@ -152,5 +142,20 @@
+ _5 = discriminant(_3); // scope 0 at $DIR/separate_const_switch.rs:+1:8: +1:10
+ switchInt(move _5) -> [0_isize: bb1, 1_isize: bb3, otherwise: bb2]; // scope 0 at $DIR/separate_const_switch.rs:+1:8: +1:10
}
+
+- bb8: {
++ bb7: {
+ StorageDead(_18); // scope 9 at $SRC_DIR/core/src/result.rs:LL:COL
+ Deinit(_0); // scope 9 at $SRC_DIR/core/src/result.rs:LL:COL
+ ((_0 as Err).0: i32) = move _17; // scope 9 at $SRC_DIR/core/src/result.rs:LL:COL
+ discriminant(_0) = 1; // scope 9 at $SRC_DIR/core/src/result.rs:LL:COL
+ StorageDead(_17); // scope 9 at $SRC_DIR/core/src/result.rs:LL:COL
+ StorageDead(_16); // scope 8 at $SRC_DIR/core/src/result.rs:LL:COL
+ StorageDead(_8); // scope 2 at $DIR/separate_const_switch.rs:+1:9: +1:10
+ StorageDead(_6); // scope 0 at $DIR/separate_const_switch.rs:+1:9: +1:10
+ StorageDead(_2); // scope 0 at $DIR/separate_const_switch.rs:+1:10: +1:11
+ StorageDead(_3); // scope 0 at $DIR/separate_const_switch.rs:+2:1: +2:2
+ return; // scope 0 at $DIR/separate_const_switch.rs:+2:2: +2:2
+ }
}
diff --git a/src/test/rustdoc-gui/enum-variants.goml b/src/test/rustdoc-gui/enum-variants.goml
index 230abb236bd..8dfc49285f2 100644
--- a/src/test/rustdoc-gui/enum-variants.goml
+++ b/src/test/rustdoc-gui/enum-variants.goml
@@ -3,3 +3,8 @@ goto: "file://" + |DOC_PATH| + "/test_docs/enum.WhoLetTheDogOut.html"
assert-css: (".variants > .variant", {"margin": "0px 0px 12px"})
assert-css: (".variants > .docblock", {"margin": "0px 0px 32px 24px"})
+
+assert-css: (
+ "details.non-exhaustive > summary",
+ {"font-family": '"Fira Sans", Arial, NanumBarunGothic, sans-serif'},
+)
diff --git a/src/test/rustdoc-gui/method-margins.goml b/src/test/rustdoc-gui/method-margins.goml
index 397bcd40b36..ed36bcdec17 100644
--- a/src/test/rustdoc-gui/method-margins.goml
+++ b/src/test/rustdoc-gui/method-margins.goml
@@ -1,3 +1,4 @@
+// This test ensures that the margins on methods are coherent inside an impl block.
goto: "file://" + |DOC_PATH| + "/test_docs/trait_members/struct.HasTrait.html#impl-TraitMembers-for-HasTrait"
assert-count: ("#trait-implementations-list > .rustdoc-toggle", 1)
diff --git a/src/test/rustdoc-gui/scrape-examples-button-focus.goml b/src/test/rustdoc-gui/scrape-examples-button-focus.goml
index 2a263a87a47..a222139f1dc 100644
--- a/src/test/rustdoc-gui/scrape-examples-button-focus.goml
+++ b/src/test/rustdoc-gui/scrape-examples-button-focus.goml
@@ -1,4 +1,17 @@
goto: "file://" + |DOC_PATH| + "/scrape_examples/fn.test.html"
+
+store-property: (initialScrollTop, ".scraped-example-list > .scraped-example pre", "scrollTop")
+focus: ".scraped-example-list > .scraped-example .next"
+press-key: "Enter"
+assert-property-false: (".scraped-example-list > .scraped-example pre", {
+ "scrollTop": |initialScrollTop|
+})
+focus: ".scraped-example-list > .scraped-example .prev"
+press-key: "Enter"
+assert-property: (".scraped-example-list > .scraped-example pre", {
+ "scrollTop": |initialScrollTop|
+})
+
store-property: (smallOffsetHeight, ".scraped-example-list > .scraped-example pre", "offsetHeight")
assert-property-false: (".scraped-example-list > .scraped-example pre", {
"scrollHeight": |smallOffsetHeight|
diff --git a/src/test/rustdoc-gui/src/scrape_examples/examples/check.rs b/src/test/rustdoc-gui/src/scrape_examples/examples/check.rs
index 3e69c6086ae..b3f682fe497 100644
--- a/src/test/rustdoc-gui/src/scrape_examples/examples/check.rs
+++ b/src/test/rustdoc-gui/src/scrape_examples/examples/check.rs
@@ -22,4 +22,5 @@ fn main() {
println!("hello world!");
println!("hello world!");
}
+ scrape_examples::test();
}
diff --git a/src/test/rustdoc-gui/src/test_docs/lib.rs b/src/test/rustdoc-gui/src/test_docs/lib.rs
index dea154c9319..1340511d472 100644
--- a/src/test/rustdoc-gui/src/test_docs/lib.rs
+++ b/src/test/rustdoc-gui/src/test_docs/lib.rs
@@ -76,6 +76,7 @@ impl AsRef<str> for Foo {
///
/// # title!
#[doc(alias = "ThisIsAnAlias")]
+#[non_exhaustive]
pub enum WhoLetTheDogOut {
/// Woof!
Woof,
diff --git a/src/test/rustdoc-gui/toggle-docs.goml b/src/test/rustdoc-gui/toggle-docs.goml
index b7d10723767..45bb8daf1f2 100644
--- a/src/test/rustdoc-gui/toggle-docs.goml
+++ b/src/test/rustdoc-gui/toggle-docs.goml
@@ -7,6 +7,10 @@ wait-for: 50
// This is now collapsed so there shouldn't be the "open" attribute on details.
assert-attribute-false: ("#main-content > details.top-doc", {"open": ""})
assert-text: ("#toggle-all-docs", "[+]")
+assert-css: (
+ "#main-content > details.top-doc > summary",
+ {"font-family": '"Fira Sans", Arial, NanumBarunGothic, sans-serif'},
+)
click: "#toggle-all-docs"
// Not collapsed anymore so the "open" attribute should be back.
wait-for-attribute: ("#main-content > details.top-doc", {"open": ""})
diff --git a/src/test/rustdoc-ui/z-help.stdout b/src/test/rustdoc-ui/z-help.stdout
index 55154803098..94cf7b94241 100644
--- a/src/test/rustdoc-ui/z-help.stdout
+++ b/src/test/rustdoc-ui/z-help.stdout
@@ -77,6 +77,7 @@
-Z location-detail=val -- what location details should be tracked when using caller_location, either `none`, or a comma separated list of location details, for which valid options are `file`, `line`, and `column` (default: `file,line,column`)
-Z ls=val -- list the symbols defined by a library crate (default: no)
-Z macro-backtrace=val -- show macro backtraces (default: no)
+ -Z maximal-hir-to-mir-coverage=val -- save as much information as possible about the correspondence between MIR and HIR as source scopes (default: no)
-Z merge-functions=val -- control the operation of the MergeFunctions LLVM pass, taking the same values as the target option of the same name
-Z meta-stats=val -- gather metadata statistics (default: no)
-Z mir-emit-retag=val -- emit Retagging MIR statements, interpreted e.g., by miri; implies -Zmir-opt-level=0 (default: no)
diff --git a/src/test/ui/associated-inherent-types/issue-104260.rs b/src/test/ui/associated-inherent-types/issue-104260.rs
new file mode 100644
index 00000000000..a73cd1775b4
--- /dev/null
+++ b/src/test/ui/associated-inherent-types/issue-104260.rs
@@ -0,0 +1,14 @@
+// check-pass
+
+#![feature(inherent_associated_types)]
+#![allow(incomplete_features)]
+
+struct Foo;
+
+impl Foo {
+ type Bar<T> = u8;
+}
+
+fn main() {
+ let a: Foo::Bar<()>;
+}
diff --git a/src/test/ui/associated-inherent-types/normalize-projection-0.rs b/src/test/ui/associated-inherent-types/normalize-projection-0.rs
new file mode 100644
index 00000000000..50763ecddf9
--- /dev/null
+++ b/src/test/ui/associated-inherent-types/normalize-projection-0.rs
@@ -0,0 +1,22 @@
+// check-pass
+
+#![feature(inherent_associated_types)]
+#![allow(incomplete_features)]
+
+struct S<T>(T);
+
+impl<T: O> S<T> {
+ type P = <T as O>::P;
+}
+
+trait O {
+ type P;
+}
+
+impl O for i32 {
+ type P = String;
+}
+
+fn main() {
+ let _: S<i32>::P = String::new();
+}
diff --git a/src/test/ui/associated-inherent-types/normalize-projection-1.rs b/src/test/ui/associated-inherent-types/normalize-projection-1.rs
new file mode 100644
index 00000000000..2f7b2551a03
--- /dev/null
+++ b/src/test/ui/associated-inherent-types/normalize-projection-1.rs
@@ -0,0 +1,22 @@
+// check-pass
+
+#![feature(inherent_associated_types)]
+#![allow(incomplete_features)]
+
+struct S;
+
+impl S {
+ type P<T: O> = <T as O>::P;
+}
+
+trait O {
+ type P;
+}
+
+impl O for i32 {
+ type P = String;
+}
+
+fn main() {
+ let _: S::P<i32> = String::new();
+}
diff --git a/src/test/ui/async-await/async-await-let-else.drop-tracking.stderr b/src/test/ui/async-await/async-await-let-else.drop-tracking.stderr
index 3be7f370da3..616623ee077 100644
--- a/src/test/ui/async-await/async-await-let-else.drop-tracking.stderr
+++ b/src/test/ui/async-await/async-await-let-else.drop-tracking.stderr
@@ -40,7 +40,7 @@ LL | async fn bar2<T>(_: T) -> ! {
LL | | panic!()
LL | | }
| |_^
- = note: required because it captures the following types: `ResumeTy`, `Option<bool>`, `impl Future<Output = !>`, `()`
+ = note: required because it captures the following types: `&mut Context<'_>`, `Option<bool>`, `impl Future<Output = !>`, `()`
note: required because it's used within this `async fn` body
--> $DIR/async-await-let-else.rs:21:32
|
diff --git a/src/test/ui/async-await/in-trait/return-type-suggestion.rs b/src/test/ui/async-await/in-trait/return-type-suggestion.rs
new file mode 100644
index 00000000000..3446761d119
--- /dev/null
+++ b/src/test/ui/async-await/in-trait/return-type-suggestion.rs
@@ -0,0 +1,14 @@
+// edition: 2021
+
+#![feature(async_fn_in_trait)]
+//~^ WARN the feature `async_fn_in_trait` is incomplete and may not be safe to use and/or cause compiler crashes
+
+trait A {
+ async fn e() {
+ Ok(())
+ //~^ ERROR mismatched types
+ //~| HELP consider using a semicolon here
+ }
+}
+
+fn main() {}
diff --git a/src/test/ui/async-await/in-trait/return-type-suggestion.stderr b/src/test/ui/async-await/in-trait/return-type-suggestion.stderr
new file mode 100644
index 00000000000..5a9b15e54a0
--- /dev/null
+++ b/src/test/ui/async-await/in-trait/return-type-suggestion.stderr
@@ -0,0 +1,23 @@
+warning: the feature `async_fn_in_trait` is incomplete and may not be safe to use and/or cause compiler crashes
+ --> $DIR/return-type-suggestion.rs:3:12
+ |
+LL | #![feature(async_fn_in_trait)]
+ | ^^^^^^^^^^^^^^^^^
+ |
+ = note: see issue #91611 <https://github.com/rust-lang/rust/issues/91611> for more information
+ = note: `#[warn(incomplete_features)]` on by default
+
+error[E0308]: mismatched types
+ --> $DIR/return-type-suggestion.rs:8:9
+ |
+LL | Ok(())
+ | ^^^^^^- help: consider using a semicolon here: `;`
+ | |
+ | expected `()`, found enum `Result`
+ |
+ = note: expected unit type `()`
+ found enum `Result<(), _>`
+
+error: aborting due to previous error; 1 warning emitted
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/async-await/issue-68112.drop_tracking.stderr b/src/test/ui/async-await/issue-68112.drop_tracking.stderr
index f2802698fd5..1c90bedae79 100644
--- a/src/test/ui/async-await/issue-68112.drop_tracking.stderr
+++ b/src/test/ui/async-await/issue-68112.drop_tracking.stderr
@@ -57,7 +57,7 @@ note: required because it appears within the type `impl Future<Output = Arc<RefC
|
LL | fn make_non_send_future2() -> impl Future<Output = Arc<RefCell<i32>>> {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
- = note: required because it captures the following types: `ResumeTy`, `impl Future<Output = Arc<RefCell<i32>>>`, `()`, `Ready<i32>`
+ = note: required because it captures the following types: `&mut Context<'_>`, `impl Future<Output = Arc<RefCell<i32>>>`, `()`, `Ready<i32>`
note: required because it's used within this `async` block
--> $DIR/issue-68112.rs:60:20
|
diff --git a/src/test/ui/async-await/issue-68112.no_drop_tracking.stderr b/src/test/ui/async-await/issue-68112.no_drop_tracking.stderr
index 38eb85b302f..e09ae7fedd8 100644
--- a/src/test/ui/async-await/issue-68112.no_drop_tracking.stderr
+++ b/src/test/ui/async-await/issue-68112.no_drop_tracking.stderr
@@ -57,7 +57,7 @@ note: required because it appears within the type `impl Future<Output = Arc<RefC
|
LL | fn make_non_send_future2() -> impl Future<Output = Arc<RefCell<i32>>> {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
- = note: required because it captures the following types: `ResumeTy`, `impl Future<Output = Arc<RefCell<i32>>>`, `()`, `i32`, `Ready<i32>`
+ = note: required because it captures the following types: `&mut Context<'_>`, `impl Future<Output = Arc<RefCell<i32>>>`, `()`, `i32`, `Ready<i32>`
note: required because it's used within this `async` block
--> $DIR/issue-68112.rs:60:20
|
diff --git a/src/test/ui/async-await/issue-69446-fnmut-capture.stderr b/src/test/ui/async-await/issue-69446-fnmut-capture.stderr
index 3d2b0402bc5..e6ad2f0d444 100644
--- a/src/test/ui/async-await/issue-69446-fnmut-capture.stderr
+++ b/src/test/ui/async-await/issue-69446-fnmut-capture.stderr
@@ -14,6 +14,9 @@ LL | | });
|
= note: `FnMut` closures only have access to their captured variables while they are executing...
= note: ...therefore, they cannot allow references to captured variables to escape
+ = note: requirement occurs because of a mutable reference to `Context<'_>`
+ = note: mutable references are invariant over their type parameter
+ = help: see <https://doc.rust-lang.org/nomicon/subtyping.html> for more information about variance
error: aborting due to previous error
diff --git a/src/test/ui/async-await/issue-70935-complex-spans.drop_tracking.stderr b/src/test/ui/async-await/issue-70935-complex-spans.drop_tracking.stderr
index 721234aa4a7..a8fd97cde8f 100644
--- a/src/test/ui/async-await/issue-70935-complex-spans.drop_tracking.stderr
+++ b/src/test/ui/async-await/issue-70935-complex-spans.drop_tracking.stderr
@@ -18,7 +18,7 @@ LL | async fn baz<T>(_c: impl FnMut() -> T) where T: Future<Output=()> {
| ___________________________________________________________________^
LL | | }
| |_^
- = note: required because it captures the following types: `ResumeTy`, `impl Future<Output = ()>`, `()`
+ = note: required because it captures the following types: `&mut Context<'_>`, `impl Future<Output = ()>`, `()`
note: required because it's used within this `async` block
--> $DIR/issue-70935-complex-spans.rs:16:5
|
diff --git a/src/test/ui/async-await/partial-drop-partial-reinit.drop_tracking.stderr b/src/test/ui/async-await/partial-drop-partial-reinit.drop_tracking.stderr
index 17b4ef7bdc6..25876d50840 100644
--- a/src/test/ui/async-await/partial-drop-partial-reinit.drop_tracking.stderr
+++ b/src/test/ui/async-await/partial-drop-partial-reinit.drop_tracking.stderr
@@ -11,7 +11,7 @@ LL | async fn foo() {
|
= help: within `impl Future<Output = ()>`, the trait `Send` is not implemented for `NotSend`
= note: required because it appears within the type `(NotSend,)`
- = note: required because it captures the following types: `ResumeTy`, `(NotSend,)`, `()`, `impl Future<Output = ()>`
+ = note: required because it captures the following types: `&mut Context<'_>`, `(NotSend,)`, `()`, `impl Future<Output = ()>`
note: required because it's used within this `async fn` body
--> $DIR/partial-drop-partial-reinit.rs:31:16
|
diff --git a/src/test/ui/async-await/partial-drop-partial-reinit.no_drop_tracking.stderr b/src/test/ui/async-await/partial-drop-partial-reinit.no_drop_tracking.stderr
index 34d8a159f10..dba2a620779 100644
--- a/src/test/ui/async-await/partial-drop-partial-reinit.no_drop_tracking.stderr
+++ b/src/test/ui/async-await/partial-drop-partial-reinit.no_drop_tracking.stderr
@@ -11,7 +11,7 @@ LL | async fn foo() {
|
= help: within `impl Future<Output = ()>`, the trait `Send` is not implemented for `NotSend`
= note: required because it appears within the type `(NotSend,)`
- = note: required because it captures the following types: `ResumeTy`, `(NotSend,)`, `impl Future<Output = ()>`, `()`
+ = note: required because it captures the following types: `&mut Context<'_>`, `(NotSend,)`, `impl Future<Output = ()>`, `()`
note: required because it's used within this `async fn` body
--> $DIR/partial-drop-partial-reinit.rs:31:16
|
diff --git a/src/test/ui/async-await/track-caller/issue-105134.rs b/src/test/ui/async-await/track-caller/issue-105134.rs
new file mode 100644
index 00000000000..4e52b8e250b
--- /dev/null
+++ b/src/test/ui/async-await/track-caller/issue-105134.rs
@@ -0,0 +1,11 @@
+// check-pass
+// edition:2021
+
+#[track_caller]
+fn f() {
+ let _ = async {};
+}
+
+fn main() {
+ f();
+}
diff --git a/src/test/ui/async-await/track-caller/panic-track-caller.rs b/src/test/ui/async-await/track-caller/panic-track-caller.rs
index b113c56412f..5ebfeb3f36a 100644
--- a/src/test/ui/async-await/track-caller/panic-track-caller.rs
+++ b/src/test/ui/async-await/track-caller/panic-track-caller.rs
@@ -54,6 +54,19 @@ async fn foo_track_caller() {
bar_track_caller().await
}
+struct Foo;
+
+impl Foo {
+ #[track_caller]
+ async fn bar_assoc() {
+ panic!();
+ }
+}
+
+async fn foo_assoc() {
+ Foo::bar_assoc().await
+}
+
fn panicked_at(f: impl FnOnce() + panic::UnwindSafe) -> u32 {
let loc = Arc::new(Mutex::new(None));
@@ -73,4 +86,5 @@ fn panicked_at(f: impl FnOnce() + panic::UnwindSafe) -> u32 {
fn main() {
assert_eq!(panicked_at(|| block_on(foo())), 41);
assert_eq!(panicked_at(|| block_on(foo_track_caller())), 54);
+ assert_eq!(panicked_at(|| block_on(foo_assoc())), 67);
}
diff --git a/src/test/ui/auto-traits/bad-generics-on-dyn.rs b/src/test/ui/auto-traits/bad-generics-on-dyn.rs
new file mode 100644
index 00000000000..3f8ac14c72d
--- /dev/null
+++ b/src/test/ui/auto-traits/bad-generics-on-dyn.rs
@@ -0,0 +1,11 @@
+#![feature(auto_traits)]
+
+auto trait Trait1<'a> {}
+//~^ ERROR auto traits cannot have generic parameters
+
+fn f<'a>(x: &dyn Trait1<'a>)
+{}
+
+fn main() {
+ f(&1);
+}
diff --git a/src/test/ui/auto-traits/bad-generics-on-dyn.stderr b/src/test/ui/auto-traits/bad-generics-on-dyn.stderr
new file mode 100644
index 00000000000..ade69ced606
--- /dev/null
+++ b/src/test/ui/auto-traits/bad-generics-on-dyn.stderr
@@ -0,0 +1,11 @@
+error[E0567]: auto traits cannot have generic parameters
+ --> $DIR/bad-generics-on-dyn.rs:3:18
+ |
+LL | auto trait Trait1<'a> {}
+ | ------^^^^ help: remove the parameters
+ | |
+ | auto trait cannot have generic parameters
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0567`.
diff --git a/src/test/ui/binop/binop-mul-i32-f32.stderr b/src/test/ui/binop/binop-mul-i32-f32.stderr
index 21c490965b1..c986bc3fd1e 100644
--- a/src/test/ui/binop/binop-mul-i32-f32.stderr
+++ b/src/test/ui/binop/binop-mul-i32-f32.stderr
@@ -6,15 +6,10 @@ LL | x * y
|
= help: the trait `Mul<f32>` is not implemented for `i32`
= help: the following other types implement trait `Mul<Rhs>`:
- <&'a f32 as Mul<f32>>
- <&'a f64 as Mul<f64>>
- <&'a i128 as Mul<i128>>
- <&'a i16 as Mul<i16>>
<&'a i32 as Mul<i32>>
- <&'a i64 as Mul<i64>>
- <&'a i8 as Mul<i8>>
- <&'a isize as Mul<isize>>
- and 49 others
+ <&i32 as Mul<&i32>>
+ <i32 as Mul<&i32>>
+ <i32 as Mul>
error: aborting due to previous error
diff --git a/src/test/ui/const-generics/defaults/rp_impl_trait_fail.stderr b/src/test/ui/const-generics/defaults/rp_impl_trait_fail.stderr
index f2e7777ce68..a46bd53520b 100644
--- a/src/test/ui/const-generics/defaults/rp_impl_trait_fail.stderr
+++ b/src/test/ui/const-generics/defaults/rp_impl_trait_fail.stderr
@@ -18,9 +18,7 @@ LL |
LL | 1_u32
| ----- return type was inferred to be `u32` here
|
- = help: the following other types implement trait `Traitor<N, M>`:
- <u32 as Traitor<N, 2>>
- <u64 as Traitor<1, 2>>
+ = help: the trait `Traitor<N, 2>` is implemented for `u32`
error[E0277]: the trait bound `u64: Traitor` is not satisfied
--> $DIR/rp_impl_trait_fail.rs:21:13
@@ -31,9 +29,7 @@ LL |
LL | 1_u64
| ----- return type was inferred to be `u64` here
|
- = help: the following other types implement trait `Traitor<N, M>`:
- <u32 as Traitor<N, 2>>
- <u64 as Traitor<1, 2>>
+ = help: the trait `Traitor<1, 2>` is implemented for `u64`
error: aborting due to 3 previous errors
diff --git a/src/test/ui/const-generics/defaults/self-referential.rs b/src/test/ui/const-generics/defaults/self-referential.rs
new file mode 100644
index 00000000000..14a870dc39b
--- /dev/null
+++ b/src/test/ui/const-generics/defaults/self-referential.rs
@@ -0,0 +1,4 @@
+trait Foo<const M: u8, const M: u8 = M> {}
+//~^ ERROR the name `M` is already used for a generic parameter in this item's generic parameters
+impl Foo<2> for () {}
+fn main() {}
diff --git a/src/test/ui/const-generics/defaults/self-referential.stderr b/src/test/ui/const-generics/defaults/self-referential.stderr
new file mode 100644
index 00000000000..170c1f7f7b2
--- /dev/null
+++ b/src/test/ui/const-generics/defaults/self-referential.stderr
@@ -0,0 +1,11 @@
+error[E0403]: the name `M` is already used for a generic parameter in this item's generic parameters
+ --> $DIR/self-referential.rs:1:30
+ |
+LL | trait Foo<const M: u8, const M: u8 = M> {}
+ | - ^ already used
+ | |
+ | first use of `M`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0403`.
diff --git a/src/test/ui/const-generics/generic_const_exprs/const_kind_expr/wf_obligation.rs b/src/test/ui/const-generics/generic_const_exprs/const_kind_expr/wf_obligation.rs
new file mode 100644
index 00000000000..6093fc70b16
--- /dev/null
+++ b/src/test/ui/const-generics/generic_const_exprs/const_kind_expr/wf_obligation.rs
@@ -0,0 +1,22 @@
+#![feature(generic_const_exprs, generic_arg_infer)]
+#![allow(incomplete_features)]
+
+// minimized repro for #105205
+//
+// the `foo::<_, L>` call results in a `WellFormed(_)` obligation and a
+// `ConstEvaluatable(Unevaluated(_ + 1 + L))` obligation. Attempting to fulfill the latter
+// unifies the `_` with `Expr(L - 1)` from the paramenv which turns the `WellFormed`
+// obligation into `WellFormed(Expr(L - 1))`
+
+fn foo<const N: usize, const M: usize>(_: [(); N + 1 + M]) {}
+
+fn ice<const L: usize>()
+where
+ [(); (L - 1) + 1 + L]:,
+{
+ foo::<_, L>([(); L + 1 + L]);
+ //~^ ERROR: mismatched types
+ //~^^ ERROR: unconstrained generic constant
+}
+
+fn main() {}
diff --git a/src/test/ui/const-generics/generic_const_exprs/const_kind_expr/wf_obligation.stderr b/src/test/ui/const-generics/generic_const_exprs/const_kind_expr/wf_obligation.stderr
new file mode 100644
index 00000000000..da5194696e6
--- /dev/null
+++ b/src/test/ui/const-generics/generic_const_exprs/const_kind_expr/wf_obligation.stderr
@@ -0,0 +1,20 @@
+error[E0308]: mismatched types
+ --> $DIR/wf_obligation.rs:17:17
+ |
+LL | foo::<_, L>([(); L + 1 + L]);
+ | ^^^^^^^^^^^^^^^ expected `N + 1 + M`, found `L + 1 + L`
+ |
+ = note: expected constant `N + 1 + M`
+ found constant `L + 1 + L`
+
+error: unconstrained generic constant
+ --> $DIR/wf_obligation.rs:17:22
+ |
+LL | foo::<_, L>([(); L + 1 + L]);
+ | ^^^^^^^^^
+ |
+ = help: try adding a `where` bound using this expression: `where [(); L + 1 + L]:`
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/consts/const-eval/const-eval-overflow-3b.stderr b/src/test/ui/consts/const-eval/const-eval-overflow-3b.stderr
index c685922c456..f199170018f 100644
--- a/src/test/ui/consts/const-eval/const-eval-overflow-3b.stderr
+++ b/src/test/ui/consts/const-eval/const-eval-overflow-3b.stderr
@@ -12,15 +12,10 @@ LL | = [0; (i8::MAX + 1u8) as usize];
|
= help: the trait `~const Add<u8>` is not implemented for `i8`
= help: the following other types implement trait `Add<Rhs>`:
- <&'a f32 as Add<f32>>
- <&'a f64 as Add<f64>>
- <&'a i128 as Add<i128>>
- <&'a i16 as Add<i16>>
- <&'a i32 as Add<i32>>
- <&'a i64 as Add<i64>>
<&'a i8 as Add<i8>>
- <&'a isize as Add<isize>>
- and 48 others
+ <&i8 as Add<&i8>>
+ <i8 as Add<&i8>>
+ <i8 as Add>
error: aborting due to 2 previous errors
diff --git a/src/test/ui/consts/const-eval/const-eval-overflow-4b.stderr b/src/test/ui/consts/const-eval/const-eval-overflow-4b.stderr
index b396079240a..1f8e402317a 100644
--- a/src/test/ui/consts/const-eval/const-eval-overflow-4b.stderr
+++ b/src/test/ui/consts/const-eval/const-eval-overflow-4b.stderr
@@ -12,15 +12,10 @@ LL | : [u32; (i8::MAX as i8 + 1u8) as usize]
|
= help: the trait `~const Add<u8>` is not implemented for `i8`
= help: the following other types implement trait `Add<Rhs>`:
- <&'a f32 as Add<f32>>
- <&'a f64 as Add<f64>>
- <&'a i128 as Add<i128>>
- <&'a i16 as Add<i16>>
- <&'a i32 as Add<i32>>
- <&'a i64 as Add<i64>>
<&'a i8 as Add<i8>>
- <&'a isize as Add<isize>>
- and 48 others
+ <&i8 as Add<&i8>>
+ <i8 as Add<&i8>>
+ <i8 as Add>
error[E0604]: only `u8` can be cast as `char`, not `i8`
--> $DIR/const-eval-overflow-4b.rs:22:13
diff --git a/src/test/ui/did_you_mean/issue-39802-show-5-trait-impls.stderr b/src/test/ui/did_you_mean/issue-39802-show-5-trait-impls.stderr
index d27b05fe7f7..7229b9ac986 100644
--- a/src/test/ui/did_you_mean/issue-39802-show-5-trait-impls.stderr
+++ b/src/test/ui/did_you_mean/issue-39802-show-5-trait-impls.stderr
@@ -12,10 +12,6 @@ LL | Foo::<i32>::bar(&1i8);
<i8 as Foo<u32>>
<i8 as Foo<u64>>
<i8 as Foo<u8>>
- <u8 as Foo<bool>>
- <u8 as Foo<u16>>
- <u8 as Foo<u32>>
- <u8 as Foo<u64>>
error[E0277]: the trait bound `u8: Foo<i32>` is not satisfied
--> $DIR/issue-39802-show-5-trait-impls.rs:25:21
@@ -26,11 +22,6 @@ LL | Foo::<i32>::bar(&1u8);
| required by a bound introduced by this call
|
= help: the following other types implement trait `Foo<B>`:
- <i8 as Foo<bool>>
- <i8 as Foo<u16>>
- <i8 as Foo<u32>>
- <i8 as Foo<u64>>
- <i8 as Foo<u8>>
<u8 as Foo<bool>>
<u8 as Foo<u16>>
<u8 as Foo<u32>>
diff --git a/src/test/ui/duplicate/duplicate-type-parameter.stderr b/src/test/ui/duplicate/duplicate-type-parameter.stderr
index 6754574f0b9..628f898d5c8 100644
--- a/src/test/ui/duplicate/duplicate-type-parameter.stderr
+++ b/src/test/ui/duplicate/duplicate-type-parameter.stderr
@@ -55,10 +55,10 @@ LL | impl<T,T> Qux<T,T> for Option<T> {}
| first use of `T`
error[E0207]: the type parameter `T` is not constrained by the impl trait, self type, or predicates
- --> $DIR/duplicate-type-parameter.rs:24:6
+ --> $DIR/duplicate-type-parameter.rs:24:8
|
LL | impl<T,T> Qux<T,T> for Option<T> {}
- | ^ unconstrained type parameter
+ | ^ unconstrained type parameter
error: aborting due to 8 previous errors
diff --git a/src/test/ui/generic-associated-types/own-bound-span.rs b/src/test/ui/generic-associated-types/own-bound-span.rs
new file mode 100644
index 00000000000..3699f7296f5
--- /dev/null
+++ b/src/test/ui/generic-associated-types/own-bound-span.rs
@@ -0,0 +1,17 @@
+struct S;
+
+trait D {
+ type P<T: Copy>;
+ //~^ NOTE required by this bound in `D::P`
+ //~| NOTE required by a bound in `D::P`
+}
+
+impl D for S {
+ type P<T: Copy> = ();
+}
+
+fn main() {
+ let _: <S as D>::P<String>;
+ //~^ ERROR the trait bound `String: Copy` is not satisfied
+ //~| NOTE the trait `Copy` is not implemented for `String`
+}
diff --git a/src/test/ui/generic-associated-types/own-bound-span.stderr b/src/test/ui/generic-associated-types/own-bound-span.stderr
new file mode 100644
index 00000000000..8ab8ea623b2
--- /dev/null
+++ b/src/test/ui/generic-associated-types/own-bound-span.stderr
@@ -0,0 +1,15 @@
+error[E0277]: the trait bound `String: Copy` is not satisfied
+ --> $DIR/own-bound-span.rs:14:12
+ |
+LL | let _: <S as D>::P<String>;
+ | ^^^^^^^^^^^^^^^^^^^ the trait `Copy` is not implemented for `String`
+ |
+note: required by a bound in `D::P`
+ --> $DIR/own-bound-span.rs:4:15
+ |
+LL | type P<T: Copy>;
+ | ^^^^ required by this bound in `D::P`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/impl-trait/equality.stderr b/src/test/ui/impl-trait/equality.stderr
index 1841b8e5dcd..69f4cbbbf42 100644
--- a/src/test/ui/impl-trait/equality.stderr
+++ b/src/test/ui/impl-trait/equality.stderr
@@ -30,15 +30,10 @@ LL | n + sum_to(n - 1)
|
= help: the trait `Add<impl Foo>` is not implemented for `u32`
= help: the following other types implement trait `Add<Rhs>`:
- <&'a f32 as Add<f32>>
- <&'a f64 as Add<f64>>
- <&'a i128 as Add<i128>>
- <&'a i16 as Add<i16>>
- <&'a i32 as Add<i32>>
- <&'a i64 as Add<i64>>
- <&'a i8 as Add<i8>>
- <&'a isize as Add<isize>>
- and 48 others
+ <&'a u32 as Add<u32>>
+ <&u32 as Add<&u32>>
+ <u32 as Add<&u32>>
+ <u32 as Add>
error: aborting due to 2 previous errors; 1 warning emitted
diff --git a/src/test/ui/impl-trait/nested-return-type4.rs b/src/test/ui/impl-trait/nested-return-type4.rs
new file mode 100644
index 00000000000..cec70bb1a0d
--- /dev/null
+++ b/src/test/ui/impl-trait/nested-return-type4.rs
@@ -0,0 +1,8 @@
+// edition: 2021
+
+fn test<'s: 's>(s: &'s str) -> impl std::future::Future<Output = impl Sized> {
+ async move { let _s = s; }
+ //~^ ERROR hidden type for `impl Future<Output = impl Sized>` captures lifetime that does not appear in bounds
+}
+
+fn main() {}
diff --git a/src/test/ui/impl-trait/nested-return-type4.stderr b/src/test/ui/impl-trait/nested-return-type4.stderr
new file mode 100644
index 00000000000..e761a60e79c
--- /dev/null
+++ b/src/test/ui/impl-trait/nested-return-type4.stderr
@@ -0,0 +1,20 @@
+error[E0700]: hidden type for `impl Future<Output = impl Sized>` captures lifetime that does not appear in bounds
+ --> $DIR/nested-return-type4.rs:4:5
+ |
+LL | fn test<'s: 's>(s: &'s str) -> impl std::future::Future<Output = impl Sized> {
+ | -- hidden type `[async block@$DIR/nested-return-type4.rs:4:5: 4:31]` captures the lifetime `'s` as defined here
+LL | async move { let _s = s; }
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+help: to declare that `impl Future<Output = impl Sized>` captures `'s`, you can add an explicit `'s` lifetime bound
+ |
+LL | fn test<'s: 's>(s: &'s str) -> impl std::future::Future<Output = impl Sized> + 's {
+ | ++++
+help: to declare that `impl Sized` captures `'s`, you can add an explicit `'s` lifetime bound
+ |
+LL | fn test<'s: 's>(s: &'s str) -> impl std::future::Future<Output = impl Sized + 's> {
+ | ++++
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0700`.
diff --git a/src/test/ui/issues/issue-105330.rs b/src/test/ui/issues/issue-105330.rs
new file mode 100644
index 00000000000..86e45f10b0e
--- /dev/null
+++ b/src/test/ui/issues/issue-105330.rs
@@ -0,0 +1,21 @@
+pub trait TraitWAssocConst {
+ const A: usize;
+}
+pub struct Demo {}
+
+impl TraitWAssocConst for impl Demo { //~ ERROR E0404
+ //~^ ERROR E0562
+ pubconst A: str = 32; //~ ERROR expected one of
+}
+
+fn foo<A: TraitWAssocConst<A=32>>() { //~ ERROR E0658
+ foo::<Demo>()(); //~ ERROR E0271
+ //~^ ERROR E0618
+ //~| ERROR E0277
+}
+
+fn main<A: TraitWAssocConst<A=32>>() { //~ ERROR E0131
+ //~^ ERROR E0658
+ foo::<Demo>(); //~ ERROR E0277
+ //~^ ERROR E0271
+}
diff --git a/src/test/ui/issues/issue-105330.stderr b/src/test/ui/issues/issue-105330.stderr
new file mode 100644
index 00000000000..92f2ccb6544
--- /dev/null
+++ b/src/test/ui/issues/issue-105330.stderr
@@ -0,0 +1,109 @@
+error: expected one of `!` or `::`, found `A`
+ --> $DIR/issue-105330.rs:8:14
+ |
+LL | impl TraitWAssocConst for impl Demo {
+ | - while parsing this item list starting here
+LL |
+LL | pubconst A: str = 32;
+ | ^ expected one of `!` or `::`
+LL | }
+ | - the item list ends here
+
+error[E0404]: expected trait, found struct `Demo`
+ --> $DIR/issue-105330.rs:6:32
+ |
+LL | impl TraitWAssocConst for impl Demo {
+ | ^^^^ not a trait
+
+error[E0658]: associated const equality is incomplete
+ --> $DIR/issue-105330.rs:11:28
+ |
+LL | fn foo<A: TraitWAssocConst<A=32>>() {
+ | ^^^^
+ |
+ = note: see issue #92827 <https://github.com/rust-lang/rust/issues/92827> for more information
+ = help: add `#![feature(associated_const_equality)]` to the crate attributes to enable
+
+error[E0658]: associated const equality is incomplete
+ --> $DIR/issue-105330.rs:17:29
+ |
+LL | fn main<A: TraitWAssocConst<A=32>>() {
+ | ^^^^
+ |
+ = note: see issue #92827 <https://github.com/rust-lang/rust/issues/92827> for more information
+ = help: add `#![feature(associated_const_equality)]` to the crate attributes to enable
+
+error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in type
+ --> $DIR/issue-105330.rs:6:27
+ |
+LL | impl TraitWAssocConst for impl Demo {
+ | ^^^^^^^^^
+
+error[E0277]: the trait bound `Demo: TraitWAssocConst` is not satisfied
+ --> $DIR/issue-105330.rs:12:11
+ |
+LL | foo::<Demo>()();
+ | ^^^^ the trait `TraitWAssocConst` is not implemented for `Demo`
+ |
+note: required by a bound in `foo`
+ --> $DIR/issue-105330.rs:11:11
+ |
+LL | fn foo<A: TraitWAssocConst<A=32>>() {
+ | ^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `foo`
+
+error[E0271]: type mismatch resolving `<Demo as TraitWAssocConst>::A == 32`
+ --> $DIR/issue-105330.rs:12:11
+ |
+LL | foo::<Demo>()();
+ | ^^^^ types differ
+ |
+note: required by a bound in `foo`
+ --> $DIR/issue-105330.rs:11:28
+ |
+LL | fn foo<A: TraitWAssocConst<A=32>>() {
+ | ^^^^ required by this bound in `foo`
+
+error[E0618]: expected function, found `()`
+ --> $DIR/issue-105330.rs:12:5
+ |
+LL | fn foo<A: TraitWAssocConst<A=32>>() {
+ | ----------------------------------- `foo::<Demo>` defined here returns `()`
+LL | foo::<Demo>()();
+ | ^^^^^^^^^^^^^--
+ | |
+ | call expression requires function
+
+error[E0277]: the trait bound `Demo: TraitWAssocConst` is not satisfied
+ --> $DIR/issue-105330.rs:19:11
+ |
+LL | foo::<Demo>();
+ | ^^^^ the trait `TraitWAssocConst` is not implemented for `Demo`
+ |
+note: required by a bound in `foo`
+ --> $DIR/issue-105330.rs:11:11
+ |
+LL | fn foo<A: TraitWAssocConst<A=32>>() {
+ | ^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `foo`
+
+error[E0271]: type mismatch resolving `<Demo as TraitWAssocConst>::A == 32`
+ --> $DIR/issue-105330.rs:19:11
+ |
+LL | foo::<Demo>();
+ | ^^^^ types differ
+ |
+note: required by a bound in `foo`
+ --> $DIR/issue-105330.rs:11:28
+ |
+LL | fn foo<A: TraitWAssocConst<A=32>>() {
+ | ^^^^ required by this bound in `foo`
+
+error[E0131]: `main` function is not allowed to have generic parameters
+ --> $DIR/issue-105330.rs:17:8
+ |
+LL | fn main<A: TraitWAssocConst<A=32>>() {
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ `main` cannot have generic parameters
+
+error: aborting due to 11 previous errors
+
+Some errors have detailed explanations: E0131, E0271, E0277, E0404, E0562, E0618, E0658.
+For more information about an error, try `rustc --explain E0131`.
diff --git a/src/test/ui/issues/issue-24352.stderr b/src/test/ui/issues/issue-24352.stderr
index 118f37f6971..1f51b6e2905 100644
--- a/src/test/ui/issues/issue-24352.stderr
+++ b/src/test/ui/issues/issue-24352.stderr
@@ -6,15 +6,10 @@ LL | 1.0f64 - 1
|
= help: the trait `Sub<{integer}>` is not implemented for `f64`
= help: the following other types implement trait `Sub<Rhs>`:
- <&'a f32 as Sub<f32>>
<&'a f64 as Sub<f64>>
- <&'a i128 as Sub<i128>>
- <&'a i16 as Sub<i16>>
- <&'a i32 as Sub<i32>>
- <&'a i64 as Sub<i64>>
- <&'a i8 as Sub<i8>>
- <&'a isize as Sub<isize>>
- and 48 others
+ <&f64 as Sub<&f64>>
+ <f64 as Sub<&f64>>
+ <f64 as Sub>
help: consider using a floating-point literal by writing it with `.0`
|
LL | 1.0f64 - 1.0
diff --git a/src/test/ui/kindck/kindck-copy.stderr b/src/test/ui/kindck/kindck-copy.stderr
index 025a5008d0f..9af89159a8c 100644
--- a/src/test/ui/kindck/kindck-copy.stderr
+++ b/src/test/ui/kindck/kindck-copy.stderr
@@ -4,16 +4,7 @@ error[E0277]: the trait bound `&'static mut isize: Copy` is not satisfied
LL | assert_copy::<&'static mut isize>();
| ^^^^^^^^^^^^^^^^^^ the trait `Copy` is not implemented for `&'static mut isize`
|
- = help: the following other types implement trait `Copy`:
- f32
- f64
- i128
- i16
- i32
- i64
- i8
- isize
- and 6 others
+ = help: the trait `Copy` is implemented for `isize`
note: required by a bound in `assert_copy`
--> $DIR/kindck-copy.rs:5:18
|
@@ -26,16 +17,7 @@ error[E0277]: the trait bound `&'a mut isize: Copy` is not satisfied
LL | assert_copy::<&'a mut isize>();
| ^^^^^^^^^^^^^ the trait `Copy` is not implemented for `&'a mut isize`
|
- = help: the following other types implement trait `Copy`:
- f32
- f64
- i128
- i16
- i32
- i64
- i8
- isize
- and 6 others
+ = help: the trait `Copy` is implemented for `isize`
note: required by a bound in `assert_copy`
--> $DIR/kindck-copy.rs:5:18
|
diff --git a/src/test/ui/lexer/lex-bad-char-literals-6.stderr b/src/test/ui/lexer/lex-bad-char-literals-6.stderr
index afef0cb6034..ce41942467c 100644
--- a/src/test/ui/lexer/lex-bad-char-literals-6.stderr
+++ b/src/test/ui/lexer/lex-bad-char-literals-6.stderr
@@ -42,12 +42,11 @@ LL | if x == y {}
<&'a str as PartialEq<OsString>>
<&'a str as PartialEq<String>>
<&'b str as PartialEq<Cow<'a, str>>>
- <String as PartialEq<&'a str>>
- <String as PartialEq<Cow<'a, str>>>
- <String as PartialEq<str>>
- <String as PartialEq>
<str as PartialEq<Cow<'a, str>>>
- and 4 others
+ <str as PartialEq<OsStr>>
+ <str as PartialEq<OsString>>
+ <str as PartialEq<String>>
+ <str as PartialEq>
error[E0308]: mismatched types
--> $DIR/lex-bad-char-literals-6.rs:15:20
@@ -68,12 +67,11 @@ LL | if x == z {}
<&'a str as PartialEq<OsString>>
<&'a str as PartialEq<String>>
<&'b str as PartialEq<Cow<'a, str>>>
- <String as PartialEq<&'a str>>
- <String as PartialEq<Cow<'a, str>>>
- <String as PartialEq<str>>
- <String as PartialEq>
<str as PartialEq<Cow<'a, str>>>
- and 4 others
+ <str as PartialEq<OsStr>>
+ <str as PartialEq<OsString>>
+ <str as PartialEq<String>>
+ <str as PartialEq>
error: aborting due to 6 previous errors
diff --git a/src/test/ui/lint/issue-104897.rs b/src/test/ui/lint/issue-104897.rs
new file mode 100644
index 00000000000..5fbc658f155
--- /dev/null
+++ b/src/test/ui/lint/issue-104897.rs
@@ -0,0 +1,6 @@
+// error-pattern: this file contains an unclosed delimiter
+// error-pattern: this file contains an unclosed delimiter
+// error-pattern: this file contains an unclosed delimiter
+// error-pattern: format argument must be a string literal
+
+fn f(){(print!(á
diff --git a/src/test/ui/lint/issue-104897.stderr b/src/test/ui/lint/issue-104897.stderr
new file mode 100644
index 00000000000..817a93c2f3b
--- /dev/null
+++ b/src/test/ui/lint/issue-104897.stderr
@@ -0,0 +1,43 @@
+error: this file contains an unclosed delimiter
+ --> $DIR/issue-104897.rs:6:18
+ |
+LL | fn f(){(print!(á
+ | -- - ^
+ | || |
+ | || unclosed delimiter
+ | |unclosed delimiter
+ | unclosed delimiter
+
+error: this file contains an unclosed delimiter
+ --> $DIR/issue-104897.rs:6:18
+ |
+LL | fn f(){(print!(á
+ | -- - ^
+ | || |
+ | || unclosed delimiter
+ | |unclosed delimiter
+ | unclosed delimiter
+
+error: this file contains an unclosed delimiter
+ --> $DIR/issue-104897.rs:6:18
+ |
+LL | fn f(){(print!(á
+ | -- - ^
+ | || |
+ | || unclosed delimiter
+ | |unclosed delimiter
+ | unclosed delimiter
+
+error: format argument must be a string literal
+ --> $DIR/issue-104897.rs:6:16
+ |
+LL | fn f(){(print!(á
+ | ^
+ |
+help: you might be missing a string literal to format with
+ |
+LL | fn f(){(print!("{}", á
+ | +++++
+
+error: aborting due to 4 previous errors
+
diff --git a/src/test/ui/macros/syntax-error-recovery.stderr b/src/test/ui/macros/syntax-error-recovery.stderr
index c153b3b910b..c42ee9b295e 100644
--- a/src/test/ui/macros/syntax-error-recovery.stderr
+++ b/src/test/ui/macros/syntax-error-recovery.stderr
@@ -7,6 +7,7 @@ LL | $token $($inner)? = $value,
LL | values!(STRING(1) as (String) => cfg(test),);
| -------------------------------------------- in this macro invocation
|
+ = help: enum variants can be `Variant`, `Variant = <integer>`, `Variant(Type, ..., TypeN)` or `Variant { fields: Types }`
= note: this error originates in the macro `values` (in Nightly builds, run with -Z macro-backtrace for more info)
error: macro expansion ignores token `(String)` and any following
diff --git a/src/test/ui/maximal_mir_to_hir_coverage.rs b/src/test/ui/maximal_mir_to_hir_coverage.rs
new file mode 100644
index 00000000000..5ca54633f21
--- /dev/null
+++ b/src/test/ui/maximal_mir_to_hir_coverage.rs
@@ -0,0 +1,10 @@
+// compile-flags: -Zmaximal-hir-to-mir-coverage
+// run-pass
+
+// Just making sure this flag is accepted and doesn't crash the compiler
+
+fn main() {
+ let x = 1;
+ let y = x + 1;
+ println!("{y}");
+}
diff --git a/src/test/ui/mismatched_types/binops.stderr b/src/test/ui/mismatched_types/binops.stderr
index 3de652d87ec..3585587ed4c 100644
--- a/src/test/ui/mismatched_types/binops.stderr
+++ b/src/test/ui/mismatched_types/binops.stderr
@@ -24,15 +24,10 @@ LL | 2 as usize - Some(1);
|
= help: the trait `Sub<Option<{integer}>>` is not implemented for `usize`
= help: the following other types implement trait `Sub<Rhs>`:
- <&'a f32 as Sub<f32>>
- <&'a f64 as Sub<f64>>
- <&'a i128 as Sub<i128>>
- <&'a i16 as Sub<i16>>
- <&'a i32 as Sub<i32>>
- <&'a i64 as Sub<i64>>
- <&'a i8 as Sub<i8>>
- <&'a isize as Sub<isize>>
- and 48 others
+ <&'a usize as Sub<usize>>
+ <&usize as Sub<&usize>>
+ <usize as Sub<&usize>>
+ <usize as Sub>
error[E0277]: cannot multiply `{integer}` by `()`
--> $DIR/binops.rs:4:7
diff --git a/src/test/ui/never_type/issue-13352.stderr b/src/test/ui/never_type/issue-13352.stderr
index fed780e6895..2d22da0b420 100644
--- a/src/test/ui/never_type/issue-13352.stderr
+++ b/src/test/ui/never_type/issue-13352.stderr
@@ -6,15 +6,10 @@ LL | 2_usize + (loop {});
|
= help: the trait `Add<()>` is not implemented for `usize`
= help: the following other types implement trait `Add<Rhs>`:
- <&'a f32 as Add<f32>>
- <&'a f64 as Add<f64>>
- <&'a i128 as Add<i128>>
- <&'a i16 as Add<i16>>
- <&'a i32 as Add<i32>>
- <&'a i64 as Add<i64>>
- <&'a i8 as Add<i8>>
- <&'a isize as Add<isize>>
- and 48 others
+ <&'a usize as Add<usize>>
+ <&usize as Add<&usize>>
+ <usize as Add<&usize>>
+ <usize as Add>
error: aborting due to previous error
diff --git a/src/test/ui/numbers-arithmetic/not-suggest-float-literal.stderr b/src/test/ui/numbers-arithmetic/not-suggest-float-literal.stderr
index 6aa1ad8dd89..8f0eef237cf 100644
--- a/src/test/ui/numbers-arithmetic/not-suggest-float-literal.stderr
+++ b/src/test/ui/numbers-arithmetic/not-suggest-float-literal.stderr
@@ -6,15 +6,10 @@ LL | x + 100.0
|
= help: the trait `Add<{float}>` is not implemented for `u8`
= help: the following other types implement trait `Add<Rhs>`:
- <&'a f32 as Add<f32>>
- <&'a f64 as Add<f64>>
- <&'a i128 as Add<i128>>
- <&'a i16 as Add<i16>>
- <&'a i32 as Add<i32>>
- <&'a i64 as Add<i64>>
- <&'a i8 as Add<i8>>
- <&'a isize as Add<isize>>
- and 48 others
+ <&'a u8 as Add<u8>>
+ <&u8 as Add<&u8>>
+ <u8 as Add<&u8>>
+ <u8 as Add>
error[E0277]: cannot add `&str` to `f64`
--> $DIR/not-suggest-float-literal.rs:6:7
@@ -24,15 +19,10 @@ LL | x + "foo"
|
= help: the trait `Add<&str>` is not implemented for `f64`
= help: the following other types implement trait `Add<Rhs>`:
- <&'a f32 as Add<f32>>
<&'a f64 as Add<f64>>
- <&'a i128 as Add<i128>>
- <&'a i16 as Add<i16>>
- <&'a i32 as Add<i32>>
- <&'a i64 as Add<i64>>
- <&'a i8 as Add<i8>>
- <&'a isize as Add<isize>>
- and 48 others
+ <&f64 as Add<&f64>>
+ <f64 as Add<&f64>>
+ <f64 as Add>
error[E0277]: cannot add `{integer}` to `f64`
--> $DIR/not-suggest-float-literal.rs:11:7
@@ -42,15 +32,10 @@ LL | x + y
|
= help: the trait `Add<{integer}>` is not implemented for `f64`
= help: the following other types implement trait `Add<Rhs>`:
- <&'a f32 as Add<f32>>
<&'a f64 as Add<f64>>
- <&'a i128 as Add<i128>>
- <&'a i16 as Add<i16>>
- <&'a i32 as Add<i32>>
- <&'a i64 as Add<i64>>
- <&'a i8 as Add<i8>>
- <&'a isize as Add<isize>>
- and 48 others
+ <&f64 as Add<&f64>>
+ <f64 as Add<&f64>>
+ <f64 as Add>
error[E0277]: cannot subtract `{float}` from `u8`
--> $DIR/not-suggest-float-literal.rs:15:7
@@ -60,15 +45,10 @@ LL | x - 100.0
|
= help: the trait `Sub<{float}>` is not implemented for `u8`
= help: the following other types implement trait `Sub<Rhs>`:
- <&'a f32 as Sub<f32>>
- <&'a f64 as Sub<f64>>
- <&'a i128 as Sub<i128>>
- <&'a i16 as Sub<i16>>
- <&'a i32 as Sub<i32>>
- <&'a i64 as Sub<i64>>
- <&'a i8 as Sub<i8>>
- <&'a isize as Sub<isize>>
- and 48 others
+ <&'a u8 as Sub<u8>>
+ <&u8 as Sub<&u8>>
+ <u8 as Sub<&u8>>
+ <u8 as Sub>
error[E0277]: cannot subtract `&str` from `f64`
--> $DIR/not-suggest-float-literal.rs:19:7
@@ -78,15 +58,10 @@ LL | x - "foo"
|
= help: the trait `Sub<&str>` is not implemented for `f64`
= help: the following other types implement trait `Sub<Rhs>`:
- <&'a f32 as Sub<f32>>
<&'a f64 as Sub<f64>>
- <&'a i128 as Sub<i128>>
- <&'a i16 as Sub<i16>>
- <&'a i32 as Sub<i32>>
- <&'a i64 as Sub<i64>>
- <&'a i8 as Sub<i8>>
- <&'a isize as Sub<isize>>
- and 48 others
+ <&f64 as Sub<&f64>>
+ <f64 as Sub<&f64>>
+ <f64 as Sub>
error[E0277]: cannot subtract `{integer}` from `f64`
--> $DIR/not-suggest-float-literal.rs:24:7
@@ -96,15 +71,10 @@ LL | x - y
|
= help: the trait `Sub<{integer}>` is not implemented for `f64`
= help: the following other types implement trait `Sub<Rhs>`:
- <&'a f32 as Sub<f32>>
<&'a f64 as Sub<f64>>
- <&'a i128 as Sub<i128>>
- <&'a i16 as Sub<i16>>
- <&'a i32 as Sub<i32>>
- <&'a i64 as Sub<i64>>
- <&'a i8 as Sub<i8>>
- <&'a isize as Sub<isize>>
- and 48 others
+ <&f64 as Sub<&f64>>
+ <f64 as Sub<&f64>>
+ <f64 as Sub>
error[E0277]: cannot multiply `u8` by `{float}`
--> $DIR/not-suggest-float-literal.rs:28:7
@@ -114,15 +84,10 @@ LL | x * 100.0
|
= help: the trait `Mul<{float}>` is not implemented for `u8`
= help: the following other types implement trait `Mul<Rhs>`:
- <&'a f32 as Mul<f32>>
- <&'a f64 as Mul<f64>>
- <&'a i128 as Mul<i128>>
- <&'a i16 as Mul<i16>>
- <&'a i32 as Mul<i32>>
- <&'a i64 as Mul<i64>>
- <&'a i8 as Mul<i8>>
- <&'a isize as Mul<isize>>
- and 49 others
+ <&'a u8 as Mul<u8>>
+ <&u8 as Mul<&u8>>
+ <u8 as Mul<&u8>>
+ <u8 as Mul>
error[E0277]: cannot multiply `f64` by `&str`
--> $DIR/not-suggest-float-literal.rs:32:7
@@ -132,15 +97,10 @@ LL | x * "foo"
|
= help: the trait `Mul<&str>` is not implemented for `f64`
= help: the following other types implement trait `Mul<Rhs>`:
- <&'a f32 as Mul<f32>>
<&'a f64 as Mul<f64>>
- <&'a i128 as Mul<i128>>
- <&'a i16 as Mul<i16>>
- <&'a i32 as Mul<i32>>
- <&'a i64 as Mul<i64>>
- <&'a i8 as Mul<i8>>
- <&'a isize as Mul<isize>>
- and 49 others
+ <&f64 as Mul<&f64>>
+ <f64 as Mul<&f64>>
+ <f64 as Mul>
error[E0277]: cannot multiply `f64` by `{integer}`
--> $DIR/not-suggest-float-literal.rs:37:7
@@ -150,15 +110,10 @@ LL | x * y
|
= help: the trait `Mul<{integer}>` is not implemented for `f64`
= help: the following other types implement trait `Mul<Rhs>`:
- <&'a f32 as Mul<f32>>
<&'a f64 as Mul<f64>>
- <&'a i128 as Mul<i128>>
- <&'a i16 as Mul<i16>>
- <&'a i32 as Mul<i32>>
- <&'a i64 as Mul<i64>>
- <&'a i8 as Mul<i8>>
- <&'a isize as Mul<isize>>
- and 49 others
+ <&f64 as Mul<&f64>>
+ <f64 as Mul<&f64>>
+ <f64 as Mul>
error[E0277]: cannot divide `u8` by `{float}`
--> $DIR/not-suggest-float-literal.rs:41:7
@@ -168,15 +123,11 @@ LL | x / 100.0
|
= help: the trait `Div<{float}>` is not implemented for `u8`
= help: the following other types implement trait `Div<Rhs>`:
- <&'a f32 as Div<f32>>
- <&'a f64 as Div<f64>>
- <&'a i128 as Div<i128>>
- <&'a i16 as Div<i16>>
- <&'a i32 as Div<i32>>
- <&'a i64 as Div<i64>>
- <&'a i8 as Div<i8>>
- <&'a isize as Div<isize>>
- and 54 others
+ <&'a u8 as Div<u8>>
+ <&u8 as Div<&u8>>
+ <u8 as Div<&u8>>
+ <u8 as Div<NonZeroU8>>
+ <u8 as Div>
error[E0277]: cannot divide `f64` by `&str`
--> $DIR/not-suggest-float-literal.rs:45:7
@@ -186,15 +137,10 @@ LL | x / "foo"
|
= help: the trait `Div<&str>` is not implemented for `f64`
= help: the following other types implement trait `Div<Rhs>`:
- <&'a f32 as Div<f32>>
<&'a f64 as Div<f64>>
- <&'a i128 as Div<i128>>
- <&'a i16 as Div<i16>>
- <&'a i32 as Div<i32>>
- <&'a i64 as Div<i64>>
- <&'a i8 as Div<i8>>
- <&'a isize as Div<isize>>
- and 54 others
+ <&f64 as Div<&f64>>
+ <f64 as Div<&f64>>
+ <f64 as Div>
error[E0277]: cannot divide `f64` by `{integer}`
--> $DIR/not-suggest-float-literal.rs:50:7
@@ -204,15 +150,10 @@ LL | x / y
|
= help: the trait `Div<{integer}>` is not implemented for `f64`
= help: the following other types implement trait `Div<Rhs>`:
- <&'a f32 as Div<f32>>
<&'a f64 as Div<f64>>
- <&'a i128 as Div<i128>>
- <&'a i16 as Div<i16>>
- <&'a i32 as Div<i32>>
- <&'a i64 as Div<i64>>
- <&'a i8 as Div<i8>>
- <&'a isize as Div<isize>>
- and 54 others
+ <&f64 as Div<&f64>>
+ <f64 as Div<&f64>>
+ <f64 as Div>
error: aborting due to 12 previous errors
diff --git a/src/test/ui/numbers-arithmetic/suggest-float-literal.stderr b/src/test/ui/numbers-arithmetic/suggest-float-literal.stderr
index 988379e582a..03779d35637 100644
--- a/src/test/ui/numbers-arithmetic/suggest-float-literal.stderr
+++ b/src/test/ui/numbers-arithmetic/suggest-float-literal.stderr
@@ -7,14 +7,9 @@ LL | x + 100
= help: the trait `Add<{integer}>` is not implemented for `f32`
= help: the following other types implement trait `Add<Rhs>`:
<&'a f32 as Add<f32>>
- <&'a f64 as Add<f64>>
- <&'a i128 as Add<i128>>
- <&'a i16 as Add<i16>>
- <&'a i32 as Add<i32>>
- <&'a i64 as Add<i64>>
- <&'a i8 as Add<i8>>
- <&'a isize as Add<isize>>
- and 48 others
+ <&f32 as Add<&f32>>
+ <f32 as Add<&f32>>
+ <f32 as Add>
help: consider using a floating-point literal by writing it with `.0`
|
LL | x + 100.0
@@ -28,15 +23,10 @@ LL | x + 100
|
= help: the trait `Add<{integer}>` is not implemented for `f64`
= help: the following other types implement trait `Add<Rhs>`:
- <&'a f32 as Add<f32>>
<&'a f64 as Add<f64>>
- <&'a i128 as Add<i128>>
- <&'a i16 as Add<i16>>
- <&'a i32 as Add<i32>>
- <&'a i64 as Add<i64>>
- <&'a i8 as Add<i8>>
- <&'a isize as Add<isize>>
- and 48 others
+ <&f64 as Add<&f64>>
+ <f64 as Add<&f64>>
+ <f64 as Add>
help: consider using a floating-point literal by writing it with `.0`
|
LL | x + 100.0
@@ -51,14 +41,9 @@ LL | x - 100
= help: the trait `Sub<{integer}>` is not implemented for `f32`
= help: the following other types implement trait `Sub<Rhs>`:
<&'a f32 as Sub<f32>>
- <&'a f64 as Sub<f64>>
- <&'a i128 as Sub<i128>>
- <&'a i16 as Sub<i16>>
- <&'a i32 as Sub<i32>>
- <&'a i64 as Sub<i64>>
- <&'a i8 as Sub<i8>>
- <&'a isize as Sub<isize>>
- and 48 others
+ <&f32 as Sub<&f32>>
+ <f32 as Sub<&f32>>
+ <f32 as Sub>
help: consider using a floating-point literal by writing it with `.0`
|
LL | x - 100.0
@@ -72,15 +57,10 @@ LL | x - 100
|
= help: the trait `Sub<{integer}>` is not implemented for `f64`
= help: the following other types implement trait `Sub<Rhs>`:
- <&'a f32 as Sub<f32>>
<&'a f64 as Sub<f64>>
- <&'a i128 as Sub<i128>>
- <&'a i16 as Sub<i16>>
- <&'a i32 as Sub<i32>>
- <&'a i64 as Sub<i64>>
- <&'a i8 as Sub<i8>>
- <&'a isize as Sub<isize>>
- and 48 others
+ <&f64 as Sub<&f64>>
+ <f64 as Sub<&f64>>
+ <f64 as Sub>
help: consider using a floating-point literal by writing it with `.0`
|
LL | x - 100.0
@@ -95,14 +75,9 @@ LL | x * 100
= help: the trait `Mul<{integer}>` is not implemented for `f32`
= help: the following other types implement trait `Mul<Rhs>`:
<&'a f32 as Mul<f32>>
- <&'a f64 as Mul<f64>>
- <&'a i128 as Mul<i128>>
- <&'a i16 as Mul<i16>>
- <&'a i32 as Mul<i32>>
- <&'a i64 as Mul<i64>>
- <&'a i8 as Mul<i8>>
- <&'a isize as Mul<isize>>
- and 49 others
+ <&f32 as Mul<&f32>>
+ <f32 as Mul<&f32>>
+ <f32 as Mul>
help: consider using a floating-point literal by writing it with `.0`
|
LL | x * 100.0
@@ -116,15 +91,10 @@ LL | x * 100
|
= help: the trait `Mul<{integer}>` is not implemented for `f64`
= help: the following other types implement trait `Mul<Rhs>`:
- <&'a f32 as Mul<f32>>
<&'a f64 as Mul<f64>>
- <&'a i128 as Mul<i128>>
- <&'a i16 as Mul<i16>>
- <&'a i32 as Mul<i32>>
- <&'a i64 as Mul<i64>>
- <&'a i8 as Mul<i8>>
- <&'a isize as Mul<isize>>
- and 49 others
+ <&f64 as Mul<&f64>>
+ <f64 as Mul<&f64>>
+ <f64 as Mul>
help: consider using a floating-point literal by writing it with `.0`
|
LL | x * 100.0
@@ -139,14 +109,9 @@ LL | x / 100
= help: the trait `Div<{integer}>` is not implemented for `f32`
= help: the following other types implement trait `Div<Rhs>`:
<&'a f32 as Div<f32>>
- <&'a f64 as Div<f64>>
- <&'a i128 as Div<i128>>
- <&'a i16 as Div<i16>>
- <&'a i32 as Div<i32>>
- <&'a i64 as Div<i64>>
- <&'a i8 as Div<i8>>
- <&'a isize as Div<isize>>
- and 54 others
+ <&f32 as Div<&f32>>
+ <f32 as Div<&f32>>
+ <f32 as Div>
help: consider using a floating-point literal by writing it with `.0`
|
LL | x / 100.0
@@ -160,15 +125,10 @@ LL | x / 100
|
= help: the trait `Div<{integer}>` is not implemented for `f64`
= help: the following other types implement trait `Div<Rhs>`:
- <&'a f32 as Div<f32>>
<&'a f64 as Div<f64>>
- <&'a i128 as Div<i128>>
- <&'a i16 as Div<i16>>
- <&'a i32 as Div<i32>>
- <&'a i64 as Div<i64>>
- <&'a i8 as Div<i8>>
- <&'a isize as Div<isize>>
- and 54 others
+ <&f64 as Div<&f64>>
+ <f64 as Div<&f64>>
+ <f64 as Div>
help: consider using a floating-point literal by writing it with `.0`
|
LL | x / 100.0
diff --git a/src/test/ui/object-safety/object-safety-supertrait-mentions-GAT.stderr b/src/test/ui/object-safety/object-safety-supertrait-mentions-GAT.stderr
index c1aaad31e81..f05b0cd6538 100644
--- a/src/test/ui/object-safety/object-safety-supertrait-mentions-GAT.stderr
+++ b/src/test/ui/object-safety/object-safety-supertrait-mentions-GAT.stderr
@@ -3,10 +3,10 @@ error[E0311]: the parameter type `Self` may not live long enough
= 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/object-safety-supertrait-mentions-GAT.rs:9:39
+ --> $DIR/object-safety-supertrait-mentions-GAT.rs:6:15
|
-LL | trait SuperTrait<T>: for<'a> GatTrait<Gat<'a> = T> {
- | ^^^^^^^^^^^
+LL | Self: 'a;
+ | ^^
error: associated item referring to unboxed trait object for its own trait
--> $DIR/object-safety-supertrait-mentions-GAT.rs:10:20
diff --git a/src/test/ui/parser/expr-as-stmt.fixed b/src/test/ui/parser/expr-as-stmt.fixed
index 36709eea17c..b06f62794c4 100644
--- a/src/test/ui/parser/expr-as-stmt.fixed
+++ b/src/test/ui/parser/expr-as-stmt.fixed
@@ -64,4 +64,16 @@ fn asteroids() -> impl FnOnce() -> bool {
{ foo(); } || { true } //~ ERROR E0308
}
+// https://github.com/rust-lang/rust/issues/105179
+fn r#match() -> i32 {
+ (match () { () => 1 }) + match () { () => 1 } //~ ERROR expected expression, found `+`
+ //~^ ERROR mismatched types
+}
+
+// https://github.com/rust-lang/rust/issues/102171
+fn r#unsafe() -> i32 {
+ (unsafe { 1 }) + unsafe { 1 } //~ ERROR expected expression, found `+`
+ //~^ ERROR mismatched types
+}
+
fn main() {}
diff --git a/src/test/ui/parser/expr-as-stmt.rs b/src/test/ui/parser/expr-as-stmt.rs
index 92bb972b240..b39d2b88647 100644
--- a/src/test/ui/parser/expr-as-stmt.rs
+++ b/src/test/ui/parser/expr-as-stmt.rs
@@ -64,4 +64,16 @@ fn asteroids() -> impl FnOnce() -> bool {
{ foo() } || { true } //~ ERROR E0308
}
+// https://github.com/rust-lang/rust/issues/105179
+fn r#match() -> i32 {
+ match () { () => 1 } + match () { () => 1 } //~ ERROR expected expression, found `+`
+ //~^ ERROR mismatched types
+}
+
+// https://github.com/rust-lang/rust/issues/102171
+fn r#unsafe() -> i32 {
+ unsafe { 1 } + unsafe { 1 } //~ ERROR expected expression, found `+`
+ //~^ ERROR mismatched types
+}
+
fn main() {}
diff --git a/src/test/ui/parser/expr-as-stmt.stderr b/src/test/ui/parser/expr-as-stmt.stderr
index 6da4ac34067..18c8b0b7c50 100644
--- a/src/test/ui/parser/expr-as-stmt.stderr
+++ b/src/test/ui/parser/expr-as-stmt.stderr
@@ -55,6 +55,28 @@ help: parentheses are required to parse this as an expression
LL | ({ true }) | { true }
| + +
+error: expected expression, found `+`
+ --> $DIR/expr-as-stmt.rs:69:26
+ |
+LL | match () { () => 1 } + match () { () => 1 }
+ | ^ expected expression
+ |
+help: parentheses are required to parse this as an expression
+ |
+LL | (match () { () => 1 }) + match () { () => 1 }
+ | + +
+
+error: expected expression, found `+`
+ --> $DIR/expr-as-stmt.rs:75:18
+ |
+LL | unsafe { 1 } + unsafe { 1 }
+ | ^ expected expression
+ |
+help: parentheses are required to parse this as an expression
+ |
+LL | (unsafe { 1 }) + unsafe { 1 }
+ | + +
+
error[E0308]: mismatched types
--> $DIR/expr-as-stmt.rs:64:7
|
@@ -201,7 +223,26 @@ help: parentheses are required to parse this as an expression
LL | ({ true }) || { true }
| + +
-error: aborting due to 18 previous errors
+error[E0308]: mismatched types
+ --> $DIR/expr-as-stmt.rs:69:5
+ |
+LL | match () { () => 1 } + match () { () => 1 }
+ | ^^^^^^^^^^^^^^^^^^^^- help: consider using a semicolon here
+ | |
+ | expected `()`, found integer
+
+error[E0308]: mismatched types
+ --> $DIR/expr-as-stmt.rs:75:14
+ |
+LL | unsafe { 1 } + unsafe { 1 }
+ | ^ expected `()`, found integer
+ |
+help: you might have meant to return this value
+ |
+LL | unsafe { return 1; } + unsafe { 1 }
+ | ++++++ +
+
+error: aborting due to 22 previous errors
Some errors have detailed explanations: E0308, E0600, E0614.
For more information about an error, try `rustc --explain E0308`.
diff --git a/src/test/ui/parser/issue-101477-enum.stderr b/src/test/ui/parser/issue-101477-enum.stderr
index bffc881bdc8..1edca391e8f 100644
--- a/src/test/ui/parser/issue-101477-enum.stderr
+++ b/src/test/ui/parser/issue-101477-enum.stderr
@@ -3,6 +3,8 @@ error: unexpected `==`
|
LL | B == 2
| ^^ help: try using `=` instead
+ |
+ = help: enum variants can be `Variant`, `Variant = <integer>`, `Variant(Type, ..., TypeN)` or `Variant { fields: Types }`
error: expected item, found `==`
--> $DIR/issue-101477-enum.rs:6:7
diff --git a/src/test/ui/parser/issue-103869.rs b/src/test/ui/parser/issue-103869.rs
new file mode 100644
index 00000000000..28c442bdd63
--- /dev/null
+++ b/src/test/ui/parser/issue-103869.rs
@@ -0,0 +1,9 @@
+enum VecOrMap{
+ vec: Vec<usize>,
+ //~^ ERROR expected one of `(`, `,`, `=`, `{`, or `}`, found `:`
+ //~| HELP: enum variants can be `Variant`, `Variant = <integer>`, `Variant(Type, ..., TypeN)` or `Variant { fields: Types }`
+ //~| ERROR expected item, found `:`
+ map: HashMap<String,usize>
+}
+
+fn main() {}
diff --git a/src/test/ui/parser/issue-103869.stderr b/src/test/ui/parser/issue-103869.stderr
new file mode 100644
index 00000000000..0b8cd919a9d
--- /dev/null
+++ b/src/test/ui/parser/issue-103869.stderr
@@ -0,0 +1,16 @@
+error: expected one of `(`, `,`, `=`, `{`, or `}`, found `:`
+ --> $DIR/issue-103869.rs:2:8
+ |
+LL | vec: Vec<usize>,
+ | ^ expected one of `(`, `,`, `=`, `{`, or `}`
+ |
+ = help: enum variants can be `Variant`, `Variant = <integer>`, `Variant(Type, ..., TypeN)` or `Variant { fields: Types }`
+
+error: expected item, found `:`
+ --> $DIR/issue-103869.rs:2:8
+ |
+LL | vec: Vec<usize>,
+ | ^ expected item
+
+error: aborting due to 2 previous errors
+
diff --git a/src/test/ui/parser/macro/issue-37113.stderr b/src/test/ui/parser/macro/issue-37113.stderr
index b1f8674fbdf..da9e743a0b4 100644
--- a/src/test/ui/parser/macro/issue-37113.stderr
+++ b/src/test/ui/parser/macro/issue-37113.stderr
@@ -9,6 +9,7 @@ LL | $( $t, )*
LL | test_macro!(String,);
| -------------------- in this macro invocation
|
+ = help: enum variants can be `Variant`, `Variant = <integer>`, `Variant(Type, ..., TypeN)` or `Variant { fields: Types }`
= note: this error originates in the macro `test_macro` (in Nightly builds, run with -Z macro-backtrace for more info)
error: aborting due to previous error
diff --git a/src/test/ui/regions/closure-in-projection-issue-97405.rs b/src/test/ui/regions/closure-in-projection-issue-97405.rs
index e567d5c2723..88b1c139651 100644
--- a/src/test/ui/regions/closure-in-projection-issue-97405.rs
+++ b/src/test/ui/regions/closure-in-projection-issue-97405.rs
@@ -22,11 +22,11 @@ fn good_generic_fn<T>() {
// This should fail because `T` ends up in the upvars of the closure.
fn bad_generic_fn<T: Copy>(t: T) {
assert_static(opaque(async move { t; }).next());
- //~^ ERROR the associated type `<impl Iterator as Iterator>::Item` may not live long enough
+ //~^ ERROR the parameter type `T` may not live long enough
assert_static(opaque(move || { t; }).next());
//~^ ERROR the associated type `<impl Iterator as Iterator>::Item` may not live long enough
assert_static(opaque(opaque(async move { t; }).next()).next());
- //~^ ERROR the associated type `<impl Iterator as Iterator>::Item` may not live long enough
+ //~^ ERROR the parameter type `T` may not live long enough
}
fn main() {}
diff --git a/src/test/ui/regions/closure-in-projection-issue-97405.stderr b/src/test/ui/regions/closure-in-projection-issue-97405.stderr
index c08f1059ebf..907964aaf37 100644
--- a/src/test/ui/regions/closure-in-projection-issue-97405.stderr
+++ b/src/test/ui/regions/closure-in-projection-issue-97405.stderr
@@ -1,11 +1,13 @@
-error[E0310]: the associated type `<impl Iterator as Iterator>::Item` may not live long enough
+error[E0310]: the parameter type `T` may not live long enough
--> $DIR/closure-in-projection-issue-97405.rs:24:5
|
LL | assert_static(opaque(async move { t; }).next());
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ...so that the type `T` will meet its required lifetime bounds
|
- = help: consider adding an explicit lifetime bound `<impl Iterator as Iterator>::Item: 'static`...
- = note: ...so that the type `<impl Iterator as Iterator>::Item` will meet its required lifetime bounds
+help: consider adding an explicit lifetime bound...
+ |
+LL | fn bad_generic_fn<T: Copy + 'static>(t: T) {
+ | +++++++++
error[E0310]: the associated type `<impl Iterator as Iterator>::Item` may not live long enough
--> $DIR/closure-in-projection-issue-97405.rs:26:5
@@ -16,14 +18,16 @@ LL | assert_static(opaque(move || { t; }).next());
= help: consider adding an explicit lifetime bound `<impl Iterator as Iterator>::Item: 'static`...
= note: ...so that the type `<impl Iterator as Iterator>::Item` will meet its required lifetime bounds
-error[E0310]: the associated type `<impl Iterator as Iterator>::Item` may not live long enough
+error[E0310]: the parameter type `T` may not live long enough
--> $DIR/closure-in-projection-issue-97405.rs:28:5
|
LL | assert_static(opaque(opaque(async move { t; }).next()).next());
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ...so that the type `T` will meet its required lifetime bounds
|
- = help: consider adding an explicit lifetime bound `<impl Iterator as Iterator>::Item: 'static`...
- = note: ...so that the type `<impl Iterator as Iterator>::Item` will meet its required lifetime bounds
+help: consider adding an explicit lifetime bound...
+ |
+LL | fn bad_generic_fn<T: Copy + 'static>(t: T) {
+ | +++++++++
error: aborting due to 3 previous errors
diff --git a/src/test/ui/rfc-1445-restrict-constants-in-patterns/match-requires-both-partialeq-and-eq.rs b/src/test/ui/rfc-1445-restrict-constants-in-patterns/match-requires-both-partialeq-and-eq.rs
index 6b7d94603b5..a8deb8a7550 100644
--- a/src/test/ui/rfc-1445-restrict-constants-in-patterns/match-requires-both-partialeq-and-eq.rs
+++ b/src/test/ui/rfc-1445-restrict-constants-in-patterns/match-requires-both-partialeq-and-eq.rs
@@ -5,7 +5,7 @@ struct Foo {
impl PartialEq for Foo {
fn eq(&self, _: &Foo) -> bool {
- false // ha ha sucker!
+ false // ha ha!
}
}
diff --git a/src/test/ui/span/multiline-span-simple.stderr b/src/test/ui/span/multiline-span-simple.stderr
index c0d9a8634e4..b44df962a9b 100644
--- a/src/test/ui/span/multiline-span-simple.stderr
+++ b/src/test/ui/span/multiline-span-simple.stderr
@@ -6,15 +6,10 @@ LL | foo(1 as u32 +
|
= help: the trait `Add<()>` is not implemented for `u32`
= help: the following other types implement trait `Add<Rhs>`:
- <&'a f32 as Add<f32>>
- <&'a f64 as Add<f64>>
- <&'a i128 as Add<i128>>
- <&'a i16 as Add<i16>>
- <&'a i32 as Add<i32>>
- <&'a i64 as Add<i64>>
- <&'a i8 as Add<i8>>
- <&'a isize as Add<isize>>
- and 48 others
+ <&'a u32 as Add<u32>>
+ <&u32 as Add<&u32>>
+ <u32 as Add<&u32>>
+ <u32 as Add>
error: aborting due to previous error
diff --git a/src/test/ui/structs/struct-fn-in-definition.rs b/src/test/ui/structs/struct-fn-in-definition.rs
index 5ae1b727dc7..7f48f55fec9 100644
--- a/src/test/ui/structs/struct-fn-in-definition.rs
+++ b/src/test/ui/structs/struct-fn-in-definition.rs
@@ -28,6 +28,7 @@ enum E {
//~^ ERROR functions are not allowed in enum definitions
//~| HELP unlike in C++, Java, and C#, functions are declared in `impl` blocks
//~| HELP see https://doc.rust-lang.org/book/ch05-03-method-syntax.html for more information
+ //~| HELP enum variants can be `Variant`, `Variant = <integer>`, `Variant(Type, ..., TypeN)` or `Variant { fields: Types }`
}
fn main() {}
diff --git a/src/test/ui/structs/struct-fn-in-definition.stderr b/src/test/ui/structs/struct-fn-in-definition.stderr
index 472365c6ed7..439c86ec22b 100644
--- a/src/test/ui/structs/struct-fn-in-definition.stderr
+++ b/src/test/ui/structs/struct-fn-in-definition.stderr
@@ -33,6 +33,7 @@ LL | fn foo() {}
|
= help: unlike in C++, Java, and C#, functions are declared in `impl` blocks
= help: see https://doc.rust-lang.org/book/ch05-03-method-syntax.html for more information
+ = help: enum variants can be `Variant`, `Variant = <integer>`, `Variant(Type, ..., TypeN)` or `Variant { fields: Types }`
error: aborting due to 3 previous errors
diff --git a/src/test/ui/suggestions/assoc-const-as-fn.stderr b/src/test/ui/suggestions/assoc-const-as-fn.stderr
index fa740687858..3b6e947c59f 100644
--- a/src/test/ui/suggestions/assoc-const-as-fn.stderr
+++ b/src/test/ui/suggestions/assoc-const-as-fn.stderr
@@ -1,8 +1,10 @@
error[E0277]: the trait bound `T: GlUniformScalar` is not satisfied
- --> $DIR/assoc-const-as-fn.rs:14:5
+ --> $DIR/assoc-const-as-fn.rs:14:40
|
LL | <T as GlUniformScalar>::FACTORY(1, value);
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `GlUniformScalar` is not implemented for `T`
+ | ------------------------------- ^^^^^ the trait `GlUniformScalar` is not implemented for `T`
+ | |
+ | required by a bound introduced by this call
|
help: consider further restricting this bound
|
diff --git a/src/test/ui/suggestions/try-removing-the-field.rs b/src/test/ui/suggestions/try-removing-the-field.rs
index 9d0573ca255..1b7289b229b 100644
--- a/src/test/ui/suggestions/try-removing-the-field.rs
+++ b/src/test/ui/suggestions/try-removing-the-field.rs
@@ -14,4 +14,19 @@ fn use_foo(x: Foo) -> i32 {
return foo;
}
+// issue #105028, suggest removing the field only for shorthand
+fn use_match(x: Foo) {
+ match x {
+ Foo { foo: unused, .. } => { //~ WARNING unused variable
+ //~| help: if this is intentional, prefix it with an underscore
+ }
+ }
+
+ match x {
+ Foo { foo, .. } => { //~ WARNING unused variable
+ //~| help: try removing the field
+ }
+ }
+}
+
fn main() {}
diff --git a/src/test/ui/suggestions/try-removing-the-field.stderr b/src/test/ui/suggestions/try-removing-the-field.stderr
index 448a2c3d2ec..7a6013d4a6e 100644
--- a/src/test/ui/suggestions/try-removing-the-field.stderr
+++ b/src/test/ui/suggestions/try-removing-the-field.stderr
@@ -8,5 +8,19 @@ LL | let Foo { foo, bar, .. } = x;
|
= note: `#[warn(unused_variables)]` on by default
-warning: 1 warning emitted
+warning: unused variable: `unused`
+ --> $DIR/try-removing-the-field.rs:20:20
+ |
+LL | Foo { foo: unused, .. } => {
+ | ^^^^^^ help: if this is intentional, prefix it with an underscore: `_unused`
+
+warning: unused variable: `foo`
+ --> $DIR/try-removing-the-field.rs:26:15
+ |
+LL | Foo { foo, .. } => {
+ | ^^^-
+ | |
+ | help: try removing the field
+
+warning: 3 warnings emitted
diff --git a/src/test/ui/trait-bounds/impl-missing-where-clause-lifetimes-from-trait.rs b/src/test/ui/trait-bounds/impl-missing-where-clause-lifetimes-from-trait.rs
new file mode 100644
index 00000000000..dcdbd022873
--- /dev/null
+++ b/src/test/ui/trait-bounds/impl-missing-where-clause-lifetimes-from-trait.rs
@@ -0,0 +1,38 @@
+trait Trait<T> {
+ fn foo<'a, K>(self, _: T, _: K) where T: 'a, K: 'a;
+}
+
+impl Trait<()> for () {
+ fn foo<'a, K>(self, _: (), _: K) where { //~ ERROR E0195
+ todo!();
+ }
+}
+
+struct State;
+
+trait Foo<T> {
+ fn foo<'a>(&self, state: &'a State) -> &'a T
+ where
+ T: 'a;
+}
+
+impl<F, T> Foo<T> for F
+where
+ F: Fn(&State) -> &T,
+{
+ fn foo<'a>(&self, state: &'a State) -> &'a T { //~ ERROR E0195
+ self(state)
+ }
+}
+
+trait Bar {
+ fn foo<'a>(&'a self) {}
+}
+
+impl Bar for () {
+ fn foo<'a: 'a>(&'a self) {} //~ ERROR E0195
+}
+
+fn main() {
+ ().foo((), ());
+}
diff --git a/src/test/ui/trait-bounds/impl-missing-where-clause-lifetimes-from-trait.stderr b/src/test/ui/trait-bounds/impl-missing-where-clause-lifetimes-from-trait.stderr
new file mode 100644
index 00000000000..e26cb22163f
--- /dev/null
+++ b/src/test/ui/trait-bounds/impl-missing-where-clause-lifetimes-from-trait.stderr
@@ -0,0 +1,36 @@
+error[E0195]: lifetime parameters or bounds on method `foo` do not match the trait declaration
+ --> $DIR/impl-missing-where-clause-lifetimes-from-trait.rs:6:11
+ |
+LL | fn foo<'a, K>(self, _: T, _: K) where T: 'a, K: 'a;
+ | ------- -- -- this bound might be missing in the impl
+ | | |
+ | | this bound might be missing in the impl
+ | lifetimes in impl do not match this method in trait
+...
+LL | fn foo<'a, K>(self, _: (), _: K) where {
+ | ^^^^^^^ lifetimes do not match method in trait
+
+error[E0195]: lifetime parameters or bounds on method `foo` do not match the trait declaration
+ --> $DIR/impl-missing-where-clause-lifetimes-from-trait.rs:23:11
+ |
+LL | fn foo<'a>(&self, state: &'a State) -> &'a T
+ | ---- lifetimes in impl do not match this method in trait
+LL | where
+LL | T: 'a;
+ | -- this bound might be missing in the impl
+...
+LL | fn foo<'a>(&self, state: &'a State) -> &'a T {
+ | ^^^^ lifetimes do not match method in trait
+
+error[E0195]: lifetime parameters or bounds on method `foo` do not match the trait declaration
+ --> $DIR/impl-missing-where-clause-lifetimes-from-trait.rs:33:11
+ |
+LL | fn foo<'a>(&'a self) {}
+ | ---- lifetimes in impl do not match this method in trait
+...
+LL | fn foo<'a: 'a>(&'a self) {}
+ | ^^^^^^^^ lifetimes do not match method in trait
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0195`.
diff --git a/src/test/ui/traits/issue-79458.stderr b/src/test/ui/traits/issue-79458.stderr
index cf2e4edf9f0..08f7bbbf0ea 100644
--- a/src/test/ui/traits/issue-79458.stderr
+++ b/src/test/ui/traits/issue-79458.stderr
@@ -7,10 +7,7 @@ LL | struct Foo<'a, T> {
LL | bar: &'a mut T
| ^^^^^^^^^^^^^^ the trait `Clone` is not implemented for `&mut T`
|
- = help: the following other types implement trait `Clone`:
- &T
- *const T
- *mut T
+ = help: the trait `Clone` is implemented for `&T`
= note: `Clone` is implemented for `&T`, but not for `&mut T`
= note: this error originates in the derive macro `Clone` (in Nightly builds, run with -Z macro-backtrace for more info)
diff --git a/src/test/ui/try-trait/bad-interconversion.stderr b/src/test/ui/try-trait/bad-interconversion.stderr
index 419a86bf33b..a49630adb95 100644
--- a/src/test/ui/try-trait/bad-interconversion.stderr
+++ b/src/test/ui/try-trait/bad-interconversion.stderr
@@ -8,15 +8,8 @@ LL | Ok(Err(123_i32)?)
|
= note: the question mark operation (`?`) implicitly performs a conversion on the error value using the `From` trait
= help: the following other types implement trait `From<T>`:
- <f32 as From<i16>>
- <f32 as From<i8>>
- <f32 as From<u16>>
- <f32 as From<u8>>
- <f64 as From<f32>>
- <f64 as From<i16>>
- <f64 as From<i32>>
- <f64 as From<i8>>
- and 68 others
+ <u8 as From<NonZeroU8>>
+ <u8 as From<bool>>
= note: required for `Result<u64, u8>` to implement `FromResidual<Result<Infallible, i32>>`
error[E0277]: the `?` operator can only be used on `Result`s, not `Option`s, in a function that returns `Result`
diff --git a/src/test/ui/type-alias-impl-trait/self-referential-2.stderr b/src/test/ui/type-alias-impl-trait/self-referential-2.stderr
index 2b505d30730..c2cf70687fd 100644
--- a/src/test/ui/type-alias-impl-trait/self-referential-2.stderr
+++ b/src/test/ui/type-alias-impl-trait/self-referential-2.stderr
@@ -7,16 +7,7 @@ LL | 42_i32
| ------ return type was inferred to be `i32` here
|
= help: the trait `PartialEq<Foo>` is not implemented for `i32`
- = help: the following other types implement trait `PartialEq<Rhs>`:
- f32
- f64
- i128
- i16
- i32
- i64
- i8
- isize
- and 6 others
+ = help: the trait `PartialEq` is implemented for `i32`
error: aborting due to previous error
diff --git a/src/test/ui/type-alias-impl-trait/self-referential-4.stderr b/src/test/ui/type-alias-impl-trait/self-referential-4.stderr
index 27880f792f4..98c762e3d38 100644
--- a/src/test/ui/type-alias-impl-trait/self-referential-4.stderr
+++ b/src/test/ui/type-alias-impl-trait/self-referential-4.stderr
@@ -7,16 +7,7 @@ LL | i
| - return type was inferred to be `&i32` here
|
= help: the trait `PartialEq<Bar<'b, 'static>>` is not implemented for `&i32`
- = help: the following other types implement trait `PartialEq<Rhs>`:
- f32
- f64
- i128
- i16
- i32
- i64
- i8
- isize
- and 6 others
+ = help: the trait `PartialEq` is implemented for `i32`
error[E0277]: can't compare `&i32` with `Foo<'static, 'b>`
--> $DIR/self-referential-4.rs:11:31
@@ -27,16 +18,7 @@ LL | i
| - return type was inferred to be `&i32` here
|
= help: the trait `PartialEq<Foo<'static, 'b>>` is not implemented for `&i32`
- = help: the following other types implement trait `PartialEq<Rhs>`:
- f32
- f64
- i128
- i16
- i32
- i64
- i8
- isize
- and 6 others
+ = help: the trait `PartialEq` is implemented for `i32`
error[E0277]: can't compare `&i32` with `Moo<'static, 'a>`
--> $DIR/self-referential-4.rs:17:31
@@ -47,16 +29,7 @@ LL | i
| - return type was inferred to be `&i32` here
|
= help: the trait `PartialEq<Moo<'static, 'a>>` is not implemented for `&i32`
- = help: the following other types implement trait `PartialEq<Rhs>`:
- f32
- f64
- i128
- i16
- i32
- i64
- i8
- isize
- and 6 others
+ = help: the trait `PartialEq` is implemented for `i32`
error: aborting due to 3 previous errors
diff --git a/src/test/ui/type-alias-impl-trait/self-referential.stderr b/src/test/ui/type-alias-impl-trait/self-referential.stderr
index 97d510f6830..aff489d70e3 100644
--- a/src/test/ui/type-alias-impl-trait/self-referential.stderr
+++ b/src/test/ui/type-alias-impl-trait/self-referential.stderr
@@ -8,16 +8,7 @@ LL | i
| - return type was inferred to be `&i32` here
|
= help: the trait `PartialEq<Bar<'b, 'a>>` is not implemented for `&i32`
- = help: the following other types implement trait `PartialEq<Rhs>`:
- f32
- f64
- i128
- i16
- i32
- i64
- i8
- isize
- and 6 others
+ = help: the trait `PartialEq` is implemented for `i32`
error[E0277]: can't compare `&i32` with `(i32, &i32)`
--> $DIR/self-referential.rs:12:31
@@ -29,16 +20,7 @@ LL | (42, i)
| ------- return type was inferred to be `(i32, &i32)` here
|
= help: the trait `PartialEq<(i32, &i32)>` is not implemented for `&i32`
- = help: the following other types implement trait `PartialEq<Rhs>`:
- f32
- f64
- i128
- i16
- i32
- i64
- i8
- isize
- and 6 others
+ = help: the trait `PartialEq` is implemented for `i32`
error[E0277]: can't compare `&i32` with `(i32, Moo<'b, 'a>::{opaque#0})`
--> $DIR/self-referential.rs:19:31
@@ -50,16 +32,7 @@ LL | (42, i)
| ------- return type was inferred to be `(i32, &i32)` here
|
= help: the trait `PartialEq<(i32, Moo<'b, 'a>::{opaque#0})>` is not implemented for `&i32`
- = help: the following other types implement trait `PartialEq<Rhs>`:
- f32
- f64
- i128
- i16
- i32
- i64
- i8
- isize
- and 6 others
+ = help: the trait `PartialEq` is implemented for `i32`
error: aborting due to 3 previous errors
diff --git a/src/test/ui/type/type-check-defaults.stderr b/src/test/ui/type/type-check-defaults.stderr
index cf77c057d46..9ba63ffe9c9 100644
--- a/src/test/ui/type/type-check-defaults.stderr
+++ b/src/test/ui/type/type-check-defaults.stderr
@@ -66,15 +66,10 @@ LL | trait ProjectionPred<T:Iterator = IntoIter<i32>> where T::Item : Add<u8> {}
|
= help: the trait `Add<u8>` is not implemented for `i32`
= help: the following other types implement trait `Add<Rhs>`:
- <&'a f32 as Add<f32>>
- <&'a f64 as Add<f64>>
- <&'a i128 as Add<i128>>
- <&'a i16 as Add<i16>>
<&'a i32 as Add<i32>>
- <&'a i64 as Add<i64>>
- <&'a i8 as Add<i8>>
- <&'a isize as Add<isize>>
- and 48 others
+ <&i32 as Add<&i32>>
+ <i32 as Add<&i32>>
+ <i32 as Add>
error: aborting due to 7 previous errors
diff --git a/src/test/ui/typeck/issue-81293.stderr b/src/test/ui/typeck/issue-81293.stderr
index 9658288ac8b..6976be71135 100644
--- a/src/test/ui/typeck/issue-81293.stderr
+++ b/src/test/ui/typeck/issue-81293.stderr
@@ -21,15 +21,10 @@ LL | a = c + b * 5;
|
= help: the trait `Add<u16>` is not implemented for `usize`
= help: the following other types implement trait `Add<Rhs>`:
- <&'a f32 as Add<f32>>
- <&'a f64 as Add<f64>>
- <&'a i128 as Add<i128>>
- <&'a i16 as Add<i16>>
- <&'a i32 as Add<i32>>
- <&'a i64 as Add<i64>>
- <&'a i8 as Add<i8>>
- <&'a isize as Add<isize>>
- and 48 others
+ <&'a usize as Add<usize>>
+ <&usize as Add<&usize>>
+ <usize as Add<&usize>>
+ <usize as Add>
error: aborting due to 3 previous errors
diff --git a/src/test/ui/typeck/path-to-method-sugg-unresolved-expr.rs b/src/test/ui/typeck/path-to-method-sugg-unresolved-expr.rs
new file mode 100644
index 00000000000..fb56b394493
--- /dev/null
+++ b/src/test/ui/typeck/path-to-method-sugg-unresolved-expr.rs
@@ -0,0 +1,4 @@
+fn main() {
+ let page_size = page_size::get();
+ //~^ ERROR failed to resolve: use of undeclared crate or module `page_size`
+}
diff --git a/src/test/ui/typeck/path-to-method-sugg-unresolved-expr.stderr b/src/test/ui/typeck/path-to-method-sugg-unresolved-expr.stderr
new file mode 100644
index 00000000000..b01e30be54d
--- /dev/null
+++ b/src/test/ui/typeck/path-to-method-sugg-unresolved-expr.stderr
@@ -0,0 +1,9 @@
+error[E0433]: failed to resolve: use of undeclared crate or module `page_size`
+ --> $DIR/path-to-method-sugg-unresolved-expr.rs:2:21
+ |
+LL | let page_size = page_size::get();
+ | ^^^^^^^^^ use of undeclared crate or module `page_size`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0433`.
diff --git a/src/test/ui/ufcs/ufcs-qpath-self-mismatch.stderr b/src/test/ui/ufcs/ufcs-qpath-self-mismatch.stderr
index eaab6ff3d9a..ed56e1cf957 100644
--- a/src/test/ui/ufcs/ufcs-qpath-self-mismatch.stderr
+++ b/src/test/ui/ufcs/ufcs-qpath-self-mismatch.stderr
@@ -8,15 +8,10 @@ LL | <i32 as Add<u32>>::add(1, 2);
|
= help: the trait `Add<u32>` is not implemented for `i32`
= help: the following other types implement trait `Add<Rhs>`:
- <&'a f32 as Add<f32>>
- <&'a f64 as Add<f64>>
- <&'a i128 as Add<i128>>
- <&'a i16 as Add<i16>>
<&'a i32 as Add<i32>>
- <&'a i64 as Add<i64>>
- <&'a i8 as Add<i8>>
- <&'a isize as Add<isize>>
- and 48 others
+ <&i32 as Add<&i32>>
+ <i32 as Add<&i32>>
+ <i32 as Add>
error[E0308]: mismatched types
--> $DIR/ufcs-qpath-self-mismatch.rs:7:28
@@ -62,15 +57,10 @@ LL | <i32 as Add<u32>>::add(1, 2);
|
= help: the trait `Add<u32>` is not implemented for `i32`
= help: the following other types implement trait `Add<Rhs>`:
- <&'a f32 as Add<f32>>
- <&'a f64 as Add<f64>>
- <&'a i128 as Add<i128>>
- <&'a i16 as Add<i16>>
<&'a i32 as Add<i32>>
- <&'a i64 as Add<i64>>
- <&'a i8 as Add<i8>>
- <&'a isize as Add<isize>>
- and 48 others
+ <&i32 as Add<&i32>>
+ <i32 as Add<&i32>>
+ <i32 as Add>
error: aborting due to 4 previous errors
diff --git a/src/tools/collect-license-metadata/Cargo.toml b/src/tools/collect-license-metadata/Cargo.toml
new file mode 100644
index 00000000000..d0820cfc2a0
--- /dev/null
+++ b/src/tools/collect-license-metadata/Cargo.toml
@@ -0,0 +1,10 @@
+[package]
+name = "collect-license-metadata"
+version = "0.1.0"
+edition = "2021"
+
+[dependencies]
+anyhow = "1.0.65"
+serde = { version = "1.0.147", features = ["derive"] }
+serde_json = "1.0.85"
+spdx-rs = "0.5.1"
diff --git a/src/tools/collect-license-metadata/src/licenses.rs b/src/tools/collect-license-metadata/src/licenses.rs
new file mode 100644
index 00000000000..1c95b1bc8e9
--- /dev/null
+++ b/src/tools/collect-license-metadata/src/licenses.rs
@@ -0,0 +1,65 @@
+use std::collections::HashMap;
+
+const COPYRIGHT_PREFIXES: &[&str] = &["SPDX-FileCopyrightText:", "Copyright", "(c)", "(C)", "©"];
+
+pub(crate) struct LicensesInterner {
+ by_id: Vec<License>,
+ by_struct: HashMap<License, usize>,
+}
+
+impl LicensesInterner {
+ pub(crate) fn new() -> Self {
+ LicensesInterner { by_id: Vec::new(), by_struct: HashMap::new() }
+ }
+
+ pub(crate) fn intern(&mut self, mut license: License) -> LicenseId {
+ license.simplify();
+ if let Some(id) = self.by_struct.get(&license) {
+ LicenseId(*id)
+ } else {
+ let id = self.by_id.len();
+ self.by_id.push(license.clone());
+ self.by_struct.insert(license, id);
+ LicenseId(id)
+ }
+ }
+
+ pub(crate) fn resolve(&self, id: LicenseId) -> &License {
+ &self.by_id[id.0]
+ }
+}
+
+#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, serde::Serialize)]
+#[serde(transparent)]
+pub(crate) struct LicenseId(usize);
+
+#[derive(Clone, Hash, PartialEq, Eq, serde::Serialize)]
+pub(crate) struct License {
+ pub(crate) spdx: String,
+ pub(crate) copyright: Vec<String>,
+}
+
+impl License {
+ fn simplify(&mut self) {
+ self.remove_copyright_prefixes();
+ self.copyright.sort();
+ self.copyright.dedup();
+ }
+
+ fn remove_copyright_prefixes(&mut self) {
+ for copyright in &mut self.copyright {
+ let mut stripped = copyright.trim();
+ let mut previous_stripped;
+ loop {
+ previous_stripped = stripped;
+ for pattern in COPYRIGHT_PREFIXES {
+ stripped = stripped.trim_start_matches(pattern).trim_start();
+ }
+ if stripped == previous_stripped {
+ break;
+ }
+ }
+ *copyright = stripped.into();
+ }
+ }
+}
diff --git a/src/tools/collect-license-metadata/src/main.rs b/src/tools/collect-license-metadata/src/main.rs
new file mode 100644
index 00000000000..ca2a6f4b8c8
--- /dev/null
+++ b/src/tools/collect-license-metadata/src/main.rs
@@ -0,0 +1,30 @@
+mod licenses;
+mod path_tree;
+mod reuse;
+
+use crate::licenses::LicensesInterner;
+use anyhow::Error;
+use std::path::PathBuf;
+
+fn main() -> Result<(), Error> {
+ let reuse_exe: PathBuf = std::env::var_os("REUSE_EXE").expect("Missing REUSE_EXE").into();
+ let dest: PathBuf = std::env::var_os("DEST").expect("Missing DEST").into();
+
+ let mut interner = LicensesInterner::new();
+ let paths = crate::reuse::collect(&reuse_exe, &mut interner)?;
+
+ let mut tree = crate::path_tree::build(paths);
+ tree.simplify();
+
+ if let Some(parent) = dest.parent() {
+ std::fs::create_dir_all(parent)?;
+ }
+ std::fs::write(
+ &dest,
+ &serde_json::to_vec_pretty(&serde_json::json!({
+ "files": crate::path_tree::expand_interned_licenses(tree, &interner),
+ }))?,
+ )?;
+
+ Ok(())
+}
diff --git a/src/tools/collect-license-metadata/src/path_tree.rs b/src/tools/collect-license-metadata/src/path_tree.rs
new file mode 100644
index 00000000000..133ff683737
--- /dev/null
+++ b/src/tools/collect-license-metadata/src/path_tree.rs
@@ -0,0 +1,294 @@
+//! Tools like REUSE output per-file licensing information, but we need to condense it in the
+//! minimum amount of data that still represents the same licensing metadata. This module is
+//! responsible for that, by turning the list of paths into a tree and executing simplification
+//! passes over the tree to remove redundant information.
+
+use crate::licenses::{License, LicenseId, LicensesInterner};
+use std::collections::BTreeMap;
+use std::path::{Path, PathBuf};
+
+#[derive(serde::Serialize)]
+#[serde(rename_all = "kebab-case", tag = "type")]
+pub(crate) enum Node<L> {
+ Root { childs: Vec<Node<L>> },
+ Directory { name: PathBuf, childs: Vec<Node<L>>, license: Option<L> },
+ File { name: PathBuf, license: L },
+ FileGroup { names: Vec<PathBuf>, license: L },
+ Empty,
+}
+
+impl Node<LicenseId> {
+ pub(crate) fn simplify(&mut self) {
+ self.merge_directories();
+ self.collapse_in_licensed_directories();
+ self.merge_directory_licenses();
+ self.merge_file_groups();
+ self.remove_empty();
+ }
+
+ /// Initially, the build() function constructs a list of separate paths from the file
+ /// system root down to each file, like so:
+ ///
+ /// ```text
+ /// ┌─► ./ ──► compiler/ ──► rustc/ ──► src/ ──► main.rs
+ /// │
+ /// <root> ─┼─► ./ ──► compiler/ ──► rustc/ ──► Cargo.toml
+ /// │
+ /// └─► ./ ──► library/ ───► std/ ──► Cargo.toml
+ /// ```
+ ///
+ /// This pass is responsible for turning that into a proper directory tree:
+ ///
+ /// ```text
+ /// ┌─► compiler/ ──► rustc/ ──┬─► src/ ──► main.rs
+ /// │ │
+ /// <root> ──► ./ ──┤ └─► Cargo.toml
+ /// │
+ /// └─► library/ ───► std/ ──► Cargo.toml
+ /// ```
+ fn merge_directories(&mut self) {
+ match self {
+ Node::Root { childs } | Node::Directory { childs, license: None, .. } => {
+ let mut directories = BTreeMap::new();
+ let mut files = Vec::new();
+
+ for child in childs.drain(..) {
+ match child {
+ Node::Directory { name, mut childs, license: None } => {
+ directories.entry(name).or_insert_with(Vec::new).append(&mut childs);
+ }
+ file @ Node::File { .. } => {
+ files.push(file);
+ }
+ Node::Empty => {}
+ Node::Root { .. } => {
+ panic!("can't have a root inside another element");
+ }
+ Node::FileGroup { .. } => {
+ panic!("FileGroup should not be present at this stage");
+ }
+ Node::Directory { license: Some(_), .. } => {
+ panic!("license should not be set at this stage");
+ }
+ }
+ }
+
+ childs.extend(directories.into_iter().map(|(name, childs)| Node::Directory {
+ name,
+ childs,
+ license: None,
+ }));
+ childs.append(&mut files);
+
+ for child in &mut *childs {
+ child.merge_directories();
+ }
+ }
+ Node::Empty => {}
+ Node::File { .. } => {}
+ Node::FileGroup { .. } => {
+ panic!("FileGroup should not be present at this stage");
+ }
+ Node::Directory { license: Some(_), .. } => {
+ panic!("license should not be set at this stage");
+ }
+ }
+ }
+
+ /// In our codebase, most files in a directory have the same license as the other files in that
+ /// same directory, so it's redundant to store licensing metadata for all the files. Instead,
+ /// we can add a license for a whole directory, and only record the exceptions to a directory
+ /// licensing metadata.
+ ///
+ /// We cannot instead record only the difference to Rust's standard licensing, as the majority
+ /// of the files in our repository are *not* licensed under Rust's standard licensing due to
+ /// our inclusion of LLVM.
+ fn collapse_in_licensed_directories(&mut self) {
+ match self {
+ Node::Directory { childs, license, .. } => {
+ for child in &mut *childs {
+ child.collapse_in_licensed_directories();
+ }
+
+ let mut licenses_count = BTreeMap::new();
+ for child in &*childs {
+ let Some(license) = child.license() else { continue };
+ *licenses_count.entry(license).or_insert(0) += 1;
+ }
+
+ let most_popular_license = licenses_count
+ .into_iter()
+ .max_by_key(|(_, count)| *count)
+ .map(|(license, _)| license);
+
+ if let Some(most_popular_license) = most_popular_license {
+ childs.retain(|child| child.license() != Some(most_popular_license));
+ *license = Some(most_popular_license);
+ }
+ }
+ Node::Root { childs } => {
+ for child in &mut *childs {
+ child.collapse_in_licensed_directories();
+ }
+ }
+ Node::File { .. } => {}
+ Node::FileGroup { .. } => {}
+ Node::Empty => {}
+ }
+ }
+
+ /// Reduce the depth of the tree by merging subdirectories with the same license as their
+ /// parent directory into their parent, and adjusting the paths of the childs accordingly.
+ fn merge_directory_licenses(&mut self) {
+ match self {
+ Node::Root { childs } => {
+ for child in &mut *childs {
+ child.merge_directory_licenses();
+ }
+ }
+ Node::Directory { childs, license, .. } => {
+ let mut to_add = Vec::new();
+ for child in &mut *childs {
+ child.merge_directory_licenses();
+
+ let Node::Directory {
+ name: child_name,
+ childs: child_childs,
+ license: child_license,
+ } = child else { continue };
+
+ if child_license != license {
+ continue;
+ }
+ for mut child_child in child_childs.drain(..) {
+ match &mut child_child {
+ Node::Root { .. } => {
+ panic!("can't have a root inside another element");
+ }
+ Node::FileGroup { .. } => {
+ panic!("FileGroup should not be present at this stage");
+ }
+ Node::Directory { name: child_child_name, .. } => {
+ *child_child_name = child_name.join(&child_child_name);
+ }
+ Node::File { name: child_child_name, .. } => {
+ *child_child_name = child_name.join(&child_child_name);
+ }
+ Node::Empty => {}
+ }
+ to_add.push(child_child);
+ }
+
+ *child = Node::Empty;
+ }
+ childs.append(&mut to_add);
+ }
+ Node::Empty => {}
+ Node::File { .. } => {}
+ Node::FileGroup { .. } => {}
+ }
+ }
+
+ /// This pass groups multiple files in a directory with the same license into a single
+ /// "FileGroup", so that the license of all those files can be reported as a group.
+ ///
+ /// Crucially this pass runs after collapse_in_licensed_directories, so the most common license
+ /// will already be marked as the directory's license and won't be turned into a group.
+ fn merge_file_groups(&mut self) {
+ match self {
+ Node::Root { childs } | Node::Directory { childs, .. } => {
+ let mut grouped = BTreeMap::new();
+
+ for child in &mut *childs {
+ child.merge_file_groups();
+ if let Node::File { name, license } = child {
+ grouped.entry(*license).or_insert_with(Vec::new).push(name.clone());
+ *child = Node::Empty;
+ }
+ }
+
+ for (license, mut names) in grouped.into_iter() {
+ if names.len() == 1 {
+ childs.push(Node::File { license, name: names.pop().unwrap() });
+ } else {
+ childs.push(Node::FileGroup { license, names });
+ }
+ }
+ }
+ Node::File { .. } => {}
+ Node::FileGroup { .. } => panic!("FileGroup should not be present at this stage"),
+ Node::Empty => {}
+ }
+ }
+
+ /// Some nodes were replaced with Node::Empty to mark them for deletion. As the last step, make
+ /// sure to remove them from the tree.
+ fn remove_empty(&mut self) {
+ match self {
+ Node::Root { childs } | Node::Directory { childs, .. } => {
+ for child in &mut *childs {
+ child.remove_empty();
+ }
+ childs.retain(|child| !matches!(child, Node::Empty));
+ }
+ Node::FileGroup { .. } => {}
+ Node::File { .. } => {}
+ Node::Empty => {}
+ }
+ }
+
+ fn license(&self) -> Option<LicenseId> {
+ match self {
+ Node::Directory { childs, license: Some(license), .. } if childs.is_empty() => {
+ Some(*license)
+ }
+ Node::File { license, .. } => Some(*license),
+ _ => None,
+ }
+ }
+}
+
+pub(crate) fn build(mut input: Vec<(PathBuf, LicenseId)>) -> Node<LicenseId> {
+ let mut childs = Vec::new();
+
+ // Ensure reproducibility of all future steps.
+ input.sort();
+
+ for (path, license) in input {
+ let mut node = Node::File { name: path.file_name().unwrap().into(), license };
+ for component in path.parent().unwrap_or_else(|| Path::new(".")).components().rev() {
+ node = Node::Directory {
+ name: component.as_os_str().into(),
+ childs: vec![node],
+ license: None,
+ };
+ }
+
+ childs.push(node);
+ }
+
+ Node::Root { childs }
+}
+
+/// Convert a `Node<LicenseId>` into a `Node<&License>`, expanding all interned license IDs with a
+/// reference to the actual license metadata.
+pub(crate) fn expand_interned_licenses(
+ node: Node<LicenseId>,
+ interner: &LicensesInterner,
+) -> Node<&License> {
+ match node {
+ Node::Root { childs } => Node::Root {
+ childs: childs.into_iter().map(|child| strip_interning(child, interner)).collect(),
+ },
+ Node::Directory { name, childs, license } => Node::Directory {
+ childs: childs.into_iter().map(|child| strip_interning(child, interner)).collect(),
+ license: license.map(|license| interner.resolve(license)),
+ name,
+ },
+ Node::File { name, license } => Node::File { name, license: interner.resolve(license) },
+ Node::FileGroup { names, license } => {
+ Node::FileGroup { names, license: interner.resolve(license) }
+ }
+ Node::Empty => Node::Empty,
+ }
+}
diff --git a/src/tools/collect-license-metadata/src/reuse.rs b/src/tools/collect-license-metadata/src/reuse.rs
new file mode 100644
index 00000000000..d6b3772ba51
--- /dev/null
+++ b/src/tools/collect-license-metadata/src/reuse.rs
@@ -0,0 +1,49 @@
+use crate::licenses::{License, LicenseId, LicensesInterner};
+use anyhow::Error;
+use std::path::{Path, PathBuf};
+use std::process::{Command, Stdio};
+use std::time::Instant;
+
+pub(crate) fn collect(
+ reuse_exe: &Path,
+ interner: &mut LicensesInterner,
+) -> Result<Vec<(PathBuf, LicenseId)>, Error> {
+ eprintln!("gathering license information from REUSE");
+ let start = Instant::now();
+ let raw = &obtain_spdx_document(reuse_exe)?;
+ eprintln!("finished gathering the license information from REUSE in {:.2?}", start.elapsed());
+
+ let document = spdx_rs::parsers::spdx_from_tag_value(&raw)?;
+
+ let mut result = Vec::new();
+ for file in document.file_information {
+ let license = interner.intern(License {
+ spdx: file.concluded_license.to_string(),
+ copyright: file.copyright_text.split('\n').map(|s| s.into()).collect(),
+ });
+
+ result.push((file.file_name.into(), license));
+ }
+
+ Ok(result)
+}
+
+fn obtain_spdx_document(reuse_exe: &Path) -> Result<String, Error> {
+ let output = Command::new(reuse_exe)
+ .args(&["spdx", "--add-license-concluded", "--creator-person=bors"])
+ .stdout(Stdio::piped())
+ .spawn()?
+ .wait_with_output()?;
+
+ if !output.status.success() {
+ eprintln!();
+ eprintln!("Note that Rust requires some REUSE features that might not be present in the");
+ eprintln!("release you're using. Make sure your REUSE release includes these PRs:");
+ eprintln!();
+ eprintln!(" - https://github.com/fsfe/reuse-tool/pull/623");
+ eprintln!();
+ anyhow::bail!("collecting licensing information with REUSE failed");
+ }
+
+ Ok(String::from_utf8(output.stdout)?)
+}
diff --git a/src/tools/compiletest/src/header.rs b/src/tools/compiletest/src/header.rs
index 0d9a629e179..64d97e91442 100644
--- a/src/tools/compiletest/src/header.rs
+++ b/src/tools/compiletest/src/header.rs
@@ -260,9 +260,9 @@ impl TestProps {
props.load_from(testfile, cfg, config);
match (props.pass_mode, props.fail_mode) {
- (None, None) => props.fail_mode = Some(FailMode::Check),
- (Some(_), None) | (None, Some(_)) => {}
+ (None, None) if config.mode == Mode::Ui => props.fail_mode = Some(FailMode::Check),
(Some(_), Some(_)) => panic!("cannot use a *-fail and *-pass mode together"),
+ _ => {}
}
props
@@ -522,8 +522,8 @@ impl TestProps {
}
pub fn pass_mode(&self, config: &Config) -> Option<PassMode> {
- if !self.ignore_pass && self.fail_mode.is_none() && config.mode == Mode::Ui {
- if let (mode @ Some(_), Some(_)) = (config.force_pass_mode, self.pass_mode) {
+ if !self.ignore_pass && self.fail_mode.is_none() {
+ if let mode @ Some(_) = config.force_pass_mode {
return mode;
}
}
diff --git a/src/tools/generate-copyright/Cargo.toml b/src/tools/generate-copyright/Cargo.toml
new file mode 100644
index 00000000000..899ef0f8a6c
--- /dev/null
+++ b/src/tools/generate-copyright/Cargo.toml
@@ -0,0 +1,11 @@
+[package]
+name = "generate-copyright"
+version = "0.1.0"
+edition = "2021"
+
+# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
+
+[dependencies]
+anyhow = "1.0.65"
+serde = { version = "1.0.147", features = ["derive"] }
+serde_json = "1.0.85"
diff --git a/src/tools/generate-copyright/src/main.rs b/src/tools/generate-copyright/src/main.rs
new file mode 100644
index 00000000000..d172c9e157b
--- /dev/null
+++ b/src/tools/generate-copyright/src/main.rs
@@ -0,0 +1,94 @@
+use anyhow::Error;
+use std::io::Write;
+use std::path::PathBuf;
+
+fn main() -> Result<(), Error> {
+ let dest = env_path("DEST")?;
+ let license_metadata = env_path("LICENSE_METADATA")?;
+
+ let metadata: Metadata = serde_json::from_slice(&std::fs::read(&license_metadata)?)?;
+
+ let mut buffer = Vec::new();
+ render_recursive(&metadata.files, &mut buffer, 0)?;
+
+ std::fs::write(&dest, &buffer)?;
+
+ Ok(())
+}
+
+fn render_recursive(node: &Node, buffer: &mut Vec<u8>, depth: usize) -> Result<(), Error> {
+ let prefix = std::iter::repeat("> ").take(depth + 1).collect::<String>();
+
+ match node {
+ Node::Root { childs } => {
+ for child in childs {
+ render_recursive(child, buffer, depth)?;
+ }
+ }
+ Node::Directory { name, childs, license } => {
+ render_license(&prefix, std::iter::once(name), license, buffer)?;
+ if !childs.is_empty() {
+ writeln!(buffer, "{prefix}")?;
+ writeln!(buffer, "{prefix}*Exceptions:*")?;
+ for child in childs {
+ writeln!(buffer, "{prefix}")?;
+ render_recursive(child, buffer, depth + 1)?;
+ }
+ }
+ }
+ Node::FileGroup { names, license } => {
+ render_license(&prefix, names.iter(), license, buffer)?;
+ }
+ Node::File { name, license } => {
+ render_license(&prefix, std::iter::once(name), license, buffer)?;
+ }
+ }
+
+ Ok(())
+}
+
+fn render_license<'a>(
+ prefix: &str,
+ names: impl Iterator<Item = &'a String>,
+ license: &License,
+ buffer: &mut Vec<u8>,
+) -> Result<(), Error> {
+ for name in names {
+ writeln!(buffer, "{prefix}**`{name}`** ")?;
+ }
+ writeln!(buffer, "{prefix}License: `{}` ", license.spdx)?;
+ for (i, copyright) in license.copyright.iter().enumerate() {
+ let suffix = if i == license.copyright.len() - 1 { "" } else { " " };
+ writeln!(buffer, "{prefix}Copyright: {copyright}{suffix}")?;
+ }
+
+ Ok(())
+}
+
+#[derive(serde::Deserialize)]
+struct Metadata {
+ files: Node,
+}
+
+#[derive(serde::Deserialize)]
+#[serde(rename_all = "kebab-case", tag = "type")]
+pub(crate) enum Node {
+ Root { childs: Vec<Node> },
+ Directory { name: String, childs: Vec<Node>, license: License },
+ File { name: String, license: License },
+ FileGroup { names: Vec<String>, license: License },
+}
+
+#[derive(serde::Deserialize)]
+struct License {
+ spdx: String,
+ copyright: Vec<String>,
+}
+
+fn env_path(var: &str) -> Result<PathBuf, Error> {
+ if let Some(var) = std::env::var_os(var) {
+ Ok(var.into())
+ } else {
+ anyhow::bail!("missing environment variable {var}")
+ }
+}
diff --git a/src/tools/miri/rust-version b/src/tools/miri/rust-version
index 0a6b9417cc2..8dd18ae98e6 100644
--- a/src/tools/miri/rust-version
+++ b/src/tools/miri/rust-version
@@ -1 +1 @@
-cef44f53034eac46be3a0e3eec7b2b3d4ef5140b
+203c8765ea33c65d888febe0e8219c4bb11b0d89
diff --git a/src/tools/miri/src/borrow_tracker/stacked_borrows/mod.rs b/src/tools/miri/src/borrow_tracker/stacked_borrows/mod.rs
index 50c2ad75ca7..bcac873251f 100644
--- a/src/tools/miri/src/borrow_tracker/stacked_borrows/mod.rs
+++ b/src/tools/miri/src/borrow_tracker/stacked_borrows/mod.rs
@@ -45,7 +45,9 @@ pub struct Stacks {
/// new pointer.
#[derive(Copy, Clone, Hash, PartialEq, Eq)]
enum RefKind {
- /// `&mut` and `Box`.
+ /// `Box`.
+ Box,
+ /// `&mut`.
Unique { two_phase: bool },
/// `&` with or without interior mutability.
Shared,
@@ -56,6 +58,7 @@ enum RefKind {
impl fmt::Display for RefKind {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
+ RefKind::Box => write!(f, "Box"),
RefKind::Unique { two_phase: false } => write!(f, "unique reference"),
RefKind::Unique { two_phase: true } => write!(f, "unique reference (two-phase)"),
RefKind::Shared => write!(f, "shared reference"),
@@ -654,15 +657,17 @@ trait EvalContextPrivExt<'mir: 'ecx, 'tcx: 'mir, 'ecx>: crate::MiriInterpCxExt<'
let (perm, access) = match kind {
RefKind::Unique { two_phase } => {
// Permission is Unique only if the type is `Unpin` and this is not twophase
- let perm = if !two_phase && place.layout.ty.is_unpin(*this.tcx, this.param_env()) {
- Permission::Unique
+ if !two_phase && place.layout.ty.is_unpin(*this.tcx, this.param_env()) {
+ (Permission::Unique, Some(AccessKind::Write))
} else {
- Permission::SharedReadWrite
- };
- // We do an access for all full borrows, even if `!Unpin`.
- let access = if !two_phase { Some(AccessKind::Write) } else { None };
- (perm, access)
+ // FIXME: We emit `dereferenceable` for `!Unpin` mutable references, so we
+ // should do fake accesses here. But then we run into
+ // <https://github.com/rust-lang/unsafe-code-guidelines/issues/381>, so for now
+ // we don't do that.
+ (Permission::SharedReadWrite, None)
+ }
}
+ RefKind::Box => (Permission::Unique, Some(AccessKind::Write)),
RefKind::Raw { mutable: true } => {
// Creating a raw ptr does not count as an access
(Permission::SharedReadWrite, None)
@@ -853,7 +858,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
// Boxes get a weak protectors, since they may be deallocated.
self.retag_place(
place,
- RefKind::Unique { two_phase: false },
+ RefKind::Box,
self.retag_cause,
/*protector*/
(self.kind == RetagKind::FnEntry).then_some(ProtectorKind::WeakProtector),
diff --git a/src/tools/miri/tests/fail/stacked_borrows/notunpin_dereferenceable_fakeread.rs b/src/tools/miri/tests/fail/stacked_borrows/notunpin_dereferenceable_fakeread.rs
deleted file mode 100644
index d660921bfe6..00000000000
--- a/src/tools/miri/tests/fail/stacked_borrows/notunpin_dereferenceable_fakeread.rs
+++ /dev/null
@@ -1,17 +0,0 @@
-//! Reborrowing a `&mut !Unpin` must still act like a (fake) read.
-use std::marker::PhantomPinned;
-
-struct NotUnpin(i32, PhantomPinned);
-
-fn main() {
- unsafe {
- let mut x = NotUnpin(0, PhantomPinned);
- // Mutable borrow of `Unpin` field (with lifetime laundering)
- let fieldref = &mut *(&mut x.0 as *mut i32);
- // Mutable reborrow of the entire `x`, which is `!Unpin` but should
- // still count as a read since we would add `dereferenceable`.
- let _xref = &mut x;
- // That read should have invalidated `fieldref`.
- *fieldref = 0; //~ ERROR: /write access .* tag does not exist in the borrow stack/
- }
-}
diff --git a/src/tools/miri/tests/fail/stacked_borrows/notunpin_dereferenceable_fakeread.stderr b/src/tools/miri/tests/fail/stacked_borrows/notunpin_dereferenceable_fakeread.stderr
deleted file mode 100644
index 3ef8a8e0e9c..00000000000
--- a/src/tools/miri/tests/fail/stacked_borrows/notunpin_dereferenceable_fakeread.stderr
+++ /dev/null
@@ -1,28 +0,0 @@
-error: Undefined Behavior: attempting a write access using <TAG> at ALLOC[0x0], but that tag does not exist in the borrow stack for this location
- --> $DIR/notunpin_dereferenceable_fakeread.rs:LL:CC
- |
-LL | *fieldref = 0;
- | ^^^^^^^^^^^^^
- | |
- | attempting a write access using <TAG> at ALLOC[0x0], but that tag does not exist in the borrow stack for this location
- | this error occurs as part of an access at ALLOC[0x0..0x4]
- |
- = help: this indicates a potential bug in the program: it performed an invalid operation, but the Stacked Borrows rules it violated are still experimental
- = help: see https://github.com/rust-lang/unsafe-code-guidelines/blob/master/wip/stacked-borrows.md for further information
-help: <TAG> was created by a Unique retag at offsets [0x0..0x4]
- --> $DIR/notunpin_dereferenceable_fakeread.rs:LL:CC
- |
-LL | let fieldref = &mut *(&mut x.0 as *mut i32);
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-help: <TAG> was later invalidated at offsets [0x0..0x4] by a SharedReadWrite retag
- --> $DIR/notunpin_dereferenceable_fakeread.rs:LL:CC
- |
-LL | let _xref = &mut x;
- | ^^^^^^
- = note: BACKTRACE:
- = note: inside `main` at $DIR/notunpin_dereferenceable_fakeread.rs:LL:CC
-
-note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace
-
-error: aborting due to previous error
-
diff --git a/src/tools/miri/tests/pass/stacked-borrows/future-self-referential.rs b/src/tools/miri/tests/pass/stacked-borrows/future-self-referential.rs
new file mode 100644
index 00000000000..3ba21552fd3
--- /dev/null
+++ b/src/tools/miri/tests/pass/stacked-borrows/future-self-referential.rs
@@ -0,0 +1,102 @@
+#![feature(pin_macro)]
+
+use std::future::*;
+use std::marker::PhantomPinned;
+use std::pin::*;
+use std::ptr;
+use std::task::*;
+
+struct Delay {
+ delay: usize,
+}
+
+impl Delay {
+ fn new(delay: usize) -> Self {
+ Delay { delay }
+ }
+}
+
+impl Future for Delay {
+ type Output = ();
+ fn poll(mut self: Pin<&mut Self>, _cx: &mut Context<'_>) -> Poll<()> {
+ if self.delay > 0 {
+ self.delay -= 1;
+ Poll::Pending
+ } else {
+ Poll::Ready(())
+ }
+ }
+}
+
+async fn do_stuff() {
+ (&mut Delay::new(1)).await;
+}
+
+// Same thing implemented by hand
+struct DoStuff {
+ state: usize,
+ delay: Delay,
+ delay_ref: *mut Delay,
+ _marker: PhantomPinned,
+}
+
+impl DoStuff {
+ fn new() -> Self {
+ DoStuff {
+ state: 0,
+ delay: Delay::new(1),
+ delay_ref: ptr::null_mut(),
+ _marker: PhantomPinned,
+ }
+ }
+}
+
+impl Future for DoStuff {
+ type Output = ();
+ fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<()> {
+ unsafe {
+ let this = self.get_unchecked_mut();
+ match this.state {
+ 0 => {
+ // Set up self-ref.
+ this.delay_ref = &mut this.delay;
+ // Move to next state.
+ this.state = 1;
+ Poll::Pending
+ }
+ 1 => {
+ let delay = &mut *this.delay_ref;
+ Pin::new_unchecked(delay).poll(cx)
+ }
+ _ => unreachable!(),
+ }
+ }
+ }
+}
+
+fn run_fut<T>(fut: impl Future<Output = T>) -> T {
+ use std::sync::Arc;
+
+ struct MyWaker;
+ impl Wake for MyWaker {
+ fn wake(self: Arc<Self>) {
+ unimplemented!()
+ }
+ }
+
+ let waker = Waker::from(Arc::new(MyWaker));
+ let mut context = Context::from_waker(&waker);
+
+ let mut pinned = pin!(fut);
+ loop {
+ match pinned.as_mut().poll(&mut context) {
+ Poll::Pending => continue,
+ Poll::Ready(v) => return v,
+ }
+ }
+}
+
+fn main() {
+ run_fut(do_stuff());
+ run_fut(DoStuff::new());
+}
diff --git a/triagebot.toml b/triagebot.toml
index bc0b88b2bab..49945e5c533 100644
--- a/triagebot.toml
+++ b/triagebot.toml
@@ -331,8 +331,16 @@ message = "Some changes occurred to MIR optimizations"
cc = ["@rust-lang/wg-mir-opt"]
[mentions."compiler/rustc_trait_selection/src/traits/const_evaluatable.rs"]
-message = "Some changes occurred in const_evaluatable.rs"
-cc = ["@lcnr"]
+message = "Some changes occurred in `const_evaluatable.rs`"
+cc = ["@BoxyUwU"]
+
+[mentions."compiler/rustc_middle/src/ty/abstract_const.rs"]
+message = "Some changes occured in `abstract_const.rs`"
+cc = ["@BoxyUwU"]
+
+[mentions."compiler/rustc_ty_utils/src/consts.rs"]
+message = "Some changes occured in `rustc_ty_utils::consts.rs`"
+cc = ["@BoxyUwU"]
[mentions."compiler/rustc_trait_selection/src/traits/engine.rs"]
message = """