diff --git a/.github/ISSUE_TEMPLATE/config.yml b/.github/ISSUE_TEMPLATE/config.yml index 7d4cfaece448..a2878a0e0120 100644 --- a/.github/ISSUE_TEMPLATE/config.yml +++ b/.github/ISSUE_TEMPLATE/config.yml @@ -6,3 +6,6 @@ contact_links: - name: Feature Request url: https://internals.rust-lang.org/ about: Please discuss language feature requests on the internals forum. + - name: Clippy Bug + url: https://github.com/rust-lang/rust-clippy/issues/new/choose + about: Please report Clippy bugs such as false positives in the Clippy repo. diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 2f54d2838cf2..8d64b5f076e4 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -30,10 +30,11 @@ permissions: defaults: run: shell: bash +concurrency: + group: "${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}" + cancel-in-progress: true jobs: pr: - permissions: - actions: write name: "PR - ${{ matrix.name }}" env: CI_JOB_NAME: "${{ matrix.name }}" @@ -84,11 +85,6 @@ jobs: - name: ensure the channel matches the target branch run: src/ci/scripts/verify-channel.sh if: success() && !env.SKIP_JOB - - name: configure GitHub Actions to kill the build when outdated - uses: rust-lang/simpleinfra/github-actions/cancel-outdated-builds@master - with: - github_token: "${{ secrets.github_token }}" - if: "success() && !env.SKIP_JOB && github.ref != 'refs/heads/try' && github.ref != 'refs/heads/try-perf'" - name: collect CPU statistics run: src/ci/scripts/collect-cpu-stats.sh if: success() && !env.SKIP_JOB @@ -162,8 +158,6 @@ jobs: AWS_SECRET_ACCESS_KEY: "${{ secrets[format('AWS_SECRET_ACCESS_KEY_{0}', env.ARTIFACTS_AWS_ACCESS_KEY_ID)] }}" if: "success() && !env.SKIP_JOB && (github.event_name == 'push' || env.DEPLOY == '1' || env.DEPLOY_ALT == '1')" auto: - permissions: - actions: write name: "auto - ${{ matrix.name }}" env: CI_JOB_NAME: "${{ matrix.name }}" @@ -496,11 +490,6 @@ jobs: - name: ensure the channel matches the target branch run: src/ci/scripts/verify-channel.sh if: success() && !env.SKIP_JOB - - name: configure GitHub Actions to kill the build when outdated - uses: rust-lang/simpleinfra/github-actions/cancel-outdated-builds@master - with: - github_token: "${{ secrets.github_token }}" - if: "success() && !env.SKIP_JOB && github.ref != 'refs/heads/try' && github.ref != 'refs/heads/try-perf'" - name: collect CPU statistics run: src/ci/scripts/collect-cpu-stats.sh if: success() && !env.SKIP_JOB @@ -574,8 +563,6 @@ jobs: AWS_SECRET_ACCESS_KEY: "${{ secrets[format('AWS_SECRET_ACCESS_KEY_{0}', env.ARTIFACTS_AWS_ACCESS_KEY_ID)] }}" if: "success() && !env.SKIP_JOB && (github.event_name == 'push' || env.DEPLOY == '1' || env.DEPLOY_ALT == '1')" try: - permissions: - actions: write name: "try - ${{ matrix.name }}" env: DIST_TRY_BUILD: 1 @@ -623,11 +610,6 @@ jobs: - name: ensure the channel matches the target branch run: src/ci/scripts/verify-channel.sh if: success() && !env.SKIP_JOB - - name: configure GitHub Actions to kill the build when outdated - uses: rust-lang/simpleinfra/github-actions/cancel-outdated-builds@master - with: - github_token: "${{ secrets.github_token }}" - if: "success() && !env.SKIP_JOB && github.ref != 'refs/heads/try' && github.ref != 'refs/heads/try-perf'" - name: collect CPU statistics run: src/ci/scripts/collect-cpu-stats.sh if: success() && !env.SKIP_JOB diff --git a/.github/workflows/dependencies.yml b/.github/workflows/dependencies.yml index 2eccd28e5bb1..26d2ba636f3e 100644 --- a/.github/workflows/dependencies.yml +++ b/.github/workflows/dependencies.yml @@ -25,6 +25,7 @@ env: jobs: not-waiting-on-bors: + if: github.repository_owner == 'rust-lang' name: skip if S-waiting-on-bors runs-on: ubuntu-latest steps: @@ -43,6 +44,7 @@ jobs: fi update: + if: github.repository_owner == 'rust-lang' name: update dependencies needs: not-waiting-on-bors runs-on: ubuntu-latest @@ -76,6 +78,7 @@ jobs: retention-days: 1 pr: + if: github.repository_owner == 'rust-lang' name: amend PR needs: update runs-on: ubuntu-latest diff --git a/Cargo.lock b/Cargo.lock index 28db40639961..dc2d2e324c93 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -480,23 +480,6 @@ dependencies = [ "winapi", ] -[[package]] -name = "clap" -version = "3.2.20" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "23b71c3ce99b7611011217b366d923f1d0a7e07a92bb2dbf1e84508c673ca3bd" -dependencies = [ - "atty", - "bitflags", - "clap_derive 3.2.18", - "clap_lex 0.2.2", - "indexmap", - "once_cell", - "strsim", - "termcolor", - "textwrap", -] - [[package]] name = "clap" version = "4.2.1" @@ -504,7 +487,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "046ae530c528f252094e4a77886ee1374437744b2bff1497aa898bbddbbb29b3" dependencies = [ "clap_builder", - "clap_derive 4.2.0", + "clap_derive", "once_cell", ] @@ -517,7 +500,7 @@ dependencies = [ "anstream", "anstyle", "bitflags", - "clap_lex 0.4.1", + "clap_lex", "once_cell", "strsim", "terminal_size", @@ -529,20 +512,7 @@ version = "4.0.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "10861370d2ba66b0f5989f83ebf35db6421713fd92351790e7fdd6c36774c56b" dependencies = [ - "clap 4.2.1", -] - -[[package]] -name = "clap_derive" -version = "3.2.18" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ea0c8bce528c4be4da13ea6fead8965e95b6073585a2f05204bd8f4119f82a65" -dependencies = [ - "heck", - "proc-macro-error", - "proc-macro2", - "quote", - "syn 1.0.102", + "clap", ] [[package]] @@ -557,15 +527,6 @@ dependencies = [ "syn 2.0.8", ] -[[package]] -name = "clap_lex" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5538cd660450ebeb4234cfecf8f2284b844ffc4c50531e66d584ad5b91293613" -dependencies = [ - "os_str_bytes", -] - [[package]] name = "clap_lex" version = "0.4.1" @@ -576,7 +537,7 @@ checksum = "8a2dd5a6fe8c6e3502f568a6353e5273bbb15193ad9a89e457b9970798efbea1" name = "clippy" version = "0.1.72" dependencies = [ - "clap 4.2.1", + "clap", "clippy_lints", "clippy_utils", "compiletest_rs", @@ -605,7 +566,7 @@ name = "clippy_dev" version = "0.0.1" dependencies = [ "aho-corasick", - "clap 4.2.1", + "clap", "indoc", "itertools", "opener", @@ -1749,7 +1710,7 @@ name = "installer" version = "0.0.0" dependencies = [ "anyhow", - "clap 3.2.20", + "clap", "flate2", "num_cpus", "rayon", @@ -1869,7 +1830,7 @@ name = "jsondoclint" version = "0.1.0" dependencies = [ "anyhow", - "clap 4.2.1", + "clap", "fs-err", "rustc-hash", "rustdoc-json-types", @@ -2086,7 +2047,7 @@ dependencies = [ "ammonia", "anyhow", "chrono", - "clap 4.2.1", + "clap", "clap_complete", "elasticlunr-rs", "env_logger 0.10.0", @@ -2370,12 +2331,6 @@ dependencies = [ "vcpkg", ] -[[package]] -name = "os_str_bytes" -version = "6.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e22443d1643a904602595ba1cd8f7d896afe56d26712531c5ff73a15b2fbf64" - [[package]] name = "owo-colors" version = "3.5.0" @@ -2617,30 +2572,6 @@ version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "925383efa346730478fb4838dbe9137d2a47675ad789c546d150a6e1dd4ab31c" -[[package]] -name = "proc-macro-error" -version = "1.0.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "da25490ff9892aab3fcf7c36f08cfb902dd3e71ca0f9f9517bea02a73a5ce38c" -dependencies = [ - "proc-macro-error-attr", - "proc-macro2", - "quote", - "syn 1.0.102", - "version_check", -] - -[[package]] -name = "proc-macro-error-attr" -version = "1.0.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a1be40180e52ecc98ad80b184934baf3d0d29f979574e439af5a55274b35f869" -dependencies = [ - "proc-macro2", - "quote", - "version_check", -] - [[package]] name = "proc-macro-hack" version = "0.5.19" @@ -2897,7 +2828,7 @@ dependencies = [ name = "rustbook" version = "0.1.0" dependencies = [ - "clap 4.2.1", + "clap", "env_logger 0.10.0", "mdbook", ] @@ -4346,7 +4277,7 @@ dependencies = [ "anyhow", "bytecount", "cargo_metadata", - "clap 4.2.1", + "clap", "diff", "dirs", "env_logger 0.10.0", @@ -4874,12 +4805,6 @@ dependencies = [ "term", ] -[[package]] -name = "textwrap" -version = "0.15.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b1141d4d61095b28419e22cb0bbf02755f5e54e0526f97f1e3d1d160e60885fb" - [[package]] name = "thin-vec" version = "0.2.12" diff --git a/README.md b/README.md index 41b135972af1..901213d2ca97 100644 --- a/README.md +++ b/README.md @@ -33,24 +33,13 @@ format: ``` This is how the documentation and examples assume you are running `x.py`. -Some alternative ways are: - -```sh -# On a Unix shell if you don't have the necessary `python3` command -./x [flags] - -# On the Windows Command Prompt (if .py files are configured to run Python) -x.py [flags] - -# You can also run Python yourself, e.g.: -python x.py [flags] -``` +See the [rustc dev guide][rustcguidebuild] if this does not work on your platform. More information about `x.py` can be found by running it with the `--help` flag or reading the [rustc dev guide][rustcguidebuild]. [gettingstarted]: https://rustc-dev-guide.rust-lang.org/getting-started.html -[rustcguidebuild]: https://rustc-dev-guide.rust-lang.org/building/how-to-build-and-run.html +[rustcguidebuild]: https://rustc-dev-guide.rust-lang.org/building/how-to-build-and-run.html#what-is-xpy ### Dependencies diff --git a/compiler/rustc_ast_lowering/src/expr.rs b/compiler/rustc_ast_lowering/src/expr.rs index 225714a13615..29972dd76eb0 100644 --- a/compiler/rustc_ast_lowering/src/expr.rs +++ b/compiler/rustc_ast_lowering/src/expr.rs @@ -277,9 +277,7 @@ impl<'hir> LoweringContext<'_, 'hir> { ExprKind::Yeet(sub_expr) => self.lower_expr_yeet(e.span, sub_expr.as_deref()), ExprKind::Become(sub_expr) => { let sub_expr = self.lower_expr(sub_expr); - - // FIXME(explicit_tail_calls): Use `hir::ExprKind::Become` once we implemented it - hir::ExprKind::Ret(Some(sub_expr)) + hir::ExprKind::Become(sub_expr) } ExprKind::InlineAsm(asm) => { hir::ExprKind::InlineAsm(self.lower_inline_asm(e.span, asm)) diff --git a/compiler/rustc_ast_passes/src/ast_validation.rs b/compiler/rustc_ast_passes/src/ast_validation.rs index a0979bbda545..096cea945b02 100644 --- a/compiler/rustc_ast_passes/src/ast_validation.rs +++ b/compiler/rustc_ast_passes/src/ast_validation.rs @@ -623,13 +623,12 @@ impl<'a> AstValidator<'a> { fn maybe_lint_missing_abi(&mut self, span: Span, id: NodeId) { // FIXME(davidtwco): This is a hack to detect macros which produce spans of the // call site which do not have a macro backtrace. See #61963. - let is_macro_callsite = self + if self .session .source_map() .span_to_snippet(span) - .map(|snippet| snippet.starts_with("#[")) - .unwrap_or(true); - if !is_macro_callsite { + .is_ok_and(|snippet| !snippet.starts_with("#[")) + { self.lint_buffer.buffer_lint_with_diagnostic( MISSING_ABI, id, diff --git a/compiler/rustc_ast_passes/src/errors.rs b/compiler/rustc_ast_passes/src/errors.rs index 82fe2a21d087..ab8015c4a43b 100644 --- a/compiler/rustc_ast_passes/src/errors.rs +++ b/compiler/rustc_ast_passes/src/errors.rs @@ -77,13 +77,6 @@ pub struct ForbiddenLifetimeBound { pub spans: Vec, } -#[derive(Diagnostic)] -#[diag(ast_passes_forbidden_non_lifetime_param)] -pub struct ForbiddenNonLifetimeParam { - #[primary_span] - pub spans: Vec, -} - #[derive(Diagnostic)] #[diag(ast_passes_fn_param_too_many)] pub struct FnParamTooMany { diff --git a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs index 5c365e98f0ba..39b05829888c 100644 --- a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs +++ b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs @@ -678,8 +678,8 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { let tcx = self.infcx.tcx; // Find out if the predicates show that the type is a Fn or FnMut - let find_fn_kind_from_did = |(pred, _): (ty::Predicate<'tcx>, _)| { - if let ty::PredicateKind::Clause(ty::ClauseKind::Trait(pred)) = pred.kind().skip_binder() + let find_fn_kind_from_did = |(pred, _): (ty::Clause<'tcx>, _)| { + if let ty::ClauseKind::Trait(pred) = pred.kind().skip_binder() && pred.self_ty() == ty { if Some(pred.def_id()) == tcx.lang_items().fn_trait() { @@ -705,7 +705,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { ty::Alias(ty::Opaque, ty::AliasTy { def_id, substs, .. }) => tcx .explicit_item_bounds(def_id) .subst_iter_copied(tcx, substs) - .find_map(|(clause, span)| find_fn_kind_from_did((clause.as_predicate(), span))), + .find_map(|(clause, span)| find_fn_kind_from_did((clause, span))), ty::Closure(_, substs) => match substs.as_closure().kind() { ty::ClosureKind::Fn => Some(hir::Mutability::Not), ty::ClosureKind::FnMut => Some(hir::Mutability::Mut), diff --git a/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs b/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs index 1ba490e9a01c..1f2fefadf65c 100644 --- a/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs +++ b/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs @@ -123,13 +123,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { item_msg = access_place_desc; debug_assert!(self.body.local_decls[ty::CAPTURE_STRUCT_LOCAL].ty.is_ref()); debug_assert!(is_closure_or_generator( - Place::ty_from( - the_place_err.local, - the_place_err.projection, - self.body, - self.infcx.tcx - ) - .ty + the_place_err.ty(self.body, self.infcx.tcx).ty )); reason = if self.is_upvar_field_projection(access_place.as_ref()).is_some() { diff --git a/compiler/rustc_borrowck/src/diagnostics/region_name.rs b/compiler/rustc_borrowck/src/diagnostics/region_name.rs index 55c9864af8c7..074f37bed134 100644 --- a/compiler/rustc_borrowck/src/diagnostics/region_name.rs +++ b/compiler/rustc_borrowck/src/diagnostics/region_name.rs @@ -928,7 +928,7 @@ impl<'tcx> MirBorrowckCtxt<'_, 'tcx> { fn any_param_predicate_mentions( &self, - predicates: &[ty::Predicate<'tcx>], + clauses: &[ty::Clause<'tcx>], ty: Ty<'tcx>, region: ty::EarlyBoundRegion, ) -> bool { @@ -937,10 +937,10 @@ impl<'tcx> MirBorrowckCtxt<'_, 'tcx> { if let ty::GenericArgKind::Type(ty) = arg.unpack() && let ty::Param(_) = ty.kind() { - predicates.iter().any(|pred| { + clauses.iter().any(|pred| { match pred.kind().skip_binder() { - ty::PredicateKind::Clause(ty::ClauseKind::Trait(data)) if data.self_ty() == ty => {} - ty::PredicateKind::Clause(ty::ClauseKind::Projection(data)) if data.projection_ty.self_ty() == ty => {} + ty::ClauseKind::Trait(data) if data.self_ty() == ty => {} + ty::ClauseKind::Projection(data) if data.projection_ty.self_ty() == ty => {} _ => return false, } tcx.any_free_region_meets(pred, |r| { diff --git a/compiler/rustc_borrowck/src/place_ext.rs b/compiler/rustc_borrowck/src/place_ext.rs index d521d0db2132..3d7e8c6ebf33 100644 --- a/compiler/rustc_borrowck/src/place_ext.rs +++ b/compiler/rustc_borrowck/src/place_ext.rs @@ -46,11 +46,9 @@ impl<'tcx> PlaceExt<'tcx> for Place<'tcx> { } } - for (i, elem) in self.projection.iter().enumerate() { - let proj_base = &self.projection[..i]; - + for (i, (proj_base, elem)) in self.iter_projections().enumerate() { if elem == ProjectionElem::Deref { - let ty = Place::ty_from(self.local, proj_base, body, tcx).ty; + let ty = proj_base.ty(body, tcx).ty; match ty.kind() { ty::Ref(_, _, hir::Mutability::Not) if i == 0 => { // For references to thread-local statics, we do need diff --git a/compiler/rustc_borrowck/src/places_conflict.rs b/compiler/rustc_borrowck/src/places_conflict.rs index c83d045a94e1..1217dcb9c40e 100644 --- a/compiler/rustc_borrowck/src/places_conflict.rs +++ b/compiler/rustc_borrowck/src/places_conflict.rs @@ -137,13 +137,11 @@ fn place_components_conflict<'tcx>( } // loop invariant: borrow_c is always either equal to access_c or disjoint from it. - for (i, (borrow_c, &access_c)) in - iter::zip(borrow_place.projection, access_place.projection).enumerate() + for ((borrow_place, borrow_c), &access_c) in + iter::zip(borrow_place.iter_projections(), access_place.projection) { debug!(?borrow_c, ?access_c); - let borrow_proj_base = &borrow_place.projection[..i]; - // Borrow and access path both have more components. // // Examples: @@ -156,15 +154,7 @@ fn place_components_conflict<'tcx>( // check whether the components being borrowed vs // accessed are disjoint (as in the second example, // but not the first). - match place_projection_conflict( - tcx, - body, - borrow_local, - borrow_proj_base, - borrow_c, - access_c, - bias, - ) { + match place_projection_conflict(tcx, body, borrow_place, borrow_c, access_c, bias) { Overlap::Arbitrary => { // We have encountered different fields of potentially // the same union - the borrow now partially overlaps. @@ -195,8 +185,7 @@ fn place_components_conflict<'tcx>( } if borrow_place.projection.len() > access_place.projection.len() { - for (i, elem) in borrow_place.projection[access_place.projection.len()..].iter().enumerate() - { + for (base, elem) in borrow_place.iter_projections().skip(access_place.projection.len()) { // Borrow path is longer than the access path. Examples: // // - borrow of `a.b.c`, access to `a.b` @@ -205,8 +194,7 @@ fn place_components_conflict<'tcx>( // our place. This is a conflict if that is a part our // access cares about. - let proj_base = &borrow_place.projection[..access_place.projection.len() + i]; - let base_ty = Place::ty_from(borrow_local, proj_base, body, tcx).ty; + let base_ty = base.ty(body, tcx).ty; match (elem, &base_ty.kind(), access) { (_, _, Shallow(Some(ArtificialField::ArrayLength))) @@ -310,8 +298,7 @@ fn place_base_conflict(l1: Local, l2: Local) -> Overlap { fn place_projection_conflict<'tcx>( tcx: TyCtxt<'tcx>, body: &Body<'tcx>, - pi1_local: Local, - pi1_proj_base: &[PlaceElem<'tcx>], + pi1: PlaceRef<'tcx>, pi1_elem: PlaceElem<'tcx>, pi2_elem: PlaceElem<'tcx>, bias: PlaceConflictBias, @@ -333,7 +320,7 @@ fn place_projection_conflict<'tcx>( debug!("place_element_conflict: DISJOINT-OR-EQ-FIELD"); Overlap::EqualOrDisjoint } else { - let ty = Place::ty_from(pi1_local, pi1_proj_base, body, tcx).ty; + let ty = pi1.ty(body, tcx).ty; if ty.is_union() { // Different fields of a union, we are basically stuck. debug!("place_element_conflict: STUCK-UNION"); diff --git a/compiler/rustc_borrowck/src/type_check/mod.rs b/compiler/rustc_borrowck/src/type_check/mod.rs index 0a897272d358..23c3b7b70169 100644 --- a/compiler/rustc_borrowck/src/type_check/mod.rs +++ b/compiler/rustc_borrowck/src/type_check/mod.rs @@ -50,7 +50,6 @@ use rustc_mir_dataflow::impls::MaybeInitializedPlaces; use rustc_mir_dataflow::move_paths::MoveData; use rustc_mir_dataflow::ResultsCursor; -use crate::renumber::RegionCtxt; use crate::session_diagnostics::MoveUnsized; use crate::{ borrow_set::BorrowSet, @@ -1040,9 +1039,9 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { .collect(); let renumbered_opaques = self.infcx.tcx.fold_regions(opaques, |_, _| { - self.infcx.next_nll_region_var( + self.infcx.next_nll_region_var_in_universe( NllRegionVariableOrigin::Existential { from_forall: false }, - || RegionCtxt::Unknown, + ty::UniverseIndex::ROOT, ) }); @@ -2503,7 +2502,6 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { location, borrow_region, borrowed_place ); - let mut cursor = borrowed_place.projection.as_ref(); let tcx = self.infcx.tcx; let field = path_utils::is_upvar_field_projection( tcx, @@ -2517,14 +2515,12 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { ConstraintCategory::Boring }; - while let [proj_base @ .., elem] = cursor { - cursor = proj_base; - + for (base, elem) in borrowed_place.as_ref().iter_projections().rev() { debug!("add_reborrow_constraint - iteration {:?}", elem); match elem { ProjectionElem::Deref => { - let base_ty = Place::ty_from(borrowed_place.local, proj_base, body, tcx).ty; + let base_ty = base.ty(body, tcx).ty; debug!("add_reborrow_constraint - base_ty = {:?}", base_ty); match base_ty.kind() { diff --git a/compiler/rustc_builtin_macros/src/derive.rs b/compiler/rustc_builtin_macros/src/derive.rs index fe4483104eeb..140853db695a 100644 --- a/compiler/rustc_builtin_macros/src/derive.rs +++ b/compiler/rustc_builtin_macros/src/derive.rs @@ -8,7 +8,7 @@ use rustc_feature::AttributeTemplate; use rustc_parse::validate_attr; use rustc_session::Session; use rustc_span::symbol::{sym, Ident}; -use rustc_span::Span; +use rustc_span::{ErrorGuaranteed, Span}; pub(crate) struct Expander(pub bool); @@ -22,7 +22,7 @@ impl MultiItemModifier for Expander { _: bool, ) -> ExpandResult, Annotatable> { let sess = ecx.sess; - if report_bad_target(sess, &item, span) { + if report_bad_target(sess, &item, span).is_err() { // We don't want to pass inappropriate targets to derive macros to avoid // follow up errors, all other errors below are recoverable. return ExpandResult::Ready(vec![item]); @@ -103,7 +103,11 @@ fn dummy_annotatable() -> Annotatable { }) } -fn report_bad_target(sess: &Session, item: &Annotatable, span: Span) -> bool { +fn report_bad_target( + sess: &Session, + item: &Annotatable, + span: Span, +) -> Result<(), ErrorGuaranteed> { let item_kind = match item { Annotatable::Item(item) => Some(&item.kind), Annotatable::Stmt(stmt) => match &stmt.kind { @@ -116,9 +120,9 @@ fn report_bad_target(sess: &Session, item: &Annotatable, span: Span) -> bool { let bad_target = !matches!(item_kind, Some(ItemKind::Struct(..) | ItemKind::Enum(..) | ItemKind::Union(..))); if bad_target { - sess.emit_err(errors::BadDeriveTarget { span, item: item.span() }); + return Err(sess.emit_err(errors::BadDeriveTarget { span, item: item.span() })); } - bad_target + Ok(()) } fn report_unexpected_meta_item_lit(sess: &Session, lit: &ast::MetaItemLit) { diff --git a/compiler/rustc_builtin_macros/src/test.rs b/compiler/rustc_builtin_macros/src/test.rs index fcc68010a34c..d7a92dac50f6 100644 --- a/compiler/rustc_builtin_macros/src/test.rs +++ b/compiler/rustc_builtin_macros/src/test.rs @@ -8,7 +8,7 @@ use rustc_ast_pretty::pprust; use rustc_errors::Applicability; use rustc_expand::base::*; use rustc_span::symbol::{sym, Ident, Symbol}; -use rustc_span::{FileNameDisplayPreference, Span}; +use rustc_span::{ErrorGuaranteed, FileNameDisplayPreference, Span}; use std::iter; use thin_vec::{thin_vec, ThinVec}; @@ -128,12 +128,15 @@ pub fn expand_test_or_bench( }; }; - // has_*_signature will report any errors in the type so compilation + // check_*_signature will report any errors in the type so compilation // will fail. We shouldn't try to expand in this case because the errors // would be spurious. - if (!is_bench && !has_test_signature(cx, &item)) - || (is_bench && !has_bench_signature(cx, &item)) - { + let check_result = if is_bench { + check_bench_signature(cx, &item, &fn_) + } else { + check_test_signature(cx, &item, &fn_) + }; + if check_result.is_err() { return if is_stmt { vec![Annotatable::Stmt(P(cx.stmt_item(item.span, item)))] } else { @@ -523,72 +526,62 @@ fn test_type(cx: &ExtCtxt<'_>) -> TestType { } } -fn has_test_signature(cx: &ExtCtxt<'_>, i: &ast::Item) -> bool { +fn check_test_signature( + cx: &ExtCtxt<'_>, + i: &ast::Item, + f: &ast::Fn, +) -> Result<(), ErrorGuaranteed> { let has_should_panic_attr = attr::contains_name(&i.attrs, sym::should_panic); let sd = &cx.sess.parse_sess.span_diagnostic; - match &i.kind { - ast::ItemKind::Fn(box ast::Fn { sig, generics, .. }) => { - if let ast::Unsafe::Yes(span) = sig.header.unsafety { - sd.emit_err(errors::TestBadFn { span: i.span, cause: span, kind: "unsafe" }); - return false; - } - if let ast::Async::Yes { span, .. } = sig.header.asyncness { - sd.emit_err(errors::TestBadFn { span: i.span, cause: span, kind: "async" }); - return false; - } - // If the termination trait is active, the compiler will check that the output - // type implements the `Termination` trait as `libtest` enforces that. - let has_output = match &sig.decl.output { - ast::FnRetTy::Default(..) => false, - ast::FnRetTy::Ty(t) if t.kind.is_unit() => false, - _ => true, - }; - - if !sig.decl.inputs.is_empty() { - sd.span_err(i.span, "functions used as tests can not have any arguments"); - return false; - } - - if has_should_panic_attr && has_output { - sd.span_err(i.span, "functions using `#[should_panic]` must return `()`"); - return false; - } - - if generics.params.iter().any(|param| !matches!(param.kind, GenericParamKind::Lifetime)) - { - sd.span_err( - i.span, - "functions used as tests can not have any non-lifetime generic parameters", - ); - return false; - } - - true - } - _ => { - // should be unreachable because `is_test_fn_item` should catch all non-fn items - debug_assert!(false); - false - } + if let ast::Unsafe::Yes(span) = f.sig.header.unsafety { + return Err(sd.emit_err(errors::TestBadFn { span: i.span, cause: span, kind: "unsafe" })); } -} -fn has_bench_signature(cx: &ExtCtxt<'_>, i: &ast::Item) -> bool { - let has_sig = match &i.kind { - // N.B., inadequate check, but we're running - // well before resolve, can't get too deep. - ast::ItemKind::Fn(box ast::Fn { sig, .. }) => sig.decl.inputs.len() == 1, - _ => false, + if let ast::Async::Yes { span, .. } = f.sig.header.asyncness { + return Err(sd.emit_err(errors::TestBadFn { span: i.span, cause: span, kind: "async" })); + } + + // If the termination trait is active, the compiler will check that the output + // type implements the `Termination` trait as `libtest` enforces that. + let has_output = match &f.sig.decl.output { + ast::FnRetTy::Default(..) => false, + ast::FnRetTy::Ty(t) if t.kind.is_unit() => false, + _ => true, }; - if !has_sig { - cx.sess.parse_sess.span_diagnostic.span_err( + if !f.sig.decl.inputs.is_empty() { + return Err(sd.span_err(i.span, "functions used as tests can not have any arguments")); + } + + if has_should_panic_attr && has_output { + return Err(sd.span_err(i.span, "functions using `#[should_panic]` must return `()`")); + } + + if f.generics.params.iter().any(|param| !matches!(param.kind, GenericParamKind::Lifetime)) { + return Err(sd.span_err( + i.span, + "functions used as tests can not have any non-lifetime generic parameters", + )); + } + + Ok(()) +} + +fn check_bench_signature( + cx: &ExtCtxt<'_>, + i: &ast::Item, + f: &ast::Fn, +) -> Result<(), ErrorGuaranteed> { + // N.B., inadequate check, but we're running + // well before resolve, can't get too deep. + if f.sig.decl.inputs.len() != 1 { + return Err(cx.sess.parse_sess.span_diagnostic.span_err( i.span, "functions used as benches must have \ signature `fn(&mut Bencher) -> impl Termination`", - ); + )); } - has_sig + Ok(()) } diff --git a/compiler/rustc_codegen_cranelift/src/pretty_clif.rs b/compiler/rustc_codegen_cranelift/src/pretty_clif.rs index 1007b33eca42..5a4f9e804453 100644 --- a/compiler/rustc_codegen_cranelift/src/pretty_clif.rs +++ b/compiler/rustc_codegen_cranelift/src/pretty_clif.rs @@ -225,10 +225,10 @@ pub(crate) fn write_ir_file( let res = std::fs::File::create(clif_file_name).and_then(|mut file| write(&mut file)); if let Err(err) = res { // Using early_warn as no Session is available here - rustc_session::early_warn( + let handler = rustc_session::EarlyErrorHandler::new( rustc_session::config::ErrorOutputType::default(), - format!("error writing ir file: {}", err), ); + handler.early_warn(format!("error writing ir file: {}", err)); } } diff --git a/compiler/rustc_codegen_llvm/src/builder.rs b/compiler/rustc_codegen_llvm/src/builder.rs index b4aa001547c4..43258078bd77 100644 --- a/compiler/rustc_codegen_llvm/src/builder.rs +++ b/compiler/rustc_codegen_llvm/src/builder.rs @@ -572,8 +572,6 @@ impl<'a, 'll, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> { ) { let zero = self.const_usize(0); let count = self.const_usize(count); - let start = dest.project_index(self, zero).llval; - let end = dest.project_index(self, count).llval; let header_bb = self.append_sibling_block("repeat_loop_header"); let body_bb = self.append_sibling_block("repeat_loop_body"); @@ -582,24 +580,18 @@ impl<'a, 'll, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> { self.br(header_bb); let mut header_bx = Self::build(self.cx, header_bb); - let current = header_bx.phi(self.val_ty(start), &[start], &[self.llbb()]); + let i = header_bx.phi(self.val_ty(zero), &[zero], &[self.llbb()]); - let keep_going = header_bx.icmp(IntPredicate::IntNE, current, end); + let keep_going = header_bx.icmp(IntPredicate::IntULT, i, count); header_bx.cond_br(keep_going, body_bb, next_bb); let mut body_bx = Self::build(self.cx, body_bb); - let align = dest.align.restrict_for_offset(dest.layout.field(self.cx(), 0).size); - cg_elem - .val - .store(&mut body_bx, PlaceRef::new_sized_aligned(current, cg_elem.layout, align)); + let dest_elem = dest.project_index(&mut body_bx, i); + cg_elem.val.store(&mut body_bx, dest_elem); - let next = body_bx.inbounds_gep( - self.backend_type(cg_elem.layout), - current, - &[self.const_usize(1)], - ); + let next = body_bx.unchecked_uadd(i, self.const_usize(1)); body_bx.br(header_bb); - header_bx.add_incoming_to_phi(current, next, body_bb); + header_bx.add_incoming_to_phi(i, next, body_bb); *self = Self::build(self.cx, next_bb); } diff --git a/compiler/rustc_codegen_ssa/src/lib.rs b/compiler/rustc_codegen_ssa/src/lib.rs index 31854c7f4c4e..c26a7422fdd2 100644 --- a/compiler/rustc_codegen_ssa/src/lib.rs +++ b/compiler/rustc_codegen_ssa/src/lib.rs @@ -4,6 +4,7 @@ #![feature(if_let_guard)] #![feature(int_roundings)] #![feature(let_chains)] +#![feature(negative_impls)] #![feature(never_type)] #![feature(strict_provenance)] #![feature(try_blocks)] diff --git a/compiler/rustc_codegen_ssa/src/mir/block.rs b/compiler/rustc_codegen_ssa/src/mir/block.rs index 0cec560ba451..5e40b672866b 100644 --- a/compiler/rustc_codegen_ssa/src/mir/block.rs +++ b/compiler/rustc_codegen_ssa/src/mir/block.rs @@ -1729,7 +1729,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { IndirectOperand(tmp, index) => { let op = bx.load_operand(tmp); tmp.storage_dead(bx); - self.locals[index] = LocalRef::Operand(op); + self.overwrite_local(index, LocalRef::Operand(op)); self.debug_introduce_local(bx, index); } DirectOperand(index) => { @@ -1744,7 +1744,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { } else { OperandRef::from_immediate_or_packed_pair(bx, llval, ret_abi.layout) }; - self.locals[index] = LocalRef::Operand(op); + self.overwrite_local(index, LocalRef::Operand(op)); self.debug_introduce_local(bx, index); } } diff --git a/compiler/rustc_codegen_ssa/src/mir/debuginfo.rs b/compiler/rustc_codegen_ssa/src/mir/debuginfo.rs index 4f79c6a3d823..c6589a40392d 100644 --- a/compiler/rustc_codegen_ssa/src/mir/debuginfo.rs +++ b/compiler/rustc_codegen_ssa/src/mir/debuginfo.rs @@ -248,7 +248,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { } fn spill_operand_to_stack( - operand: &OperandRef<'tcx, Bx::Value>, + operand: OperandRef<'tcx, Bx::Value>, name: Option, bx: &mut Bx, ) -> PlaceRef<'tcx, Bx::Value> { @@ -375,7 +375,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { return; } - Self::spill_operand_to_stack(operand, name, bx) + Self::spill_operand_to_stack(*operand, name, bx) } LocalRef::Place(place) => *place, @@ -550,7 +550,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { if let Ok(operand) = self.eval_mir_constant_to_operand(bx, &c) { self.set_debug_loc(bx, var.source_info); let base = Self::spill_operand_to_stack( - &operand, + operand, Some(var.name.to_string()), bx, ); diff --git a/compiler/rustc_codegen_ssa/src/mir/locals.rs b/compiler/rustc_codegen_ssa/src/mir/locals.rs new file mode 100644 index 000000000000..da8bf5e7916a --- /dev/null +++ b/compiler/rustc_codegen_ssa/src/mir/locals.rs @@ -0,0 +1,75 @@ +//! Locals are in a private module as updating `LocalRef::Operand` has to +//! be careful wrt to subtyping. To deal with this we only allow updates by using +//! `FunctionCx::overwrite_local` which handles it automatically. +use crate::mir::{FunctionCx, LocalRef}; +use crate::traits::BuilderMethods; +use rustc_index::IndexVec; +use rustc_middle::mir; +use rustc_middle::ty::print::with_no_trimmed_paths; +use std::ops::{Index, IndexMut}; + +pub(super) struct Locals<'tcx, V> { + values: IndexVec>, +} + +impl<'tcx, V> Index for Locals<'tcx, V> { + type Output = LocalRef<'tcx, V>; + #[inline] + fn index(&self, index: mir::Local) -> &LocalRef<'tcx, V> { + &self.values[index] + } +} + +/// To mutate locals, use `FunctionCx::overwrite_local` instead. +impl<'tcx, V, Idx: ?Sized> !IndexMut for Locals<'tcx, V> {} + +impl<'tcx, V> Locals<'tcx, V> { + pub(super) fn empty() -> Locals<'tcx, V> { + Locals { values: IndexVec::default() } + } + + pub(super) fn indices(&self) -> impl DoubleEndedIterator + Clone + 'tcx { + self.values.indices() + } +} + +impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { + pub(super) fn initialize_locals(&mut self, values: Vec>) { + assert!(self.locals.values.is_empty()); + + for (local, value) in values.into_iter().enumerate() { + match value { + LocalRef::Place(_) | LocalRef::UnsizedPlace(_) | LocalRef::PendingOperand => (), + LocalRef::Operand(op) => { + let local = mir::Local::from_usize(local); + let expected_ty = self.monomorphize(self.mir.local_decls[local].ty); + assert_eq!(expected_ty, op.layout.ty, "unexpected initial operand type"); + } + } + + self.locals.values.push(value); + } + } + + pub(super) fn overwrite_local( + &mut self, + local: mir::Local, + mut value: LocalRef<'tcx, Bx::Value>, + ) { + match value { + LocalRef::Place(_) | LocalRef::UnsizedPlace(_) | LocalRef::PendingOperand => (), + LocalRef::Operand(ref mut op) => { + let local_ty = self.monomorphize(self.mir.local_decls[local].ty); + if local_ty != op.layout.ty { + // FIXME(#112651): This can be changed to an ICE afterwards. + debug!("updating type of operand due to subtyping"); + with_no_trimmed_paths!(debug!(?op.layout.ty)); + with_no_trimmed_paths!(debug!(?local_ty)); + op.layout.ty = local_ty; + } + } + }; + + self.locals.values[local] = value; + } +} diff --git a/compiler/rustc_codegen_ssa/src/mir/mod.rs b/compiler/rustc_codegen_ssa/src/mir/mod.rs index 2809ec2deb55..15b0e34b8e4d 100644 --- a/compiler/rustc_codegen_ssa/src/mir/mod.rs +++ b/compiler/rustc_codegen_ssa/src/mir/mod.rs @@ -1,21 +1,31 @@ use crate::base; use crate::traits::*; +use rustc_index::bit_set::BitSet; +use rustc_index::IndexVec; use rustc_middle::mir; use rustc_middle::mir::interpret::ErrorHandled; +use rustc_middle::mir::traversal; use rustc_middle::ty::layout::{FnAbiOf, HasTyCtxt, TyAndLayout}; use rustc_middle::ty::{self, Instance, Ty, TyCtxt, TypeFoldable, TypeVisitableExt}; use rustc_target::abi::call::{FnAbi, PassMode}; use std::iter; -use rustc_index::bit_set::BitSet; -use rustc_index::IndexVec; +mod analyze; +mod block; +pub mod constant; +pub mod coverageinfo; +pub mod debuginfo; +mod intrinsic; +mod locals; +pub mod operand; +pub mod place; +mod rvalue; +mod statement; use self::debuginfo::{FunctionDebugContext, PerLocalVarDebugInfo}; -use self::place::PlaceRef; -use rustc_middle::mir::traversal; - use self::operand::{OperandRef, OperandValue}; +use self::place::PlaceRef; // Used for tracking the state of generated basic blocks. enum CachedLlbb { @@ -91,7 +101,7 @@ pub struct FunctionCx<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> { /// /// Avoiding allocs can also be important for certain intrinsics, /// notably `expect`. - locals: IndexVec>, + locals: locals::Locals<'tcx, Bx::Value>, /// All `VarDebugInfo` from the MIR body, partitioned by `Local`. /// This is `None` if no var`#[non_exhaustive]`iable debuginfo/names are needed. @@ -192,7 +202,7 @@ pub fn codegen_mir<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>( cleanup_kinds, landing_pads: IndexVec::from_elem(None, &mir.basic_blocks), funclets: IndexVec::from_fn_n(|_| None, mir.basic_blocks.len()), - locals: IndexVec::new(), + locals: locals::Locals::empty(), debug_context, per_local_var_debug_info: None, caller_location: None, @@ -223,7 +233,7 @@ pub fn codegen_mir<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>( let memory_locals = analyze::non_ssa_locals(&fx); // Allocate variable and temp allocas - fx.locals = { + let local_values = { let args = arg_local_refs(&mut start_bx, &mut fx, &memory_locals); let mut allocate_local = |local| { @@ -256,6 +266,7 @@ pub fn codegen_mir<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>( .chain(mir.vars_and_temps_iter().map(allocate_local)) .collect() }; + fx.initialize_locals(local_values); // Apply debuginfo to the newly allocated locals. fx.debug_introduce_locals(&mut start_bx); @@ -289,14 +300,13 @@ fn arg_local_refs<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>( .enumerate() .map(|(arg_index, local)| { let arg_decl = &mir.local_decls[local]; + let arg_ty = fx.monomorphize(arg_decl.ty); if Some(local) == mir.spread_arg { // This argument (e.g., the last argument in the "rust-call" ABI) // is a tuple that was spread at the ABI level and now we have // to reconstruct it into a tuple local variable, from multiple // individual LLVM function arguments. - - let arg_ty = fx.monomorphize(arg_decl.ty); let ty::Tuple(tupled_arg_tys) = arg_ty.kind() else { bug!("spread argument isn't a tuple?!"); }; @@ -331,8 +341,6 @@ fn arg_local_refs<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>( } if fx.fn_abi.c_variadic && arg_index == fx.fn_abi.args.len() { - let arg_ty = fx.monomorphize(arg_decl.ty); - let va_list = PlaceRef::alloca(bx, bx.layout_of(arg_ty)); bx.va_start(va_list.llval); @@ -429,14 +437,3 @@ fn arg_local_refs<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>( args } - -mod analyze; -mod block; -pub mod constant; -pub mod coverageinfo; -pub mod debuginfo; -mod intrinsic; -pub mod operand; -pub mod place; -mod rvalue; -mod statement; diff --git a/compiler/rustc_codegen_ssa/src/mir/statement.rs b/compiler/rustc_codegen_ssa/src/mir/statement.rs index 3fd7397ad386..314d364c0c2a 100644 --- a/compiler/rustc_codegen_ssa/src/mir/statement.rs +++ b/compiler/rustc_codegen_ssa/src/mir/statement.rs @@ -20,7 +20,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { } LocalRef::PendingOperand => { let operand = self.codegen_rvalue_operand(bx, rvalue); - self.locals[index] = LocalRef::Operand(operand); + self.overwrite_local(index, LocalRef::Operand(operand)); self.debug_introduce_local(bx, index); } LocalRef::Operand(op) => { diff --git a/compiler/rustc_codegen_ssa/src/target_features.rs b/compiler/rustc_codegen_ssa/src/target_features.rs index c5976a65411f..6a3a31a0d60a 100644 --- a/compiler/rustc_codegen_ssa/src/target_features.rs +++ b/compiler/rustc_codegen_ssa/src/target_features.rs @@ -44,6 +44,7 @@ const ARM_ALLOWED_FEATURES: &[(&str, Option)] = &[ // #[target_feature]. ("thumb-mode", Some(sym::arm_target_feature)), ("thumb2", Some(sym::arm_target_feature)), + ("trustzone", Some(sym::arm_target_feature)), ("v5te", Some(sym::arm_target_feature)), ("v6", Some(sym::arm_target_feature)), ("v6k", Some(sym::arm_target_feature)), @@ -53,6 +54,7 @@ const ARM_ALLOWED_FEATURES: &[(&str, Option)] = &[ ("vfp2", Some(sym::arm_target_feature)), ("vfp3", Some(sym::arm_target_feature)), ("vfp4", Some(sym::arm_target_feature)), + ("virtualization", Some(sym::arm_target_feature)), // tidy-alphabetical-end ]; diff --git a/compiler/rustc_const_eval/src/const_eval/eval_queries.rs b/compiler/rustc_const_eval/src/const_eval/eval_queries.rs index 8b8e8ff58e90..417ab78fd548 100644 --- a/compiler/rustc_const_eval/src/const_eval/eval_queries.rs +++ b/compiler/rustc_const_eval/src/const_eval/eval_queries.rs @@ -14,7 +14,7 @@ use rustc_middle::ty::{self, TyCtxt}; use rustc_span::source_map::Span; use rustc_target::abi::{self, Abi}; -use super::{CompileTimeEvalContext, CompileTimeInterpreter}; +use super::{CanAccessStatics, CompileTimeEvalContext, CompileTimeInterpreter}; use crate::errors; use crate::interpret::eval_nullary_intrinsic; use crate::interpret::{ @@ -93,7 +93,7 @@ pub(super) fn mk_eval_cx<'mir, 'tcx>( tcx: TyCtxt<'tcx>, root_span: Span, param_env: ty::ParamEnv<'tcx>, - can_access_statics: bool, + can_access_statics: CanAccessStatics, ) -> CompileTimeEvalContext<'mir, 'tcx> { debug!("mk_eval_cx: {:?}", param_env); InterpCx::new( @@ -207,7 +207,7 @@ pub(crate) fn turn_into_const_value<'tcx>( tcx, tcx.def_span(key.value.instance.def_id()), key.param_env, - /*can_access_statics:*/ is_static, + CanAccessStatics::from(is_static), ); let mplace = ecx.raw_const_to_mplace(constant).expect( @@ -309,7 +309,7 @@ pub fn eval_to_allocation_raw_provider<'tcx>( // Statics (and promoteds inside statics) may access other statics, because unlike consts // they do not have to behave "as if" they were evaluated at runtime. CompileTimeInterpreter::new( - /*can_access_statics:*/ is_static, + CanAccessStatics::from(is_static), if tcx.sess.opts.unstable_opts.extra_const_ub_checks { CheckAlignment::Error } else { diff --git a/compiler/rustc_const_eval/src/const_eval/machine.rs b/compiler/rustc_const_eval/src/const_eval/machine.rs index 7391f5670400..f9f645af41f1 100644 --- a/compiler/rustc_const_eval/src/const_eval/machine.rs +++ b/compiler/rustc_const_eval/src/const_eval/machine.rs @@ -57,7 +57,7 @@ pub struct CompileTimeInterpreter<'mir, 'tcx> { /// * Interning makes everything outside of statics immutable. /// * Pointers to allocations inside of statics can never leak outside, to a non-static global. /// This boolean here controls the second part. - pub(super) can_access_statics: bool, + pub(super) can_access_statics: CanAccessStatics, /// Whether to check alignment during evaluation. pub(super) check_alignment: CheckAlignment, @@ -83,8 +83,23 @@ impl CheckAlignment { } } +#[derive(Copy, Clone, PartialEq)] +pub(crate) enum CanAccessStatics { + No, + Yes, +} + +impl From for CanAccessStatics { + fn from(value: bool) -> Self { + if value { Self::Yes } else { Self::No } + } +} + impl<'mir, 'tcx> CompileTimeInterpreter<'mir, 'tcx> { - pub(crate) fn new(can_access_statics: bool, check_alignment: CheckAlignment) -> Self { + pub(crate) fn new( + can_access_statics: CanAccessStatics, + check_alignment: CheckAlignment, + ) -> Self { CompileTimeInterpreter { num_evaluated_steps: 0, stack: Vec::new(), @@ -699,7 +714,7 @@ impl<'mir, 'tcx> interpret::Machine<'mir, 'tcx> for CompileTimeInterpreter<'mir, } } else { // Read access. These are usually allowed, with some exceptions. - if machine.can_access_statics { + if machine.can_access_statics == CanAccessStatics::Yes { // Machine configuration allows us read from anything (e.g., `static` initializer). Ok(()) } else if static_def_id.is_some() { diff --git a/compiler/rustc_const_eval/src/const_eval/mod.rs b/compiler/rustc_const_eval/src/const_eval/mod.rs index 6e462d3a1e98..b9ab0a4b7c8f 100644 --- a/compiler/rustc_const_eval/src/const_eval/mod.rs +++ b/compiler/rustc_const_eval/src/const_eval/mod.rs @@ -26,7 +26,7 @@ pub(crate) fn const_caller_location( (file, line, col): (Symbol, u32, u32), ) -> ConstValue<'_> { trace!("const_caller_location: {}:{}:{}", file, line, col); - let mut ecx = mk_eval_cx(tcx, DUMMY_SP, ty::ParamEnv::reveal_all(), false); + let mut ecx = mk_eval_cx(tcx, DUMMY_SP, ty::ParamEnv::reveal_all(), CanAccessStatics::No); let loc_place = ecx.alloc_caller_location(file, line, col); if intern_const_alloc_recursive(&mut ecx, InternKind::Constant, &loc_place).is_err() { @@ -55,10 +55,12 @@ pub(crate) fn eval_to_valtree<'tcx>( // FIXME Need to provide a span to `eval_to_valtree` let ecx = mk_eval_cx( - tcx, DUMMY_SP, param_env, + tcx, + DUMMY_SP, + param_env, // It is absolutely crucial for soundness that // we do not read from static items or other mutable memory. - false, + CanAccessStatics::No, ); let place = ecx.raw_const_to_mplace(const_alloc).unwrap(); debug!(?place); @@ -91,7 +93,7 @@ pub(crate) fn try_destructure_mir_constant<'tcx>( val: mir::ConstantKind<'tcx>, ) -> InterpResult<'tcx, mir::DestructuredConstant<'tcx>> { trace!("destructure_mir_constant: {:?}", val); - let ecx = mk_eval_cx(tcx, DUMMY_SP, param_env, false); + let ecx = mk_eval_cx(tcx, DUMMY_SP, param_env, CanAccessStatics::No); let op = ecx.eval_mir_constant(&val, None, None)?; // We go to `usize` as we cannot allocate anything bigger anyway. diff --git a/compiler/rustc_const_eval/src/const_eval/valtrees.rs b/compiler/rustc_const_eval/src/const_eval/valtrees.rs index b10f2e9f862d..e574df27694f 100644 --- a/compiler/rustc_const_eval/src/const_eval/valtrees.rs +++ b/compiler/rustc_const_eval/src/const_eval/valtrees.rs @@ -1,6 +1,7 @@ use super::eval_queries::{mk_eval_cx, op_to_const}; use super::machine::CompileTimeEvalContext; use super::{ValTreeCreationError, ValTreeCreationResult, VALTREE_MAX_NODES}; +use crate::const_eval::CanAccessStatics; use crate::interpret::{ intern_const_alloc_recursive, ConstValue, ImmTy, Immediate, InternKind, MemPlaceMeta, MemoryKind, PlaceTy, Scalar, @@ -263,7 +264,11 @@ pub fn valtree_to_const_value<'tcx>( // FIXME Does this need an example? let (param_env, ty) = param_env_ty.into_parts(); - let mut ecx = mk_eval_cx(tcx, DUMMY_SP, param_env, false); + let mut ecx: crate::interpret::InterpCx< + '_, + '_, + crate::const_eval::CompileTimeInterpreter<'_, '_>, + > = mk_eval_cx(tcx, DUMMY_SP, param_env, CanAccessStatics::No); match ty.kind() { ty::FnDef(..) => { diff --git a/compiler/rustc_const_eval/src/transform/check_consts/check.rs b/compiler/rustc_const_eval/src/transform/check_consts/check.rs index 33c79ad7e553..28cf9daf1c11 100644 --- a/compiler/rustc_const_eval/src/transform/check_consts/check.rs +++ b/compiler/rustc_const_eval/src/transform/check_consts/check.rs @@ -612,30 +612,28 @@ impl<'tcx> Visitor<'tcx> for Checker<'_, 'tcx> { } fn visit_projection_elem( &mut self, - place_local: Local, - proj_base: &[PlaceElem<'tcx>], + place_ref: PlaceRef<'tcx>, elem: PlaceElem<'tcx>, context: PlaceContext, location: Location, ) { trace!( - "visit_projection_elem: place_local={:?} proj_base={:?} elem={:?} \ + "visit_projection_elem: place_ref={:?} elem={:?} \ context={:?} location={:?}", - place_local, - proj_base, + place_ref, elem, context, location, ); - self.super_projection_elem(place_local, proj_base, elem, context, location); + self.super_projection_elem(place_ref, elem, context, location); match elem { ProjectionElem::Deref => { - let base_ty = Place::ty_from(place_local, proj_base, self.body, self.tcx).ty; + let base_ty = place_ref.ty(self.body, self.tcx).ty; if base_ty.is_unsafe_ptr() { - if proj_base.is_empty() { - let decl = &self.body.local_decls[place_local]; + if place_ref.projection.is_empty() { + let decl = &self.body.local_decls[place_ref.local]; if let LocalInfo::StaticRef { def_id, .. } = *decl.local_info() { let span = decl.source_info.span; self.check_static(def_id, span); diff --git a/compiler/rustc_const_eval/src/transform/validate.rs b/compiler/rustc_const_eval/src/transform/validate.rs index f197541da5be..7ed73a3f6fe6 100644 --- a/compiler/rustc_const_eval/src/transform/validate.rs +++ b/compiler/rustc_const_eval/src/transform/validate.rs @@ -318,8 +318,7 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> { fn visit_projection_elem( &mut self, - local: Local, - proj_base: &[PlaceElem<'tcx>], + place_ref: PlaceRef<'tcx>, elem: PlaceElem<'tcx>, context: PlaceContext, location: Location, @@ -334,7 +333,7 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> { ProjectionElem::Deref if self.mir_phase >= MirPhase::Runtime(RuntimePhase::PostCleanup) => { - let base_ty = Place::ty_from(local, proj_base, &self.body.local_decls, self.tcx).ty; + let base_ty = place_ref.ty(&self.body.local_decls, self.tcx).ty; if base_ty.is_box() { self.fail( @@ -344,8 +343,7 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> { } } ProjectionElem::Field(f, ty) => { - let parent = Place { local, projection: self.tcx.mk_place_elems(proj_base) }; - let parent_ty = parent.ty(&self.body.local_decls, self.tcx); + let parent_ty = place_ref.ty(&self.body.local_decls, self.tcx); let fail_out_of_bounds = |this: &Self, location| { this.fail(location, format!("Out of bounds field {:?} for {:?}", f, parent_ty)); }; @@ -355,7 +353,7 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> { location, format!( "Field projection `{:?}.{:?}` specified type `{:?}`, but actual type is `{:?}`", - parent, f, ty, f_ty + place_ref, f, ty, f_ty ) ) } @@ -434,7 +432,7 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> { } _ => {} } - self.super_projection_elem(local, proj_base, elem, context, location); + self.super_projection_elem(place_ref, elem, context, location); } fn visit_var_debug_info(&mut self, debuginfo: &VarDebugInfo<'tcx>) { diff --git a/compiler/rustc_const_eval/src/util/check_validity_requirement.rs b/compiler/rustc_const_eval/src/util/check_validity_requirement.rs index 29063261adab..f56798d4c323 100644 --- a/compiler/rustc_const_eval/src/util/check_validity_requirement.rs +++ b/compiler/rustc_const_eval/src/util/check_validity_requirement.rs @@ -2,7 +2,7 @@ use rustc_middle::ty::layout::{LayoutCx, LayoutError, LayoutOf, TyAndLayout, Val use rustc_middle::ty::{ParamEnv, ParamEnvAnd, Ty, TyCtxt}; use rustc_target::abi::{Abi, FieldsShape, Scalar, Variants}; -use crate::const_eval::{CheckAlignment, CompileTimeInterpreter}; +use crate::const_eval::{CanAccessStatics, CheckAlignment, CompileTimeInterpreter}; use crate::interpret::{InterpCx, MemoryKind, OpTy}; /// Determines if this type permits "raw" initialization by just transmuting some memory into an @@ -44,8 +44,7 @@ fn might_permit_raw_init_strict<'tcx>( tcx: TyCtxt<'tcx>, kind: ValidityRequirement, ) -> Result> { - let machine = - CompileTimeInterpreter::new(/*can_access_statics:*/ false, CheckAlignment::Error); + let machine = CompileTimeInterpreter::new(CanAccessStatics::No, CheckAlignment::Error); let mut cx = InterpCx::new(tcx, rustc_span::DUMMY_SP, ParamEnv::reveal_all(), machine); diff --git a/compiler/rustc_driver_impl/src/args.rs b/compiler/rustc_driver_impl/src/args.rs index eb92ccc17b20..654d7636da20 100644 --- a/compiler/rustc_driver_impl/src/args.rs +++ b/compiler/rustc_driver_impl/src/args.rs @@ -3,6 +3,8 @@ use std::fmt; use std::fs; use std::io; +use rustc_session::EarlyErrorHandler; + fn arg_expand(arg: String) -> Result, Error> { if let Some(path) = arg.strip_prefix('@') { let file = match fs::read_to_string(path) { @@ -21,15 +23,12 @@ fn arg_expand(arg: String) -> Result, Error> { /// **Note:** This function doesn't interpret argument 0 in any special way. /// If this function is intended to be used with command line arguments, /// `argv[0]` must be removed prior to calling it manually. -pub fn arg_expand_all(at_args: &[String]) -> Vec { +pub fn arg_expand_all(handler: &EarlyErrorHandler, at_args: &[String]) -> Vec { let mut args = Vec::new(); for arg in at_args { match arg_expand(arg.clone()) { Ok(arg) => args.extend(arg), - Err(err) => rustc_session::early_error( - rustc_session::config::ErrorOutputType::default(), - format!("Failed to load argument file: {err}"), - ), + Err(err) => handler.early_error(format!("Failed to load argument file: {err}")), } } args diff --git a/compiler/rustc_driver_impl/src/lib.rs b/compiler/rustc_driver_impl/src/lib.rs index 984cc1557a49..4b4573ec2eba 100644 --- a/compiler/rustc_driver_impl/src/lib.rs +++ b/compiler/rustc_driver_impl/src/lib.rs @@ -40,8 +40,7 @@ use rustc_session::config::{ use rustc_session::cstore::MetadataLoader; use rustc_session::getopts::{self, Matches}; use rustc_session::lint::{Lint, LintId}; -use rustc_session::{config, Session}; -use rustc_session::{early_error, early_error_no_abort, early_warn}; +use rustc_session::{config, EarlyErrorHandler, Session}; use rustc_span::source_map::{FileLoader, FileName}; use rustc_span::symbol::sym; use rustc_target::json::ToJson; @@ -174,6 +173,7 @@ pub trait Callbacks { /// continue the compilation afterwards (defaults to `Compilation::Continue`) fn after_analysis<'tcx>( &mut self, + _handler: &EarlyErrorHandler, _compiler: &interface::Compiler, _queries: &'tcx Queries<'tcx>, ) -> Compilation { @@ -260,6 +260,8 @@ fn run_compiler( Box Box + Send>, >, ) -> interface::Result<()> { + let mut early_error_handler = EarlyErrorHandler::new(ErrorOutputType::default()); + // Throw away the first argument, the name of the binary. // In case of at_args being empty, as might be the case by // passing empty argument array to execve under some platforms, @@ -270,22 +272,22 @@ fn run_compiler( // the compiler with @empty_file as argv[0] and no more arguments. let at_args = at_args.get(1..).unwrap_or_default(); - let args = args::arg_expand_all(at_args); + let args = args::arg_expand_all(&early_error_handler, at_args); - let Some(matches) = handle_options(&args) else { return Ok(()) }; + let Some(matches) = handle_options(&early_error_handler, &args) else { return Ok(()) }; - let sopts = config::build_session_options(&matches); + let sopts = config::build_session_options(&mut early_error_handler, &matches); // Set parallel mode before thread pool creation, which will create `Lock`s. interface::set_thread_safe_mode(&sopts.unstable_opts); if let Some(ref code) = matches.opt_str("explain") { - handle_explain(diagnostics_registry(), code, sopts.error_format); + handle_explain(&early_error_handler, diagnostics_registry(), code); return Ok(()); } - let cfg = interface::parse_cfgspecs(matches.opt_strs("cfg")); - let check_cfg = interface::parse_check_cfg(matches.opt_strs("check-cfg")); + let cfg = interface::parse_cfgspecs(&early_error_handler, matches.opt_strs("cfg")); + let check_cfg = interface::parse_check_cfg(&early_error_handler, matches.opt_strs("check-cfg")); let (odir, ofile) = make_output(&matches); let mut config = interface::Config { opts: sopts, @@ -304,7 +306,7 @@ fn run_compiler( registry: diagnostics_registry(), }; - match make_input(config.opts.error_format, &matches.free) { + match make_input(&early_error_handler, &matches.free) { Err(reported) => return Err(reported), Ok(Some(input)) => { config.input = input; @@ -314,8 +316,13 @@ fn run_compiler( Ok(None) => match matches.free.len() { 0 => { callbacks.config(&mut config); + + early_error_handler.abort_if_errors(); + interface::run_compiler(config, |compiler| { let sopts = &compiler.session().opts; + let handler = EarlyErrorHandler::new(sopts.error_format); + if sopts.describe_lints { let mut lint_store = rustc_lint::new_lint_store(compiler.session().enable_internal_lints()); @@ -329,31 +336,38 @@ fn run_compiler( describe_lints(compiler.session(), &lint_store, registered_lints); return; } - let should_stop = - print_crate_info(&**compiler.codegen_backend(), compiler.session(), false); + let should_stop = print_crate_info( + &handler, + &**compiler.codegen_backend(), + compiler.session(), + false, + ); if should_stop == Compilation::Stop { return; } - early_error(sopts.error_format, "no input filename given") + handler.early_error("no input filename given") }); return Ok(()); } 1 => panic!("make_input should have provided valid inputs"), - _ => early_error( - config.opts.error_format, - format!( - "multiple input filenames provided (first two filenames are `{}` and `{}`)", - matches.free[0], matches.free[1], - ), - ), + _ => early_error_handler.early_error(format!( + "multiple input filenames provided (first two filenames are `{}` and `{}`)", + matches.free[0], matches.free[1], + )), }, }; + early_error_handler.abort_if_errors(); + interface::run_compiler(config, |compiler| { let sess = compiler.session(); - let should_stop = print_crate_info(&**compiler.codegen_backend(), sess, true) - .and_then(|| list_metadata(sess, &*compiler.codegen_backend().metadata_loader())) + let handler = EarlyErrorHandler::new(sess.opts.error_format); + + let should_stop = print_crate_info(&handler, &**compiler.codegen_backend(), sess, true) + .and_then(|| { + list_metadata(&handler, sess, &*compiler.codegen_backend().metadata_loader()) + }) .and_then(|| try_process_rlink(sess, compiler)); if should_stop == Compilation::Stop { @@ -421,7 +435,7 @@ fn run_compiler( queries.global_ctxt()?.enter(|tcx| tcx.analysis(()))?; - if callbacks.after_analysis(compiler, queries) == Compilation::Stop { + if callbacks.after_analysis(&handler, compiler, queries) == Compilation::Stop { return early_exit(); } @@ -475,7 +489,7 @@ fn make_output(matches: &getopts::Matches) -> (Option, Option Result, ErrorGuaranteed> { if free_matches.len() == 1 { @@ -485,8 +499,7 @@ fn make_input( if io::stdin().read_to_string(&mut src).is_err() { // Immediately stop compilation if there was an issue reading // the input (for example if the input stream is not UTF-8). - let reported = early_error_no_abort( - error_format, + let reported = handler.early_error_no_abort( "couldn't read from stdin, as it did not contain valid UTF-8", ); return Err(reported); @@ -527,7 +540,7 @@ impl Compilation { } } -fn handle_explain(registry: Registry, code: &str, output: ErrorOutputType) { +fn handle_explain(handler: &EarlyErrorHandler, registry: Registry, code: &str) { let upper_cased_code = code.to_ascii_uppercase(); let normalised = if upper_cased_code.starts_with('E') { upper_cased_code } else { format!("E{code:0>4}") }; @@ -557,7 +570,7 @@ fn handle_explain(registry: Registry, code: &str, output: ErrorOutputType) { } } Err(InvalidErrorCode) => { - early_error(output, format!("{code} is not a valid error code")); + handler.early_error(format!("{code} is not a valid error code")); } } } @@ -636,7 +649,11 @@ pub fn try_process_rlink(sess: &Session, compiler: &interface::Compiler) -> Comp } } -pub fn list_metadata(sess: &Session, metadata_loader: &dyn MetadataLoader) -> Compilation { +pub fn list_metadata( + handler: &EarlyErrorHandler, + sess: &Session, + metadata_loader: &dyn MetadataLoader, +) -> Compilation { if sess.opts.unstable_opts.ls { match sess.io.input { Input::File(ref ifile) => { @@ -646,7 +663,7 @@ pub fn list_metadata(sess: &Session, metadata_loader: &dyn MetadataLoader) -> Co safe_println!("{}", String::from_utf8(v).unwrap()); } Input::Str { .. } => { - early_error(ErrorOutputType::default(), "cannot list metadata for stdin"); + handler.early_error("cannot list metadata for stdin"); } } return Compilation::Stop; @@ -656,6 +673,7 @@ pub fn list_metadata(sess: &Session, metadata_loader: &dyn MetadataLoader) -> Co } fn print_crate_info( + handler: &EarlyErrorHandler, codegen_backend: &dyn CodegenBackend, sess: &Session, parse_attrs: bool, @@ -787,10 +805,8 @@ fn print_crate_info( .expect("unknown Apple target OS") ) } else { - early_error( - ErrorOutputType::default(), - "only Apple targets currently support deployment version info", - ) + handler + .early_error("only Apple targets currently support deployment version info") } } } @@ -801,11 +817,12 @@ fn print_crate_info( /// Prints version information /// /// NOTE: this is a macro to support drivers built at a different time than the main `rustc_driver` crate. -pub macro version($binary: literal, $matches: expr) { +pub macro version($handler: expr, $binary: literal, $matches: expr) { fn unw(x: Option<&str>) -> &str { x.unwrap_or("unknown") } $crate::version_at_macro_invocation( + $handler, $binary, $matches, unw(option_env!("CFG_VERSION")), @@ -817,6 +834,7 @@ pub macro version($binary: literal, $matches: expr) { #[doc(hidden)] // use the macro instead pub fn version_at_macro_invocation( + handler: &EarlyErrorHandler, binary: &str, matches: &getopts::Matches, version: &str, @@ -837,7 +855,7 @@ pub fn version_at_macro_invocation( let debug_flags = matches.opt_strs("Z"); let backend_name = debug_flags.iter().find_map(|x| x.strip_prefix("codegen-backend=")); - get_codegen_backend(&None, backend_name).print_version(); + get_codegen_backend(handler, &None, backend_name).print_version(); } } @@ -1014,7 +1032,7 @@ Available lint options: /// Show help for flag categories shared between rustdoc and rustc. /// /// Returns whether a help option was printed. -pub fn describe_flag_categories(matches: &Matches) -> bool { +pub fn describe_flag_categories(handler: &EarlyErrorHandler, matches: &Matches) -> bool { // Handle the special case of -Wall. let wall = matches.opt_strs("W"); if wall.iter().any(|x| *x == "all") { @@ -1036,15 +1054,12 @@ pub fn describe_flag_categories(matches: &Matches) -> bool { } if cg_flags.iter().any(|x| *x == "no-stack-check") { - early_warn( - ErrorOutputType::default(), - "the --no-stack-check flag is deprecated and does nothing", - ); + handler.early_warn("the --no-stack-check flag is deprecated and does nothing"); } if cg_flags.iter().any(|x| *x == "passes=list") { let backend_name = debug_flags.iter().find_map(|x| x.strip_prefix("codegen-backend=")); - get_codegen_backend(&None, backend_name).print_passes(); + get_codegen_backend(handler, &None, backend_name).print_passes(); return true; } @@ -1101,7 +1116,7 @@ fn print_flag_list( /// /// So with all that in mind, the comments below have some more detail about the /// contortions done here to get things to work out correctly. -pub fn handle_options(args: &[String]) -> Option { +pub fn handle_options(handler: &EarlyErrorHandler, args: &[String]) -> Option { if args.is_empty() { // user did not write `-v` nor `-Z unstable-options`, so do not // include that extra information. @@ -1127,7 +1142,7 @@ pub fn handle_options(args: &[String]) -> Option { .map(|(flag, _)| format!("{e}. Did you mean `-{flag} {opt}`?")), _ => None, }; - early_error(ErrorOutputType::default(), msg.unwrap_or_else(|| e.to_string())); + handler.early_error(msg.unwrap_or_else(|| e.to_string())); }); // For all options we just parsed, we check a few aspects: @@ -1141,7 +1156,7 @@ pub fn handle_options(args: &[String]) -> Option { // we're good to go. // * Otherwise, if we're an unstable option then we generate an error // (unstable option being used on stable) - nightly_options::check_nightly_options(&matches, &config::rustc_optgroups()); + nightly_options::check_nightly_options(handler, &matches, &config::rustc_optgroups()); if matches.opt_present("h") || matches.opt_present("help") { // Only show unstable options in --help if we accept unstable options. @@ -1151,12 +1166,12 @@ pub fn handle_options(args: &[String]) -> Option { return None; } - if describe_flag_categories(&matches) { + if describe_flag_categories(handler, &matches) { return None; } if matches.opt_present("version") { - version!("rustc", &matches); + version!(handler, "rustc", &matches); return None; } @@ -1276,7 +1291,8 @@ pub fn install_ice_hook(bug_report_url: &'static str, extra_info: fn(&Handler)) if let Some(msg) = info.payload().downcast_ref::() { if msg.starts_with("failed printing to stdout: ") && msg.ends_with("(os error 232)") { // the error code is already going to be reported when the panic unwinds up the stack - let _ = early_error_no_abort(ErrorOutputType::default(), msg.clone()); + let handler = EarlyErrorHandler::new(ErrorOutputType::default()); + let _ = handler.early_error_no_abort(msg.clone()); return; } }; @@ -1359,16 +1375,16 @@ pub fn report_ice(info: &panic::PanicInfo<'_>, bug_report_url: &str, extra_info: /// This allows tools to enable rust logging without having to magically match rustc's /// tracing crate version. -pub fn init_rustc_env_logger() { - init_env_logger("RUSTC_LOG"); +pub fn init_rustc_env_logger(handler: &EarlyErrorHandler) { + init_env_logger(handler, "RUSTC_LOG"); } /// This allows tools to enable rust logging without having to magically match rustc's /// tracing crate version. In contrast to `init_rustc_env_logger` it allows you to choose an env var /// other than `RUSTC_LOG`. -pub fn init_env_logger(env: &str) { +pub fn init_env_logger(handler: &EarlyErrorHandler, env: &str) { if let Err(error) = rustc_log::init_env_logger(env) { - early_error(ErrorOutputType::default(), error.to_string()); + handler.early_error(error.to_string()); } } @@ -1424,7 +1440,10 @@ mod signal_handler { pub fn main() -> ! { let start_time = Instant::now(); let start_rss = get_resident_set_size(); - init_rustc_env_logger(); + + let handler = EarlyErrorHandler::new(ErrorOutputType::default()); + + init_rustc_env_logger(&handler); signal_handler::install(); let mut callbacks = TimePassesCallbacks::default(); install_ice_hook(DEFAULT_BUG_REPORT_URL, |_| ()); @@ -1433,10 +1452,7 @@ pub fn main() -> ! { .enumerate() .map(|(i, arg)| { arg.into_string().unwrap_or_else(|arg| { - early_error( - ErrorOutputType::default(), - format!("argument {i} is not valid Unicode: {arg:?}"), - ) + handler.early_error(format!("argument {i} is not valid Unicode: {arg:?}")) }) }) .collect::>(); diff --git a/compiler/rustc_expand/src/config.rs b/compiler/rustc_expand/src/config.rs index bcfa5313bde3..3e43eae006fd 100644 --- a/compiler/rustc_expand/src/config.rs +++ b/compiler/rustc_expand/src/config.rs @@ -445,7 +445,7 @@ impl<'a> StripUnconfigured<'a> { /// If attributes are not allowed on expressions, emit an error for `attr` #[instrument(level = "trace", skip(self))] pub(crate) fn maybe_emit_expr_attr_err(&self, attr: &Attribute) { - if !self.features.map_or(true, |features| features.stmt_expr_attributes) { + if self.features.is_some_and(|features| !features.stmt_expr_attributes) { let mut err = feature_err( &self.sess.parse_sess, sym::stmt_expr_attributes, diff --git a/compiler/rustc_fluent_macro/src/fluent.rs b/compiler/rustc_fluent_macro/src/fluent.rs index 9dffc9a76454..56e23ac27752 100644 --- a/compiler/rustc_fluent_macro/src/fluent.rs +++ b/compiler/rustc_fluent_macro/src/fluent.rs @@ -179,7 +179,8 @@ pub(crate) fn fluent_messages(input: proc_macro::TokenStream) -> proc_macro::Tok let mut previous_defns = HashMap::new(); let mut message_refs = Vec::new(); for entry in resource.entries() { - if let Entry::Message(Message { id: Identifier { name }, attributes, value, .. }) = entry { + if let Entry::Message(msg) = entry { + let Message { id: Identifier { name }, attributes, value, .. } = msg; let _ = previous_defns.entry(name.to_string()).or_insert(resource_span); if name.contains('-') { Diagnostic::spanned( @@ -229,9 +230,10 @@ pub(crate) fn fluent_messages(input: proc_macro::TokenStream) -> proc_macro::Tok continue; } - let msg = format!("Constant referring to Fluent message `{name}` from `{crate_name}`"); + let docstr = + format!("Constant referring to Fluent message `{name}` from `{crate_name}`"); constants.extend(quote! { - #[doc = #msg] + #[doc = #docstr] pub const #snake_name: crate::DiagnosticMessage = crate::DiagnosticMessage::FluentIdentifier( std::borrow::Cow::Borrowed(#name), @@ -269,6 +271,15 @@ pub(crate) fn fluent_messages(input: proc_macro::TokenStream) -> proc_macro::Tok ); }); } + + // Record variables referenced by these messages so we can produce + // tests in the derive diagnostics to validate them. + let ident = quote::format_ident!("{snake_name}_refs"); + let vrefs = variable_references(msg); + constants.extend(quote! { + #[cfg(test)] + pub const #ident: &[&str] = &[#(#vrefs),*]; + }) } } @@ -334,3 +345,28 @@ pub(crate) fn fluent_messages(input: proc_macro::TokenStream) -> proc_macro::Tok } .into() } + +fn variable_references<'a>(msg: &Message<&'a str>) -> Vec<&'a str> { + let mut refs = vec![]; + if let Some(Pattern { elements }) = &msg.value { + for elt in elements { + if let PatternElement::Placeable { + expression: Expression::Inline(InlineExpression::VariableReference { id }), + } = elt + { + refs.push(id.name); + } + } + } + for attr in &msg.attributes { + for elt in &attr.value.elements { + if let PatternElement::Placeable { + expression: Expression::Inline(InlineExpression::VariableReference { id }), + } = elt + { + refs.push(id.name); + } + } + } + refs +} diff --git a/compiler/rustc_hir/src/hir.rs b/compiler/rustc_hir/src/hir.rs index 5e5001bc8b45..591831b59a1a 100644 --- a/compiler/rustc_hir/src/hir.rs +++ b/compiler/rustc_hir/src/hir.rs @@ -1719,6 +1719,7 @@ impl Expr<'_> { ExprKind::Break(..) => ExprPrecedence::Break, ExprKind::Continue(..) => ExprPrecedence::Continue, ExprKind::Ret(..) => ExprPrecedence::Ret, + ExprKind::Become(..) => ExprPrecedence::Become, ExprKind::InlineAsm(..) => ExprPrecedence::InlineAsm, ExprKind::OffsetOf(..) => ExprPrecedence::OffsetOf, ExprKind::Struct(..) => ExprPrecedence::Struct, @@ -1776,6 +1777,7 @@ impl Expr<'_> { | ExprKind::Break(..) | ExprKind::Continue(..) | ExprKind::Ret(..) + | ExprKind::Become(..) | ExprKind::Let(..) | ExprKind::Loop(..) | ExprKind::Assign(..) @@ -1866,6 +1868,7 @@ impl Expr<'_> { | ExprKind::Break(..) | ExprKind::Continue(..) | ExprKind::Ret(..) + | ExprKind::Become(..) | ExprKind::Let(..) | ExprKind::Loop(..) | ExprKind::Assign(..) @@ -2025,6 +2028,8 @@ pub enum ExprKind<'hir> { Continue(Destination), /// A `return`, with an optional value to be returned. Ret(Option<&'hir Expr<'hir>>), + /// A `become`, with the value to be returned. + Become(&'hir Expr<'hir>), /// Inline assembly (from `asm!`), with its outputs and inputs. InlineAsm(&'hir InlineAsm<'hir>), diff --git a/compiler/rustc_hir/src/intravisit.rs b/compiler/rustc_hir/src/intravisit.rs index f84c814bd927..1886a91bda83 100644 --- a/compiler/rustc_hir/src/intravisit.rs +++ b/compiler/rustc_hir/src/intravisit.rs @@ -791,6 +791,7 @@ pub fn walk_expr<'v, V: Visitor<'v>>(visitor: &mut V, expression: &'v Expr<'v>) ExprKind::Ret(ref optional_expression) => { walk_list!(visitor, visit_expr, optional_expression); } + ExprKind::Become(ref expr) => visitor.visit_expr(expr), ExprKind::InlineAsm(ref asm) => { visitor.visit_inline_asm(asm, expression.hir_id); } diff --git a/compiler/rustc_hir_analysis/messages.ftl b/compiler/rustc_hir_analysis/messages.ftl index cd6cf36baa44..edc6bcacc683 100644 --- a/compiler/rustc_hir_analysis/messages.ftl +++ b/compiler/rustc_hir_analysis/messages.ftl @@ -137,7 +137,7 @@ hir_analysis_missing_trait_item_suggestion = implement the missing item: `{$snip hir_analysis_missing_trait_item_unstable = not all trait items implemented, missing: `{$missing_item_name}` .note = default implementation of `{$missing_item_name}` is unstable - .some_note = use of unstable library feature '{$feature}': {$r} + .some_note = use of unstable library feature '{$feature}': {$reason} .none_note = use of unstable library feature '{$feature}' hir_analysis_missing_type_params = diff --git a/compiler/rustc_hir_analysis/src/astconv/mod.rs b/compiler/rustc_hir_analysis/src/astconv/mod.rs index 41a6d94b2788..6a59aa36ec7d 100644 --- a/compiler/rustc_hir_analysis/src/astconv/mod.rs +++ b/compiler/rustc_hir_analysis/src/astconv/mod.rs @@ -945,40 +945,30 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { let mut trait_bounds = vec![]; let mut projection_bounds = vec![]; - for (clause, span) in bounds.clauses() { - let pred: ty::Predicate<'tcx> = clause.as_predicate(); + for (pred, span) in bounds.clauses() { let bound_pred = pred.kind(); match bound_pred.skip_binder() { - ty::PredicateKind::Clause(clause) => match clause { - ty::ClauseKind::Trait(trait_pred) => { - assert_eq!(trait_pred.polarity, ty::ImplPolarity::Positive); - trait_bounds.push(( - bound_pred.rebind(trait_pred.trait_ref), - span, - trait_pred.constness, - )); - } - ty::ClauseKind::Projection(proj) => { - projection_bounds.push((bound_pred.rebind(proj), span)); - } - ty::ClauseKind::TypeOutlives(_) => { - // Do nothing, we deal with regions separately - } - ty::ClauseKind::RegionOutlives(_) - | ty::ClauseKind::ConstArgHasType(..) - | ty::ClauseKind::WellFormed(_) - | ty::ClauseKind::ConstEvaluatable(_) => { - bug!() - } - }, - ty::PredicateKind::AliasRelate(..) - | ty::PredicateKind::ObjectSafe(_) - | ty::PredicateKind::ClosureKind(_, _, _) - | ty::PredicateKind::Subtype(_) - | ty::PredicateKind::Coerce(_) - | ty::PredicateKind::ConstEquate(_, _) - | ty::PredicateKind::TypeWellFormedFromEnv(_) - | ty::PredicateKind::Ambiguous => bug!(), + ty::ClauseKind::Trait(trait_pred) => { + assert_eq!(trait_pred.polarity, ty::ImplPolarity::Positive); + trait_bounds.push(( + bound_pred.rebind(trait_pred.trait_ref), + span, + trait_pred.constness, + )); + } + ty::ClauseKind::Projection(proj) => { + projection_bounds.push((bound_pred.rebind(proj), span)); + } + ty::ClauseKind::TypeOutlives(_) => { + // Do nothing, we deal with regions separately + } + ty::ClauseKind::RegionOutlives(_) + | ty::ClauseKind::ConstArgHasType(..) + | ty::ClauseKind::WellFormed(_) + | ty::ClauseKind::ConstEvaluatable(_) + | ty::ClauseKind::TypeWellFormedFromEnv(_) => { + bug!() + } } } @@ -1425,9 +1415,9 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { || { traits::transitive_bounds_that_define_assoc_item( tcx, - predicates.iter().filter_map(|(p, _)| { - Some(p.to_opt_poly_trait_pred()?.map_bound(|t| t.trait_ref)) - }), + predicates + .iter() + .filter_map(|(p, _)| Some(p.as_trait_clause()?.map_bound(|t| t.trait_ref))), assoc_name, ) }, diff --git a/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs b/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs index b2ba566f60c7..3048c175e1e4 100644 --- a/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs +++ b/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs @@ -220,7 +220,7 @@ fn compare_method_predicate_entailment<'tcx>( // the new hybrid bounds we computed. let normalize_cause = traits::ObligationCause::misc(impl_m_span, impl_m_def_id); let param_env = ty::ParamEnv::new( - tcx.mk_predicates(&hybrid_preds.predicates), + tcx.mk_clauses(&hybrid_preds.predicates), Reveal::UserFacing, hir::Constness::NotConst, ); @@ -1835,7 +1835,7 @@ fn compare_type_predicate_entailment<'tcx>( let impl_ty_span = tcx.def_span(impl_ty_def_id); let normalize_cause = traits::ObligationCause::misc(impl_ty_span, impl_ty_def_id); let param_env = ty::ParamEnv::new( - tcx.mk_predicates(&hybrid_preds.predicates), + tcx.mk_clauses(&hybrid_preds.predicates), Reveal::UserFacing, hir::Constness::NotConst, ); @@ -2011,7 +2011,7 @@ pub(super) fn check_type_bounds<'tcx>( .to_predicate(tcx), ), }; - ty::ParamEnv::new(tcx.mk_predicates(&predicates), Reveal::UserFacing, param_env.constness()) + ty::ParamEnv::new(tcx.mk_clauses(&predicates), Reveal::UserFacing, param_env.constness()) }; debug!(?normalize_param_env); diff --git a/compiler/rustc_hir_analysis/src/check/mod.rs b/compiler/rustc_hir_analysis/src/check/mod.rs index 596c5518086d..ce2da7cb1a32 100644 --- a/compiler/rustc_hir_analysis/src/check/mod.rs +++ b/compiler/rustc_hir_analysis/src/check/mod.rs @@ -296,7 +296,7 @@ fn default_body_is_unstable( /// Re-sugar `ty::GenericPredicates` in a way suitable to be used in structured suggestions. fn bounds_from_generic_predicates<'tcx>( tcx: TyCtxt<'tcx>, - predicates: impl IntoIterator, Span)>, + predicates: impl IntoIterator, Span)>, ) -> (String, String) { let mut types: FxHashMap, Vec> = FxHashMap::default(); let mut projections = vec![]; @@ -304,7 +304,7 @@ fn bounds_from_generic_predicates<'tcx>( debug!("predicate {:?}", predicate); let bound_predicate = predicate.kind(); match bound_predicate.skip_binder() { - ty::PredicateKind::Clause(ty::ClauseKind::Trait(trait_predicate)) => { + ty::ClauseKind::Trait(trait_predicate) => { let entry = types.entry(trait_predicate.self_ty()).or_default(); let def_id = trait_predicate.def_id(); if Some(def_id) != tcx.lang_items().sized_trait() { @@ -313,7 +313,7 @@ fn bounds_from_generic_predicates<'tcx>( entry.push(trait_predicate.def_id()); } } - ty::PredicateKind::Clause(ty::ClauseKind::Projection(projection_pred)) => { + ty::ClauseKind::Projection(projection_pred) => { projections.push(bound_predicate.rebind(projection_pred)); } _ => {} @@ -362,7 +362,7 @@ fn fn_sig_suggestion<'tcx>( tcx: TyCtxt<'tcx>, sig: ty::FnSig<'tcx>, ident: Ident, - predicates: impl IntoIterator, Span)>, + predicates: impl IntoIterator, Span)>, assoc: ty::AssocItem, ) -> String { let args = sig diff --git a/compiler/rustc_hir_analysis/src/check/wfcheck.rs b/compiler/rustc_hir_analysis/src/check/wfcheck.rs index 744eb0369335..d34d6f644a73 100644 --- a/compiler/rustc_hir_analysis/src/check/wfcheck.rs +++ b/compiler/rustc_hir_analysis/src/check/wfcheck.rs @@ -15,7 +15,7 @@ use rustc_middle::mir::ConstraintCategory; use rustc_middle::query::Providers; use rustc_middle::ty::trait_def::TraitSpecializationKind; use rustc_middle::ty::{ - self, AdtKind, GenericParamDefKind, Ty, TyCtxt, TypeFoldable, TypeSuperVisitable, + self, AdtKind, GenericParamDefKind, ToPredicate, Ty, TyCtxt, TypeFoldable, TypeSuperVisitable, TypeVisitable, TypeVisitableExt, TypeVisitor, }; use rustc_middle::ty::{GenericArgKind, InternalSubsts}; @@ -322,7 +322,7 @@ fn check_gat_where_clauses(tcx: TyCtxt<'_>, associated_items: &[hir::TraitItemRe // Gather the bounds with which all other items inside of this trait constrain the GAT. // This is calculated by taking the intersection of the bounds that each item // constrains the GAT with individually. - let mut new_required_bounds: Option>> = None; + let mut new_required_bounds: Option>> = None; for item in associated_items { let item_def_id = item.id.owner_id; // Skip our own GAT, since it does not constrain itself at all. @@ -419,9 +419,17 @@ fn check_gat_where_clauses(tcx: TyCtxt<'_>, associated_items: &[hir::TraitItemRe let mut unsatisfied_bounds: Vec<_> = required_bounds .into_iter() .filter(|clause| match clause.kind().skip_binder() { - ty::PredicateKind::Clause(ty::ClauseKind::RegionOutlives( - ty::OutlivesPredicate(a, b), - )) => !region_known_to_outlive( + ty::ClauseKind::RegionOutlives(ty::OutlivesPredicate(a, b)) => { + !region_known_to_outlive( + tcx, + gat_def_id.def_id, + param_env, + &FxIndexSet::default(), + a, + b, + ) + } + ty::ClauseKind::TypeOutlives(ty::OutlivesPredicate(a, b)) => !ty_known_to_outlive( tcx, gat_def_id.def_id, param_env, @@ -429,18 +437,7 @@ fn check_gat_where_clauses(tcx: TyCtxt<'_>, associated_items: &[hir::TraitItemRe a, b, ), - ty::PredicateKind::Clause(ty::ClauseKind::TypeOutlives(ty::OutlivesPredicate( - a, - b, - ))) => !ty_known_to_outlive( - tcx, - gat_def_id.def_id, - param_env, - &FxIndexSet::default(), - a, - b, - ), - _ => bug!("Unexpected PredicateKind"), + _ => bug!("Unexpected ClauseKind"), }) .map(|clause| clause.to_string()) .collect(); @@ -488,7 +485,7 @@ fn check_gat_where_clauses(tcx: TyCtxt<'_>, associated_items: &[hir::TraitItemRe fn augment_param_env<'tcx>( tcx: TyCtxt<'tcx>, param_env: ty::ParamEnv<'tcx>, - new_predicates: Option<&FxHashSet>>, + new_predicates: Option<&FxHashSet>>, ) -> ty::ParamEnv<'tcx> { let Some(new_predicates) = new_predicates else { return param_env; @@ -498,7 +495,7 @@ fn augment_param_env<'tcx>( return param_env; } - let bounds = tcx.mk_predicates_from_iter( + let bounds = tcx.mk_clauses_from_iter( param_env.caller_bounds().iter().chain(new_predicates.iter().cloned()), ); // FIXME(compiler-errors): Perhaps there is a case where we need to normalize this @@ -524,7 +521,7 @@ fn gather_gat_bounds<'tcx, T: TypeFoldable>>( wf_tys: &FxIndexSet>, gat_def_id: LocalDefId, gat_generics: &'tcx ty::Generics, -) -> Option>> { +) -> Option>> { // The bounds we that we would require from `to_check` let mut bounds = FxHashSet::default(); @@ -573,11 +570,10 @@ fn gather_gat_bounds<'tcx, T: TypeFoldable>>( ); // The predicate we expect to see. (In our example, // `Self: 'me`.) - let clause = ty::PredicateKind::Clause(ty::ClauseKind::TypeOutlives( - ty::OutlivesPredicate(ty_param, region_param), - )); - let clause = tcx.mk_predicate(ty::Binder::dummy(clause)); - bounds.insert(clause); + bounds.insert( + ty::ClauseKind::TypeOutlives(ty::OutlivesPredicate(ty_param, region_param)) + .to_predicate(tcx), + ); } } @@ -622,11 +618,13 @@ fn gather_gat_bounds<'tcx, T: TypeFoldable>>( }, ); // The predicate we expect to see. - let clause = ty::PredicateKind::Clause(ty::ClauseKind::RegionOutlives( - ty::OutlivesPredicate(region_a_param, region_b_param), - )); - let clause = tcx.mk_predicate(ty::Binder::dummy(clause)); - bounds.insert(clause); + bounds.insert( + ty::ClauseKind::RegionOutlives(ty::OutlivesPredicate( + region_a_param, + region_b_param, + )) + .to_predicate(tcx), + ); } } } @@ -1406,7 +1404,7 @@ fn check_where_clauses<'tcx>(wfcx: &WfCheckingCtxt<'_, 'tcx>, span: Span, def_id infcx, wfcx.param_env.without_const(), wfcx.body_def_id, - p, + p.as_predicate(), sp, ) }); @@ -1549,7 +1547,7 @@ impl<'tcx> TypeVisitor> for ImplTraitInTraitFinder<'_, 'tcx> { { let opaque_ty = tcx.fold_regions(unshifted_opaque_ty, |re, _depth| { match re.kind() { - ty::ReEarlyBound(_) | ty::ReFree(_) | ty::ReError(_) => re, + ty::ReEarlyBound(_) | ty::ReFree(_) | ty::ReError(_) | ty::ReStatic => re, r => bug!("unexpected region: {r:?}"), } }); @@ -1875,9 +1873,7 @@ impl<'tcx> WfCheckingCtxt<'_, 'tcx> { // We lower empty bounds like `Vec:` as // `WellFormed(Vec)`, which will later get checked by // regular WF checking - if let ty::PredicateKind::Clause(ty::ClauseKind::WellFormed(..)) = - pred.kind().skip_binder() - { + if let ty::ClauseKind::WellFormed(..) = pred.kind().skip_binder() { continue; } // Match the existing behavior. diff --git a/compiler/rustc_hir_analysis/src/coherence/inherent_impls_overlap.rs b/compiler/rustc_hir_analysis/src/coherence/inherent_impls_overlap.rs index bd6252344b2c..3bd2931265c7 100644 --- a/compiler/rustc_hir_analysis/src/coherence/inherent_impls_overlap.rs +++ b/compiler/rustc_hir_analysis/src/coherence/inherent_impls_overlap.rs @@ -140,7 +140,7 @@ impl<'tcx> InherentOverlapChecker<'tcx> { impl1_def_id: DefId, impl2_def_id: DefId, ) { - traits::overlapping_impls( + let maybe_overlap = traits::overlapping_impls( self.tcx, impl1_def_id, impl2_def_id, @@ -148,11 +148,11 @@ impl<'tcx> InherentOverlapChecker<'tcx> { // inherent impls without warning. SkipLeakCheck::Yes, overlap_mode, - ) - .map_or(true, |overlap| { + ); + + if let Some(overlap) = maybe_overlap { self.check_for_common_items_in_impls(impl1_def_id, impl2_def_id, overlap); - false - }); + } } fn check_item(&mut self, id: hir::ItemId) { diff --git a/compiler/rustc_hir_analysis/src/collect/item_bounds.rs b/compiler/rustc_hir_analysis/src/collect/item_bounds.rs index 958313fee6fb..44c393bfe82f 100644 --- a/compiler/rustc_hir_analysis/src/collect/item_bounds.rs +++ b/compiler/rustc_hir_analysis/src/collect/item_bounds.rs @@ -38,16 +38,12 @@ fn associated_type_bounds<'tcx>( .iter() .copied() .filter(|(pred, _)| match pred.kind().skip_binder() { - ty::PredicateKind::Clause(ty::ClauseKind::Trait(tr)) => tr.self_ty() == item_ty, - ty::PredicateKind::Clause(ty::ClauseKind::Projection(proj)) => { - proj.projection_ty.self_ty() == item_ty - } - ty::PredicateKind::Clause(ty::ClauseKind::TypeOutlives(outlives)) => { - outlives.0 == item_ty - } + ty::ClauseKind::Trait(tr) => tr.self_ty() == item_ty, + ty::ClauseKind::Projection(proj) => proj.projection_ty.self_ty() == item_ty, + ty::ClauseKind::TypeOutlives(outlives) => outlives.0 == item_ty, _ => false, }) - .map(|(pred, span)| (pred.expect_clause(), span)); + .map(|(clause, span)| (clause, span)); let all_bounds = tcx.arena.alloc_from_iter(bounds.clauses().chain(bounds_from_parent)); debug!( diff --git a/compiler/rustc_hir_analysis/src/collect/predicates_of.rs b/compiler/rustc_hir_analysis/src/collect/predicates_of.rs index 3081f0c386a2..edb6a4cace34 100644 --- a/compiler/rustc_hir_analysis/src/collect/predicates_of.rs +++ b/compiler/rustc_hir_analysis/src/collect/predicates_of.rs @@ -75,7 +75,7 @@ fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Gen // We use an `IndexSet` to preserve order of insertion. // Preserving the order of insertion is important here so as not to break UI tests. - let mut predicates: FxIndexSet<(ty::Predicate<'_>, Span)> = FxIndexSet::default(); + let mut predicates: FxIndexSet<(ty::Clause<'_>, Span)> = FxIndexSet::default(); let ast_generics = match node { Node::TraitItem(item) => item.generics, @@ -126,8 +126,7 @@ fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Gen predicates.extend( icx.astconv() .compute_bounds(tcx.types.self_param, self_bounds, OnlySelfBounds(false)) - .clauses() - .map(|(clause, span)| (clause.as_predicate(), span)), + .clauses(), ); } @@ -176,8 +175,7 @@ fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Gen param.span, ); trace!(?bounds); - predicates - .extend(bounds.clauses().map(|(clause, span)| (clause.as_predicate(), span))); + predicates.extend(bounds.clauses()); trace!(?predicates); } GenericParamKind::Const { .. } => { @@ -188,11 +186,10 @@ fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Gen let ct = tcx.mk_const(param_const, ct_ty); - let predicate = ty::Binder::dummy(ty::PredicateKind::Clause( - ty::ClauseKind::ConstArgHasType(ct, ct_ty), - )) - .to_predicate(tcx); - predicates.insert((predicate, param.span)); + predicates.insert(( + ty::ClauseKind::ConstArgHasType(ct, ct_ty).to_predicate(tcx), + param.span, + )); index += 1; } @@ -221,7 +218,7 @@ fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Gen } else { let span = bound_pred.bounded_ty.span; let predicate = ty::Binder::bind_with_vars( - ty::PredicateKind::Clause(ty::ClauseKind::WellFormed(ty.into())), + ty::ClauseKind::WellFormed(ty.into()), bound_vars, ); predicates.insert((predicate.to_predicate(tcx), span)); @@ -236,8 +233,7 @@ fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Gen bound_vars, OnlySelfBounds(false), ); - predicates - .extend(bounds.clauses().map(|(clause, span)| (clause.as_predicate(), span))); + predicates.extend(bounds.clauses()); } hir::WherePredicate::RegionPredicate(region_pred) => { @@ -249,11 +245,8 @@ fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Gen } _ => bug!(), }; - let pred = ty::Binder::dummy(ty::PredicateKind::Clause( - ty::ClauseKind::RegionOutlives(ty::OutlivesPredicate(r1, r2)), - )) - .to_predicate(icx.tcx); - + let pred = ty::ClauseKind::RegionOutlives(ty::OutlivesPredicate(r1, r2)) + .to_predicate(icx.tcx); (pred, span) })) } @@ -318,17 +311,13 @@ fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Gen }, ); predicates.push(( - ty::Binder::dummy(ty::PredicateKind::Clause(ty::ClauseKind::RegionOutlives( - ty::OutlivesPredicate(orig_region, dup_region), - ))) - .to_predicate(icx.tcx), + ty::ClauseKind::RegionOutlives(ty::OutlivesPredicate(orig_region, dup_region)) + .to_predicate(icx.tcx), duplicate.span, )); predicates.push(( - ty::Binder::dummy(ty::PredicateKind::Clause(ty::ClauseKind::RegionOutlives( - ty::OutlivesPredicate(dup_region, orig_region), - ))) - .to_predicate(icx.tcx), + ty::ClauseKind::RegionOutlives(ty::OutlivesPredicate(dup_region, orig_region)) + .to_predicate(icx.tcx), duplicate.span, )); } @@ -344,10 +333,10 @@ fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Gen fn const_evaluatable_predicates_of( tcx: TyCtxt<'_>, def_id: LocalDefId, -) -> FxIndexSet<(ty::Predicate<'_>, Span)> { +) -> FxIndexSet<(ty::Clause<'_>, Span)> { struct ConstCollector<'tcx> { tcx: TyCtxt<'tcx>, - preds: FxIndexSet<(ty::Predicate<'tcx>, Span)>, + preds: FxIndexSet<(ty::Clause<'tcx>, Span)>, } impl<'tcx> intravisit::Visitor<'tcx> for ConstCollector<'tcx> { @@ -355,13 +344,8 @@ fn const_evaluatable_predicates_of( let ct = ty::Const::from_anon_const(self.tcx, c.def_id); if let ty::ConstKind::Unevaluated(_) = ct.kind() { let span = self.tcx.def_span(c.def_id); - self.preds.insert(( - ty::Binder::dummy(ty::PredicateKind::Clause(ty::ClauseKind::ConstEvaluatable( - ct, - ))) - .to_predicate(self.tcx), - span, - )); + self.preds + .insert((ty::ClauseKind::ConstEvaluatable(ct).to_predicate(self.tcx), span)); } } @@ -449,15 +433,9 @@ pub(super) fn explicit_predicates_of<'tcx>( .iter() .copied() .filter(|(pred, _)| match pred.kind().skip_binder() { - ty::PredicateKind::Clause(ty::ClauseKind::Trait(tr)) => { - !is_assoc_item_ty(tr.self_ty()) - } - ty::PredicateKind::Clause(ty::ClauseKind::Projection(proj)) => { - !is_assoc_item_ty(proj.projection_ty.self_ty()) - } - ty::PredicateKind::Clause(ty::ClauseKind::TypeOutlives(outlives)) => { - !is_assoc_item_ty(outlives.0) - } + ty::ClauseKind::Trait(tr) => !is_assoc_item_ty(tr.self_ty()), + ty::ClauseKind::Projection(proj) => !is_assoc_item_ty(proj.projection_ty.self_ty()), + ty::ClauseKind::TypeOutlives(outlives) => !is_assoc_item_ty(outlives.0), _ => true, }) .collect(); @@ -498,9 +476,7 @@ pub(super) fn explicit_predicates_of<'tcx>( .predicates .into_iter() .filter(|(pred, _)| { - if let ty::PredicateKind::Clause(ty::ClauseKind::ConstArgHasType(ct, _)) = - pred.kind().skip_binder() - { + if let ty::ClauseKind::ConstArgHasType(ct, _) = pred.kind().skip_binder() { match ct.kind() { ty::ConstKind::Param(param_const) => { let defaulted_param_idx = tcx @@ -665,12 +641,8 @@ pub(super) fn implied_predicates_with_filter( }; // Combine the two lists to form the complete set of superbounds: - let implied_bounds = &*tcx.arena.alloc_from_iter( - superbounds - .clauses() - .map(|(clause, span)| (clause.as_predicate(), span)) - .chain(where_bounds_that_match), - ); + let implied_bounds = + &*tcx.arena.alloc_from_iter(superbounds.clauses().chain(where_bounds_that_match)); debug!(?implied_bounds); // Now require that immediate supertraits are converted, which will, in @@ -679,7 +651,7 @@ pub(super) fn implied_predicates_with_filter( if matches!(filter, PredicateFilter::SelfOnly) { for &(pred, span) in implied_bounds { debug!("superbound: {:?}", pred); - if let ty::PredicateKind::Clause(ty::ClauseKind::Trait(bound)) = pred.kind().skip_binder() + if let ty::ClauseKind::Trait(bound) = pred.kind().skip_binder() && bound.polarity == ty::ImplPolarity::Positive { tcx.at(span).super_predicates_of(bound.def_id()); @@ -776,9 +748,7 @@ pub(super) fn type_param_predicates( ) .into_iter() .filter(|(predicate, _)| match predicate.kind().skip_binder() { - ty::PredicateKind::Clause(ty::ClauseKind::Trait(data)) => { - data.self_ty().is_param(index) - } + ty::ClauseKind::Trait(data) => data.self_ty().is_param(index), _ => false, }), ); @@ -800,7 +770,7 @@ impl<'tcx> ItemCtxt<'tcx> { ty: Ty<'tcx>, only_self_bounds: OnlySelfBounds, assoc_name: Option, - ) -> Vec<(ty::Predicate<'tcx>, Span)> { + ) -> Vec<(ty::Clause<'tcx>, Span)> { let mut bounds = Bounds::default(); for predicate in ast_generics.predicates { @@ -829,7 +799,7 @@ impl<'tcx> ItemCtxt<'tcx> { ); } - bounds.clauses().map(|(clause, span)| (clause.as_predicate(), span)).collect() + bounds.clauses().collect() } #[instrument(level = "trace", skip(self))] diff --git a/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs b/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs index d20f39e9b05b..3d75df8c69f0 100644 --- a/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs +++ b/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs @@ -1761,7 +1761,7 @@ impl<'a, 'tcx> BoundVarContext<'a, 'tcx> { let obligations = predicates.predicates.iter().filter_map(|&(pred, _)| { let bound_predicate = pred.kind(); match bound_predicate.skip_binder() { - ty::PredicateKind::Clause(ty::ClauseKind::Trait(data)) => { + ty::ClauseKind::Trait(data) => { // The order here needs to match what we would get from `subst_supertrait` let pred_bound_vars = bound_predicate.bound_vars(); let mut all_bound_vars = bound_vars.clone(); diff --git a/compiler/rustc_hir_analysis/src/constrained_generic_params.rs b/compiler/rustc_hir_analysis/src/constrained_generic_params.rs index 6aecb95b484a..35882ad352be 100644 --- a/compiler/rustc_hir_analysis/src/constrained_generic_params.rs +++ b/compiler/rustc_hir_analysis/src/constrained_generic_params.rs @@ -151,7 +151,7 @@ pub fn identify_constrained_generic_params<'tcx>( /// think of any. pub fn setup_constraining_predicates<'tcx>( tcx: TyCtxt<'tcx>, - predicates: &mut [(ty::Predicate<'tcx>, Span)], + predicates: &mut [(ty::Clause<'tcx>, Span)], impl_trait_ref: Option>, input_parameters: &mut FxHashSet, ) { @@ -187,9 +187,7 @@ pub fn setup_constraining_predicates<'tcx>( for j in i..predicates.len() { // Note that we don't have to care about binders here, // as the impl trait ref never contains any late-bound regions. - if let ty::PredicateKind::Clause(ty::ClauseKind::Projection(projection)) = - predicates[j].0.kind().skip_binder() - { + if let ty::ClauseKind::Projection(projection) = predicates[j].0.kind().skip_binder() { // Special case: watch out for some kind of sneaky attempt // to project out an associated type defined by this very // trait. diff --git a/compiler/rustc_hir_analysis/src/impl_wf_check/min_specialization.rs b/compiler/rustc_hir_analysis/src/impl_wf_check/min_specialization.rs index 97813a291da6..383144ce1396 100644 --- a/compiler/rustc_hir_analysis/src/impl_wf_check/min_specialization.rs +++ b/compiler/rustc_hir_analysis/src/impl_wf_check/min_specialization.rs @@ -235,10 +235,8 @@ fn unconstrained_parent_impl_substs<'tcx>( // what we want here. We want only a list of constrained parameters while // the functions in `cgp` add the constrained parameters to a list of // unconstrained parameters. - for (predicate, _) in impl_generic_predicates.predicates.iter() { - if let ty::PredicateKind::Clause(ty::ClauseKind::Projection(proj)) = - predicate.kind().skip_binder() - { + for (clause, _) in impl_generic_predicates.predicates.iter() { + if let ty::ClauseKind::Projection(proj) = clause.kind().skip_binder() { let projection_ty = proj.projection_ty; let projected_ty = proj.term; @@ -340,8 +338,11 @@ fn check_predicates<'tcx>( impl2_substs: SubstsRef<'tcx>, span: Span, ) { - let instantiated = tcx.predicates_of(impl1_def_id).instantiate(tcx, impl1_substs); - let impl1_predicates: Vec<_> = traits::elaborate(tcx, instantiated.into_iter()).collect(); + let impl1_predicates: Vec<_> = traits::elaborate( + tcx, + tcx.predicates_of(impl1_def_id).instantiate(tcx, impl1_substs).into_iter(), + ) + .collect(); let mut impl2_predicates = if impl2_node.is_from_trait() { // Always applicable traits have to be always applicable without any @@ -352,8 +353,8 @@ fn check_predicates<'tcx>( tcx, tcx.predicates_of(impl2_node.def_id()) .instantiate(tcx, impl2_substs) - .predicates - .into_iter(), + .into_iter() + .map(|(c, _s)| c.as_predicate()), ) .collect() }; @@ -377,13 +378,13 @@ fn check_predicates<'tcx>( let always_applicable_traits = impl1_predicates .iter() .copied() - .filter(|&(predicate, _)| { + .filter(|(clause, _span)| { matches!( - trait_predicate_kind(tcx, predicate), + trait_predicate_kind(tcx, clause.as_predicate()), Some(TraitSpecializationKind::AlwaysApplicable) ) }) - .map(|(pred, _span)| pred); + .map(|(c, _span)| c.as_predicate()); // Include the well-formed predicates of the type parameters of the impl. for arg in tcx.impl_trait_ref(impl1_def_id).unwrap().subst_identity().substs { @@ -398,9 +399,12 @@ fn check_predicates<'tcx>( } impl2_predicates.extend(traits::elaborate(tcx, always_applicable_traits)); - for (predicate, span) in impl1_predicates { - if !impl2_predicates.iter().any(|pred2| trait_predicates_eq(tcx, predicate, *pred2, span)) { - check_specialization_on(tcx, predicate, span) + for (clause, span) in impl1_predicates { + if !impl2_predicates + .iter() + .any(|pred2| trait_predicates_eq(tcx, clause.as_predicate(), *pred2, span)) + { + check_specialization_on(tcx, clause.as_predicate(), span) } } } @@ -550,6 +554,6 @@ fn trait_predicate_kind<'tcx>( | ty::PredicateKind::Clause(ty::ClauseKind::ConstEvaluatable(..)) | ty::PredicateKind::ConstEquate(..) | ty::PredicateKind::Ambiguous - | ty::PredicateKind::TypeWellFormedFromEnv(..) => None, + | ty::PredicateKind::Clause(ty::ClauseKind::TypeWellFormedFromEnv(..)) => None, } } diff --git a/compiler/rustc_hir_analysis/src/outlives/explicit.rs b/compiler/rustc_hir_analysis/src/outlives/explicit.rs index e63549998d2a..3a04c3336caa 100644 --- a/compiler/rustc_hir_analysis/src/outlives/explicit.rs +++ b/compiler/rustc_hir_analysis/src/outlives/explicit.rs @@ -30,40 +30,31 @@ impl<'tcx> ExplicitPredicatesMap<'tcx> { // process predicates and convert to `RequiredPredicates` entry, see below for &(predicate, span) in predicates.predicates { match predicate.kind().skip_binder() { - ty::PredicateKind::Clause(ty::ClauseKind::TypeOutlives(OutlivesPredicate( - ty, - reg, - ))) => insert_outlives_predicate( - tcx, - ty.into(), - reg, - span, - &mut required_predicates, - ), + ty::ClauseKind::TypeOutlives(OutlivesPredicate(ty, reg)) => { + insert_outlives_predicate( + tcx, + ty.into(), + reg, + span, + &mut required_predicates, + ) + } - ty::PredicateKind::Clause(ty::ClauseKind::RegionOutlives( - OutlivesPredicate(reg1, reg2), - )) => insert_outlives_predicate( - tcx, - reg1.into(), - reg2, - span, - &mut required_predicates, - ), - - ty::PredicateKind::Clause(ty::ClauseKind::Trait(..)) - | ty::PredicateKind::Clause(ty::ClauseKind::Projection(..)) - | ty::PredicateKind::Clause(ty::ClauseKind::ConstArgHasType(..)) - | ty::PredicateKind::Clause(ty::ClauseKind::WellFormed(..)) - | ty::PredicateKind::AliasRelate(..) - | ty::PredicateKind::ObjectSafe(..) - | ty::PredicateKind::ClosureKind(..) - | ty::PredicateKind::Subtype(..) - | ty::PredicateKind::Coerce(..) - | ty::PredicateKind::Clause(ty::ClauseKind::ConstEvaluatable(..)) - | ty::PredicateKind::ConstEquate(..) - | ty::PredicateKind::Ambiguous - | ty::PredicateKind::TypeWellFormedFromEnv(..) => (), + ty::ClauseKind::RegionOutlives(OutlivesPredicate(reg1, reg2)) => { + insert_outlives_predicate( + tcx, + reg1.into(), + reg2, + span, + &mut required_predicates, + ) + } + ty::ClauseKind::Trait(_) + | ty::ClauseKind::Projection(_) + | ty::ClauseKind::ConstArgHasType(_, _) + | ty::ClauseKind::WellFormed(_) + | ty::ClauseKind::ConstEvaluatable(_) + | ty::ClauseKind::TypeWellFormedFromEnv(_) => {} } } diff --git a/compiler/rustc_hir_pretty/src/lib.rs b/compiler/rustc_hir_pretty/src/lib.rs index ced46fe426c4..a699cd6c942e 100644 --- a/compiler/rustc_hir_pretty/src/lib.rs +++ b/compiler/rustc_hir_pretty/src/lib.rs @@ -1554,6 +1554,11 @@ impl<'a> State<'a> { self.print_expr_maybe_paren(expr, parser::PREC_JUMP); } } + hir::ExprKind::Become(result) => { + self.word("become"); + self.word(" "); + self.print_expr_maybe_paren(result, parser::PREC_JUMP); + } hir::ExprKind::InlineAsm(asm) => { self.word("asm!"); self.print_inline_asm(asm); diff --git a/compiler/rustc_hir_typeck/messages.ftl b/compiler/rustc_hir_typeck/messages.ftl index c1c58db57648..3d012a15a675 100644 --- a/compiler/rustc_hir_typeck/messages.ftl +++ b/compiler/rustc_hir_typeck/messages.ftl @@ -78,8 +78,8 @@ hir_typeck_note_edition_guide = for more on editions, read https://doc.rust-lang hir_typeck_op_trait_generic_params = `{$method_name}` must not have any generic parameters hir_typeck_return_stmt_outside_of_fn_body = - return statement outside of function body - .encl_body_label = the return is part of this body... + {$statement_kind} statement outside of function body + .encl_body_label = the {$statement_kind} is part of this body... .encl_fn_label = ...not the enclosing function body hir_typeck_struct_expr_non_exhaustive = diff --git a/compiler/rustc_hir_typeck/src/demand.rs b/compiler/rustc_hir_typeck/src/demand.rs index 9ce03060e0fe..47f3c6b84079 100644 --- a/compiler/rustc_hir_typeck/src/demand.rs +++ b/compiler/rustc_hir_typeck/src/demand.rs @@ -83,6 +83,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } self.annotate_expected_due_to_let_ty(err, expr, error); + + if self.is_destruct_assignment_desugaring(expr) { + return; + } self.emit_type_mismatch_suggestions(err, expr, expr_ty, expected, expected_ty_expr, error); self.note_type_is_not_clone(err, expected, expr_ty, expr); self.note_internal_mutation_in_method(err, expr, Some(expected), expr_ty); @@ -1253,6 +1257,26 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { false } + // Returns whether the given expression is a destruct assignment desugaring. + // For example, `(a, b) = (1, &2);` + // Here we try to find the pattern binding of the expression, + // `default_binding_modes` is false only for destruct assignment desugaring. + pub(crate) fn is_destruct_assignment_desugaring(&self, expr: &hir::Expr<'_>) -> bool { + if let hir::ExprKind::Path(hir::QPath::Resolved( + _, + hir::Path { res: hir::def::Res::Local(bind_hir_id), .. }, + )) = expr.kind + { + let bind = self.tcx.hir().find(*bind_hir_id); + let parent = self.tcx.hir().find(self.tcx.hir().parent_id(*bind_hir_id)); + if let Some(hir::Node::Pat(hir::Pat { kind: hir::PatKind::Binding(_, _hir_id, _, _), .. })) = bind && + let Some(hir::Node::Pat(hir::Pat { default_binding_modes: false, .. })) = parent { + return true; + } + } + return false; + } + /// This function is used to determine potential "simple" improvements or users' errors and /// provide them useful help. For example: /// @@ -1443,6 +1467,20 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { _, &ty::Ref(_, checked, _), ) if self.can_sub(self.param_env, checked, expected) => { + let make_sugg = |start: Span, end: BytePos| { + // skip `(` for tuples such as `(c) = (&123)`. + // make sure we won't suggest like `(c) = 123)` which is incorrect. + let sp = sm.span_extend_while(start.shrink_to_lo(), |c| c == '(' || c.is_whitespace()) + .map_or(start, |s| s.shrink_to_hi()); + Some(( + vec![(sp.with_hi(end), String::new())], + "consider removing the borrow".to_string(), + Applicability::MachineApplicable, + true, + true, + )) + }; + // We have `&T`, check if what was expected was `T`. If so, // we may want to suggest removing a `&`. if sm.is_imported(expr.span) { @@ -1456,24 +1494,12 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { .find(|&s| sp.contains(s)) && sm.is_span_accessible(call_span) { - return Some(( - vec![(sp.with_hi(call_span.lo()), String::new())], - "consider removing the borrow".to_string(), - Applicability::MachineApplicable, - true, - true, - )); + return make_sugg(sp, call_span.lo()) } return None; } if sp.contains(expr.span) && sm.is_span_accessible(expr.span) { - return Some(( - vec![(sp.with_hi(expr.span.lo()), String::new())], - "consider removing the borrow".to_string(), - Applicability::MachineApplicable, - true, - true, - )); + return make_sugg(sp, expr.span.lo()) } } ( diff --git a/compiler/rustc_hir_typeck/src/errors.rs b/compiler/rustc_hir_typeck/src/errors.rs index 6b4168d89446..05906a4b9f59 100644 --- a/compiler/rustc_hir_typeck/src/errors.rs +++ b/compiler/rustc_hir_typeck/src/errors.rs @@ -2,7 +2,10 @@ use std::borrow::Cow; use crate::fluent_generated as fluent; -use rustc_errors::{AddToDiagnostic, Applicability, Diagnostic, MultiSpan, SubdiagnosticMessage}; +use rustc_errors::{ + AddToDiagnostic, Applicability, Diagnostic, DiagnosticArgValue, IntoDiagnosticArg, MultiSpan, + SubdiagnosticMessage, +}; use rustc_macros::{Diagnostic, Subdiagnostic}; use rustc_middle::ty::Ty; use rustc_span::{ @@ -31,6 +34,24 @@ pub struct ReturnStmtOutsideOfFnBody { pub encl_body_span: Option, #[label(hir_typeck_encl_fn_label)] pub encl_fn_span: Option, + pub statement_kind: ReturnLikeStatementKind, +} + +pub enum ReturnLikeStatementKind { + Return, + Become, +} + +impl IntoDiagnosticArg for ReturnLikeStatementKind { + fn into_diagnostic_arg(self) -> DiagnosticArgValue<'static> { + let kind = match self { + Self::Return => "return", + Self::Become => "become", + } + .into(); + + DiagnosticArgValue::Str(kind) + } } #[derive(Diagnostic)] diff --git a/compiler/rustc_hir_typeck/src/expr.rs b/compiler/rustc_hir_typeck/src/expr.rs index e250e68a7f17..8d621c5a42b2 100644 --- a/compiler/rustc_hir_typeck/src/expr.rs +++ b/compiler/rustc_hir_typeck/src/expr.rs @@ -5,6 +5,7 @@ use crate::cast; use crate::coercion::CoerceMany; use crate::coercion::DynamicCoerceMany; +use crate::errors::ReturnLikeStatementKind; use crate::errors::TypeMismatchFruTypo; use crate::errors::{AddressOfTemporaryTaken, ReturnStmtOutsideOfFnBody, StructExprNonExhaustive}; use crate::errors::{ @@ -324,6 +325,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } } ExprKind::Ret(ref expr_opt) => self.check_expr_return(expr_opt.as_deref(), expr), + ExprKind::Become(call) => self.check_expr_become(call, expr), ExprKind::Let(let_expr) => self.check_expr_let(let_expr), ExprKind::Loop(body, _, source, _) => { self.check_expr_loop(body, source, expected, expr) @@ -735,47 +737,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { expr: &'tcx hir::Expr<'tcx>, ) -> Ty<'tcx> { if self.ret_coercion.is_none() { - let mut err = ReturnStmtOutsideOfFnBody { - span: expr.span, - encl_body_span: None, - encl_fn_span: None, - }; - - let encl_item_id = self.tcx.hir().get_parent_item(expr.hir_id); - - if let Some(hir::Node::Item(hir::Item { - kind: hir::ItemKind::Fn(..), - span: encl_fn_span, - .. - })) - | Some(hir::Node::TraitItem(hir::TraitItem { - kind: hir::TraitItemKind::Fn(_, hir::TraitFn::Provided(_)), - span: encl_fn_span, - .. - })) - | Some(hir::Node::ImplItem(hir::ImplItem { - kind: hir::ImplItemKind::Fn(..), - span: encl_fn_span, - .. - })) = self.tcx.hir().find_by_def_id(encl_item_id.def_id) - { - // We are inside a function body, so reporting "return statement - // outside of function body" needs an explanation. - - let encl_body_owner_id = self.tcx.hir().enclosing_body_owner(expr.hir_id); - - // If this didn't hold, we would not have to report an error in - // the first place. - assert_ne!(encl_item_id.def_id, encl_body_owner_id); - - let encl_body_id = self.tcx.hir().body_owned_by(encl_body_owner_id); - let encl_body = self.tcx.hir().body(encl_body_id); - - err.encl_body_span = Some(encl_body.value.span); - err.encl_fn_span = Some(*encl_fn_span); - } - - self.tcx.sess.emit_err(err); + self.emit_return_outside_of_fn_body(expr, ReturnLikeStatementKind::Return); if let Some(e) = expr_opt { // We still have to type-check `e` (issue #86188), but calling @@ -815,6 +777,38 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { self.tcx.types.never } + fn check_expr_become( + &self, + call: &'tcx hir::Expr<'tcx>, + expr: &'tcx hir::Expr<'tcx>, + ) -> Ty<'tcx> { + match &self.ret_coercion { + Some(ret_coercion) => { + let ret_ty = ret_coercion.borrow().expected_ty(); + let call_expr_ty = self.check_expr_with_hint(call, ret_ty); + + // N.B. don't coerce here, as tail calls can't support most/all coercions + // FIXME(explicit_tail_calls): add a diagnostic note that `become` doesn't allow coercions + self.demand_suptype(expr.span, ret_ty, call_expr_ty); + } + None => { + self.emit_return_outside_of_fn_body(expr, ReturnLikeStatementKind::Become); + + // Fallback to simply type checking `call` without hint/demanding the right types. + // Best effort to highlight more errors. + self.check_expr(call); + } + } + + self.tcx.types.never + } + + /// Check an expression that _is being returned_. + /// For example, this is called with `return_expr: $expr` when `return $expr` + /// is encountered. + /// + /// Note that this function must only be called in function bodies. + /// /// `explicit_return` is `true` if we're checking an explicit `return expr`, /// and `false` if we're checking a trailing expression. pub(super) fn check_return_expr( @@ -831,10 +825,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let mut span = return_expr.span; // Use the span of the trailing expression for our cause, // not the span of the entire function - if !explicit_return { - if let ExprKind::Block(body, _) = return_expr.kind && let Some(last_expr) = body.expr { + if !explicit_return + && let ExprKind::Block(body, _) = return_expr.kind + && let Some(last_expr) = body.expr + { span = last_expr.span; - } } ret_coercion.borrow_mut().coerce( self, @@ -854,6 +849,55 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } } + /// Emit an error because `return` or `become` is used outside of a function body. + /// + /// `expr` is the `return` (`become`) "statement", `kind` is the kind of the statement + /// either `Return` or `Become`. + fn emit_return_outside_of_fn_body(&self, expr: &hir::Expr<'_>, kind: ReturnLikeStatementKind) { + let mut err = ReturnStmtOutsideOfFnBody { + span: expr.span, + encl_body_span: None, + encl_fn_span: None, + statement_kind: kind, + }; + + let encl_item_id = self.tcx.hir().get_parent_item(expr.hir_id); + + if let Some(hir::Node::Item(hir::Item { + kind: hir::ItemKind::Fn(..), + span: encl_fn_span, + .. + })) + | Some(hir::Node::TraitItem(hir::TraitItem { + kind: hir::TraitItemKind::Fn(_, hir::TraitFn::Provided(_)), + span: encl_fn_span, + .. + })) + | Some(hir::Node::ImplItem(hir::ImplItem { + kind: hir::ImplItemKind::Fn(..), + span: encl_fn_span, + .. + })) = self.tcx.hir().find_by_def_id(encl_item_id.def_id) + { + // We are inside a function body, so reporting "return statement + // outside of function body" needs an explanation. + + let encl_body_owner_id = self.tcx.hir().enclosing_body_owner(expr.hir_id); + + // If this didn't hold, we would not have to report an error in + // the first place. + assert_ne!(encl_item_id.def_id, encl_body_owner_id); + + let encl_body_id = self.tcx.hir().body_owned_by(encl_body_owner_id); + let encl_body = self.tcx.hir().body(encl_body_id); + + err.encl_body_span = Some(encl_body.value.span); + err.encl_fn_span = Some(*encl_fn_span); + } + + self.tcx.sess.emit_err(err); + } + fn point_at_return_for_opaque_ty_error( &self, errors: &mut Vec>, diff --git a/compiler/rustc_hir_typeck/src/expr_use_visitor.rs b/compiler/rustc_hir_typeck/src/expr_use_visitor.rs index 82d9f03b1451..0d2e0602e1cd 100644 --- a/compiler/rustc_hir_typeck/src/expr_use_visitor.rs +++ b/compiler/rustc_hir_typeck/src/expr_use_visitor.rs @@ -326,6 +326,10 @@ impl<'a, 'tcx> ExprUseVisitor<'a, 'tcx> { } } + hir::ExprKind::Become(call) => { + self.consume_expr(call); + } + hir::ExprKind::Assign(lhs, rhs, _) => { self.mutate_expr(lhs); self.consume_expr(rhs); diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs index b44c51ba9458..cf6d9eda321a 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs @@ -683,7 +683,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // inference variable. | ty::PredicateKind::ClosureKind(..) | ty::PredicateKind::Ambiguous - | ty::PredicateKind::TypeWellFormedFromEnv(..) => None, + | ty::PredicateKind::Clause(ty::ClauseKind::TypeWellFormedFromEnv(..)) => None, }, ) } diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/adjust_fulfillment_errors.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/adjust_fulfillment_errors.rs index 880437023c8b..223aedefea3d 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/adjust_fulfillment_errors.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/adjust_fulfillment_errors.rs @@ -25,16 +25,12 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let generics = self.tcx.generics_of(def_id); let predicate_substs = match unsubstituted_pred.kind().skip_binder() { - ty::PredicateKind::Clause(ty::ClauseKind::Trait(pred)) => { - pred.trait_ref.substs.to_vec() - } - ty::PredicateKind::Clause(ty::ClauseKind::Projection(pred)) => { - pred.projection_ty.substs.to_vec() - } - ty::PredicateKind::Clause(ty::ClauseKind::ConstArgHasType(arg, ty)) => { + ty::ClauseKind::Trait(pred) => pred.trait_ref.substs.to_vec(), + ty::ClauseKind::Projection(pred) => pred.projection_ty.substs.to_vec(), + ty::ClauseKind::ConstArgHasType(arg, ty) => { vec![ty.into(), arg.into()] } - ty::PredicateKind::Clause(ty::ClauseKind::ConstEvaluatable(e)) => vec![e.into()], + ty::ClauseKind::ConstEvaluatable(e) => vec![e.into()], _ => return false, }; @@ -512,11 +508,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // This shouldn't happen, but since this is only a diagnostic improvement, avoid breaking things. return Err(expr); } - let relevant_broken_predicate: ty::PredicateKind<'tcx> = - impl_predicates.predicates[impl_predicate_index].0.kind().skip_binder(); - match relevant_broken_predicate { - ty::PredicateKind::Clause(ty::ClauseKind::Trait(broken_trait)) => { + match impl_predicates.predicates[impl_predicate_index].0.kind().skip_binder() { + ty::ClauseKind::Trait(broken_trait) => { // ... self.blame_specific_part_of_expr_corresponding_to_generic_param( broken_trait.trait_ref.self_ty().into(), diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs index f294ff0051df..3c67280e0d4a 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs @@ -955,9 +955,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // - f(0, 1,) // + f() if only_extras_so_far - && errors + && !errors .peek() - .map_or(true, |next_error| !matches!(next_error, Error::Extra(_))) + .is_some_and(|next_error| matches!(next_error, Error::Extra(_))) { let next = provided_arg_tys .get(arg_idx + 1) @@ -1948,7 +1948,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // do that, so it's OK. for (predicate, span) in instantiated { - if let ty::PredicateKind::Clause(ty::ClauseKind::Trait(pred)) = predicate.kind().skip_binder() + if let ty::ClauseKind::Trait(pred) = predicate.kind().skip_binder() && pred.self_ty().peel_refs() == callee_ty && self.tcx.is_fn_trait(pred.def_id()) { diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs index d311ebe8c327..00a3f47b306b 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs @@ -226,9 +226,7 @@ impl<'a, 'tcx> AstConv<'tcx> for FnCtxt<'a, 'tcx> { predicates: tcx.arena.alloc_from_iter( self.param_env.caller_bounds().iter().filter_map(|predicate| { match predicate.kind().skip_binder() { - ty::PredicateKind::Clause(ty::ClauseKind::Trait(data)) - if data.self_ty().is_param(index) => - { + ty::ClauseKind::Trait(data) if data.self_ty().is_param(index) => { // HACK(eddyb) should get the original `Span`. let span = tcx.def_span(def_id); Some((predicate, span)) diff --git a/compiler/rustc_hir_typeck/src/generator_interior/drop_ranges/cfg_build.rs b/compiler/rustc_hir_typeck/src/generator_interior/drop_ranges/cfg_build.rs index 786a8c28f998..b84c49186495 100644 --- a/compiler/rustc_hir_typeck/src/generator_interior/drop_ranges/cfg_build.rs +++ b/compiler/rustc_hir_typeck/src/generator_interior/drop_ranges/cfg_build.rs @@ -214,6 +214,7 @@ impl<'a, 'tcx> DropRangeVisitor<'a, 'tcx> { | ExprKind::Break(..) | ExprKind::Continue(..) | ExprKind::Ret(..) + | ExprKind::Become(..) | ExprKind::InlineAsm(..) | ExprKind::OffsetOf(..) | ExprKind::Struct(..) @@ -451,6 +452,8 @@ impl<'a, 'tcx> Visitor<'tcx> for DropRangeVisitor<'a, 'tcx> { } } + ExprKind::Become(_call) => bug!("encountered a tail-call inside a generator"), + ExprKind::Call(f, args) => { self.visit_expr(f); for arg in args { diff --git a/compiler/rustc_hir_typeck/src/mem_categorization.rs b/compiler/rustc_hir_typeck/src/mem_categorization.rs index 78171e0b20e8..6c8589493cb0 100644 --- a/compiler/rustc_hir_typeck/src/mem_categorization.rs +++ b/compiler/rustc_hir_typeck/src/mem_categorization.rs @@ -361,6 +361,7 @@ impl<'a, 'tcx> MemCategorizationContext<'a, 'tcx> { | hir::ExprKind::AssignOp(..) | hir::ExprKind::Closure { .. } | hir::ExprKind::Ret(..) + | hir::ExprKind::Become(..) | hir::ExprKind::Unary(..) | hir::ExprKind::Yield(..) | hir::ExprKind::MethodCall(..) diff --git a/compiler/rustc_hir_typeck/src/method/confirm.rs b/compiler/rustc_hir_typeck/src/method/confirm.rs index 279ff849e3d5..31894d25b60d 100644 --- a/compiler/rustc_hir_typeck/src/method/confirm.rs +++ b/compiler/rustc_hir_typeck/src/method/confirm.rs @@ -606,9 +606,7 @@ impl<'a, 'tcx> ConfirmContext<'a, 'tcx> { traits::elaborate(self.tcx, predicates.predicates.iter().copied()) // We don't care about regions here. .filter_map(|pred| match pred.kind().skip_binder() { - ty::PredicateKind::Clause(ty::ClauseKind::Trait(trait_pred)) - if trait_pred.def_id() == sized_def_id => - { + ty::ClauseKind::Trait(trait_pred) if trait_pred.def_id() == sized_def_id => { let span = predicates .iter() .find_map(|(p, span)| if p == pred { Some(span) } else { None }) diff --git a/compiler/rustc_hir_typeck/src/method/probe.rs b/compiler/rustc_hir_typeck/src/method/probe.rs index 762176ecfc79..35d70968ce7d 100644 --- a/compiler/rustc_hir_typeck/src/method/probe.rs +++ b/compiler/rustc_hir_typeck/src/method/probe.rs @@ -834,7 +834,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> { let bounds = self.param_env.caller_bounds().iter().filter_map(|predicate| { let bound_predicate = predicate.kind(); match bound_predicate.skip_binder() { - ty::PredicateKind::Clause(ty::ClauseKind::Trait(trait_predicate)) => { + ty::ClauseKind::Trait(trait_predicate) => { match *trait_predicate.trait_ref.self_ty().kind() { ty::Param(p) if p == param_ty => { Some(bound_predicate.rebind(trait_predicate.trait_ref)) @@ -842,20 +842,13 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> { _ => None, } } - ty::PredicateKind::Subtype(..) - | ty::PredicateKind::Clause(ty::ClauseKind::ConstArgHasType(..)) - | ty::PredicateKind::Coerce(..) - | ty::PredicateKind::Clause(ty::ClauseKind::Projection(..)) - | ty::PredicateKind::Clause(ty::ClauseKind::RegionOutlives(..)) - | ty::PredicateKind::Clause(ty::ClauseKind::WellFormed(..)) - | ty::PredicateKind::ObjectSafe(..) - | ty::PredicateKind::ClosureKind(..) - | ty::PredicateKind::Clause(ty::ClauseKind::TypeOutlives(..)) - | ty::PredicateKind::Clause(ty::ClauseKind::ConstEvaluatable(..)) - | ty::PredicateKind::ConstEquate(..) - | ty::PredicateKind::Ambiguous - | ty::PredicateKind::AliasRelate(..) - | ty::PredicateKind::TypeWellFormedFromEnv(..) => None, + ty::ClauseKind::RegionOutlives(_) + | ty::ClauseKind::TypeOutlives(_) + | ty::ClauseKind::Projection(_) + | ty::ClauseKind::ConstArgHasType(_, _) + | ty::ClauseKind::WellFormed(_) + | ty::ClauseKind::ConstEvaluatable(_) + | ty::ClauseKind::TypeWellFormedFromEnv(_) => None, } }); diff --git a/compiler/rustc_hir_typeck/src/pat.rs b/compiler/rustc_hir_typeck/src/pat.rs index 2f9871a103a8..5af955d31348 100644 --- a/compiler/rustc_hir_typeck/src/pat.rs +++ b/compiler/rustc_hir_typeck/src/pat.rs @@ -393,8 +393,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // They can denote both statically and dynamically-sized byte arrays. let mut pat_ty = ty; if let hir::ExprKind::Lit(Spanned { node: ast::LitKind::ByteStr(..), .. }) = lt.kind { - if let ty::Ref(_, inner_ty, _) = *self.structurally_resolved_type(span, expected).kind() - && self.structurally_resolved_type(span, inner_ty).is_slice() + let expected = self.structurally_resolved_type(span, expected); + if let ty::Ref(_, inner_ty, _) = expected.kind() + && matches!(inner_ty.kind(), ty::Slice(_)) { let tcx = self.tcx; trace!(?lt.hir_id.local_id, "polymorphic byte string lit"); diff --git a/compiler/rustc_infer/src/infer/canonical/query_response.rs b/compiler/rustc_infer/src/infer/canonical/query_response.rs index 630014e23806..32054e6d1256 100644 --- a/compiler/rustc_infer/src/infer/canonical/query_response.rs +++ b/compiler/rustc_infer/src/infer/canonical/query_response.rs @@ -739,10 +739,8 @@ impl<'tcx> TypeRelatingDelegate<'tcx> for QueryTypeRelatingDelegate<'_, 'tcx> { self.obligations.push(Obligation { cause: self.cause.clone(), param_env: self.param_env, - predicate: ty::Binder::dummy(ty::PredicateKind::Clause( - ty::ClauseKind::RegionOutlives(ty::OutlivesPredicate(sup, sub)), - )) - .to_predicate(self.infcx.tcx), + predicate: ty::ClauseKind::RegionOutlives(ty::OutlivesPredicate(sup, sub)) + .to_predicate(self.infcx.tcx), recursion_depth: 0, }); } diff --git a/compiler/rustc_infer/src/infer/error_reporting/note_and_explain.rs b/compiler/rustc_infer/src/infer/error_reporting/note_and_explain.rs index 2a32f0b50473..7293de4c6c5e 100644 --- a/compiler/rustc_infer/src/infer/error_reporting/note_and_explain.rs +++ b/compiler/rustc_infer/src/infer/error_reporting/note_and_explain.rs @@ -139,7 +139,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { tcx, generics, diag, - &format!("{}", proj.self_ty()), + &proj.self_ty().to_string(), &path, None, matching_span, @@ -153,7 +153,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { tcx, generics, diag, - &format!("{}", proj.self_ty()), + &proj.self_ty().to_string(), &path, None, matching_span, diff --git a/compiler/rustc_infer/src/infer/mod.rs b/compiler/rustc_infer/src/infer/mod.rs index 9526ed144c34..7dbc18908d5f 100644 --- a/compiler/rustc_infer/src/infer/mod.rs +++ b/compiler/rustc_infer/src/infer/mod.rs @@ -1474,6 +1474,7 @@ impl<'tcx> InferCtxt<'tcx> { /// universes. Updates `self.universe` to that new universe. pub fn create_next_universe(&self) -> ty::UniverseIndex { let u = self.universe.get().next_universe(); + debug!("create_next_universe {u:?}"); self.universe.set(u); u } diff --git a/compiler/rustc_infer/src/infer/outlives/mod.rs b/compiler/rustc_infer/src/infer/outlives/mod.rs index d926f7f7cbd6..c998c9237608 100644 --- a/compiler/rustc_infer/src/infer/outlives/mod.rs +++ b/compiler/rustc_infer/src/infer/outlives/mod.rs @@ -20,27 +20,19 @@ pub fn explicit_outlives_bounds<'tcx>( param_env .caller_bounds() .into_iter() - .map(ty::Predicate::kind) + .map(ty::Clause::kind) .filter_map(ty::Binder::no_bound_vars) .filter_map(move |kind| match kind { - ty::PredicateKind::Clause(ty::ClauseKind::Projection(..)) - | ty::PredicateKind::Clause(ty::ClauseKind::Trait(..)) - | ty::PredicateKind::Clause(ty::ClauseKind::ConstArgHasType(..)) - | ty::PredicateKind::AliasRelate(..) - | ty::PredicateKind::Coerce(..) - | ty::PredicateKind::Subtype(..) - | ty::PredicateKind::Clause(ty::ClauseKind::WellFormed(..)) - | ty::PredicateKind::ObjectSafe(..) - | ty::PredicateKind::ClosureKind(..) - | ty::PredicateKind::Clause(ty::ClauseKind::TypeOutlives(..)) - | ty::PredicateKind::Clause(ty::ClauseKind::ConstEvaluatable(..)) - | ty::PredicateKind::ConstEquate(..) - | ty::PredicateKind::Ambiguous - | ty::PredicateKind::TypeWellFormedFromEnv(..) => None, - ty::PredicateKind::Clause(ty::ClauseKind::RegionOutlives(ty::OutlivesPredicate( - r_a, - r_b, - ))) => Some(OutlivesBound::RegionSubRegion(r_b, r_a)), + ty::ClauseKind::RegionOutlives(ty::OutlivesPredicate(r_a, r_b)) => { + Some(OutlivesBound::RegionSubRegion(r_b, r_a)) + } + ty::ClauseKind::Trait(_) + | ty::ClauseKind::TypeOutlives(_) + | ty::ClauseKind::Projection(_) + | ty::ClauseKind::ConstArgHasType(_, _) + | ty::ClauseKind::WellFormed(_) + | ty::ClauseKind::ConstEvaluatable(_) + | ty::ClauseKind::TypeWellFormedFromEnv(_) => None, }) } diff --git a/compiler/rustc_infer/src/infer/outlives/verify.rs b/compiler/rustc_infer/src/infer/outlives/verify.rs index 871171f9447f..1a5e2b520b80 100644 --- a/compiler/rustc_infer/src/infer/outlives/verify.rs +++ b/compiler/rustc_infer/src/infer/outlives/verify.rs @@ -223,7 +223,7 @@ impl<'cx, 'tcx> VerifyBoundCx<'cx, 'tcx> { // parameter environments are already elaborated, so we don't // have to worry about that. let c_b = self.param_env.caller_bounds(); - let param_bounds = self.collect_outlives_from_predicate_list(erased_ty, c_b.into_iter()); + let param_bounds = self.collect_outlives_from_clause_list(erased_ty, c_b.into_iter()); // Next, collect regions we scraped from the well-formedness // constraints in the fn signature. To do that, we walk the list @@ -307,15 +307,15 @@ impl<'cx, 'tcx> VerifyBoundCx<'cx, 'tcx> { /// when comparing `ty` for equality, so `ty` must be something /// that does not involve inference variables and where you /// otherwise want a precise match. - fn collect_outlives_from_predicate_list( + fn collect_outlives_from_clause_list( &self, erased_ty: Ty<'tcx>, - predicates: impl Iterator>, + clauses: impl Iterator>, ) -> impl Iterator, ty::Region<'tcx>>>> { let tcx = self.tcx; let param_env = self.param_env; - predicates.filter_map(|p| p.to_opt_type_outlives()).filter(move |outlives_predicate| { + clauses.filter_map(|p| p.as_type_outlives_clause()).filter(move |outlives_predicate| { super::test_type_match::can_match_erased_ty( tcx, param_env, diff --git a/compiler/rustc_infer/src/traits/util.rs b/compiler/rustc_infer/src/traits/util.rs index 269198729529..847b267b6144 100644 --- a/compiler/rustc_infer/src/traits/util.rs +++ b/compiler/rustc_infer/src/traits/util.rs @@ -258,7 +258,8 @@ impl<'tcx, O: Elaboratable<'tcx>> Elaborator<'tcx, O> { pred = pred.without_const(tcx); } elaboratable.child_with_derived_cause( - pred.subst_supertrait(tcx, &bound_predicate.rebind(data.trait_ref)), + pred.subst_supertrait(tcx, &bound_predicate.rebind(data.trait_ref)) + .as_predicate(), span, bound_predicate.rebind(data), index, @@ -367,7 +368,7 @@ impl<'tcx, O: Elaboratable<'tcx>> Elaborator<'tcx, O> { .map(|predicate| elaboratable.child(predicate)), ); } - ty::PredicateKind::TypeWellFormedFromEnv(..) => { + ty::PredicateKind::Clause(ty::ClauseKind::TypeWellFormedFromEnv(..)) => { // Nothing to elaborate } ty::PredicateKind::Ambiguous => {} @@ -440,7 +441,7 @@ pub fn transitive_bounds_that_define_assoc_item<'tcx>( tcx.super_predicates_that_define_assoc_item((trait_ref.def_id(), assoc_name)); for (super_predicate, _) in super_predicates.predicates { let subst_predicate = super_predicate.subst_supertrait(tcx, &trait_ref); - if let Some(binder) = subst_predicate.to_opt_poly_trait_pred() { + if let Some(binder) = subst_predicate.as_trait_clause() { stack.push(binder.map_bound(|t| t.trait_ref)); } } diff --git a/compiler/rustc_interface/src/interface.rs b/compiler/rustc_interface/src/interface.rs index 54dabb757643..ab5f64b383da 100644 --- a/compiler/rustc_interface/src/interface.rs +++ b/compiler/rustc_interface/src/interface.rs @@ -14,12 +14,11 @@ use rustc_middle::{bug, ty}; use rustc_parse::maybe_new_parser_from_source_str; use rustc_query_impl::QueryCtxt; use rustc_query_system::query::print_query_stack; -use rustc_session::config::{self, ErrorOutputType, Input, OutFileName, OutputFilenames}; -use rustc_session::config::{CheckCfg, ExpectedValues}; -use rustc_session::lint; +use rustc_session::config::{self, CheckCfg, ExpectedValues, Input, OutFileName, OutputFilenames}; use rustc_session::parse::{CrateConfig, ParseSess}; +use rustc_session::CompilerIO; use rustc_session::Session; -use rustc_session::{early_error, CompilerIO}; +use rustc_session::{lint, EarlyErrorHandler}; use rustc_span::source_map::{FileLoader, FileName}; use rustc_span::symbol::sym; use std::path::PathBuf; @@ -66,7 +65,10 @@ pub fn set_thread_safe_mode(sopts: &config::UnstableOptions) { } /// Converts strings provided as `--cfg [cfgspec]` into a `crate_cfg`. -pub fn parse_cfgspecs(cfgspecs: Vec) -> FxHashSet<(String, Option)> { +pub fn parse_cfgspecs( + handler: &EarlyErrorHandler, + cfgspecs: Vec, +) -> FxHashSet<(String, Option)> { rustc_span::create_default_session_if_not_set_then(move |_| { let cfg = cfgspecs .into_iter() @@ -78,10 +80,10 @@ pub fn parse_cfgspecs(cfgspecs: Vec) -> FxHashSet<(String, Option { - early_error( - ErrorOutputType::default(), - format!(concat!("invalid `--cfg` argument: `{}` (", $reason, ")"), s), - ); + handler.early_error(format!( + concat!("invalid `--cfg` argument: `{}` (", $reason, ")"), + s + )); }; } @@ -125,7 +127,7 @@ pub fn parse_cfgspecs(cfgspecs: Vec) -> FxHashSet<(String, Option) -> CheckCfg { +pub fn parse_check_cfg(handler: &EarlyErrorHandler, specs: Vec) -> CheckCfg { rustc_span::create_default_session_if_not_set_then(move |_| { let mut check_cfg = CheckCfg::default(); @@ -137,10 +139,10 @@ pub fn parse_check_cfg(specs: Vec) -> CheckCfg { macro_rules! error { ($reason: expr) => { - early_error( - ErrorOutputType::default(), - format!(concat!("invalid `--check-cfg` argument: `{}` (", $reason, ")"), s), - ) + handler.early_error(format!( + concat!("invalid `--check-cfg` argument: `{}` (", $reason, ")"), + s + )) }; } @@ -294,8 +296,11 @@ pub fn run_compiler(config: Config, f: impl FnOnce(&Compiler) -> R + Se let registry = &config.registry; + let handler = EarlyErrorHandler::new(config.opts.error_format); + let temps_dir = config.opts.unstable_opts.temps_dir.as_deref().map(PathBuf::from); let (mut sess, codegen_backend) = util::create_session( + &handler, config.opts, config.crate_cfg, config.crate_check_cfg, diff --git a/compiler/rustc_interface/src/tests.rs b/compiler/rustc_interface/src/tests.rs index 9d0c9ec97423..6054b48b0b53 100644 --- a/compiler/rustc_interface/src/tests.rs +++ b/compiler/rustc_interface/src/tests.rs @@ -21,8 +21,8 @@ use rustc_session::config::{InstrumentCoverage, Passes}; use rustc_session::lint::Level; use rustc_session::search_paths::SearchPath; use rustc_session::utils::{CanonicalizedPath, NativeLib, NativeLibKind}; -use rustc_session::CompilerIO; use rustc_session::{build_session, getopts, Session}; +use rustc_session::{CompilerIO, EarlyErrorHandler}; use rustc_span::edition::{Edition, DEFAULT_EDITION}; use rustc_span::symbol::sym; use rustc_span::FileName; @@ -36,15 +36,18 @@ use std::path::{Path, PathBuf}; type CfgSpecs = FxHashSet<(String, Option)>; -fn build_session_options_and_crate_config(matches: getopts::Matches) -> (Options, CfgSpecs) { - let sessopts = build_session_options(&matches); - let cfg = parse_cfgspecs(matches.opt_strs("cfg")); +fn build_session_options_and_crate_config( + handler: &mut EarlyErrorHandler, + matches: getopts::Matches, +) -> (Options, CfgSpecs) { + let sessopts = build_session_options(handler, &matches); + let cfg = parse_cfgspecs(handler, matches.opt_strs("cfg")); (sessopts, cfg) } -fn mk_session(matches: getopts::Matches) -> (Session, CfgSpecs) { +fn mk_session(handler: &mut EarlyErrorHandler, matches: getopts::Matches) -> (Session, CfgSpecs) { let registry = registry::Registry::new(&[]); - let (sessopts, cfg) = build_session_options_and_crate_config(matches); + let (sessopts, cfg) = build_session_options_and_crate_config(handler, matches); let temps_dir = sessopts.unstable_opts.temps_dir.as_deref().map(PathBuf::from); let io = CompilerIO { input: Input::Str { name: FileName::Custom(String::new()), input: String::new() }, @@ -52,8 +55,18 @@ fn mk_session(matches: getopts::Matches) -> (Session, CfgSpecs) { output_file: None, temps_dir, }; - let sess = - build_session(sessopts, io, None, registry, vec![], Default::default(), None, None, ""); + let sess = build_session( + handler, + sessopts, + io, + None, + registry, + vec![], + Default::default(), + None, + None, + "", + ); (sess, cfg) } @@ -120,7 +133,8 @@ fn assert_non_crate_hash_different(x: &Options, y: &Options) { fn test_switch_implies_cfg_test() { rustc_span::create_default_session_globals_then(|| { let matches = optgroups().parse(&["--test".to_string()]).unwrap(); - let (sess, cfg) = mk_session(matches); + let mut handler = EarlyErrorHandler::new(ErrorOutputType::default()); + let (sess, cfg) = mk_session(&mut handler, matches); let cfg = build_configuration(&sess, to_crate_config(cfg)); assert!(cfg.contains(&(sym::test, None))); }); @@ -131,7 +145,8 @@ fn test_switch_implies_cfg_test() { fn test_switch_implies_cfg_test_unless_cfg_test() { rustc_span::create_default_session_globals_then(|| { let matches = optgroups().parse(&["--test".to_string(), "--cfg=test".to_string()]).unwrap(); - let (sess, cfg) = mk_session(matches); + let mut handler = EarlyErrorHandler::new(ErrorOutputType::default()); + let (sess, cfg) = mk_session(&mut handler, matches); let cfg = build_configuration(&sess, to_crate_config(cfg)); let mut test_items = cfg.iter().filter(|&&(name, _)| name == sym::test); assert!(test_items.next().is_some()); @@ -143,20 +158,23 @@ fn test_switch_implies_cfg_test_unless_cfg_test() { fn test_can_print_warnings() { rustc_span::create_default_session_globals_then(|| { let matches = optgroups().parse(&["-Awarnings".to_string()]).unwrap(); - let (sess, _) = mk_session(matches); + let mut handler = EarlyErrorHandler::new(ErrorOutputType::default()); + let (sess, _) = mk_session(&mut handler, matches); assert!(!sess.diagnostic().can_emit_warnings()); }); rustc_span::create_default_session_globals_then(|| { let matches = optgroups().parse(&["-Awarnings".to_string(), "-Dwarnings".to_string()]).unwrap(); - let (sess, _) = mk_session(matches); + let mut handler = EarlyErrorHandler::new(ErrorOutputType::default()); + let (sess, _) = mk_session(&mut handler, matches); assert!(sess.diagnostic().can_emit_warnings()); }); rustc_span::create_default_session_globals_then(|| { let matches = optgroups().parse(&["-Adead_code".to_string()]).unwrap(); - let (sess, _) = mk_session(matches); + let mut handler = EarlyErrorHandler::new(ErrorOutputType::default()); + let (sess, _) = mk_session(&mut handler, matches); assert!(sess.diagnostic().can_emit_warnings()); }); } @@ -302,35 +320,36 @@ fn test_search_paths_tracking_hash_different_order() { let mut v3 = Options::default(); let mut v4 = Options::default(); + let handler = EarlyErrorHandler::new(JSON); const JSON: ErrorOutputType = ErrorOutputType::Json { pretty: false, json_rendered: HumanReadableErrorType::Default(ColorConfig::Never), }; // Reference - v1.search_paths.push(SearchPath::from_cli_opt("native=abc", JSON)); - v1.search_paths.push(SearchPath::from_cli_opt("crate=def", JSON)); - v1.search_paths.push(SearchPath::from_cli_opt("dependency=ghi", JSON)); - v1.search_paths.push(SearchPath::from_cli_opt("framework=jkl", JSON)); - v1.search_paths.push(SearchPath::from_cli_opt("all=mno", JSON)); + v1.search_paths.push(SearchPath::from_cli_opt(&handler, "native=abc")); + v1.search_paths.push(SearchPath::from_cli_opt(&handler, "crate=def")); + v1.search_paths.push(SearchPath::from_cli_opt(&handler, "dependency=ghi")); + v1.search_paths.push(SearchPath::from_cli_opt(&handler, "framework=jkl")); + v1.search_paths.push(SearchPath::from_cli_opt(&handler, "all=mno")); - v2.search_paths.push(SearchPath::from_cli_opt("native=abc", JSON)); - v2.search_paths.push(SearchPath::from_cli_opt("dependency=ghi", JSON)); - v2.search_paths.push(SearchPath::from_cli_opt("crate=def", JSON)); - v2.search_paths.push(SearchPath::from_cli_opt("framework=jkl", JSON)); - v2.search_paths.push(SearchPath::from_cli_opt("all=mno", JSON)); + v2.search_paths.push(SearchPath::from_cli_opt(&handler, "native=abc")); + v2.search_paths.push(SearchPath::from_cli_opt(&handler, "dependency=ghi")); + v2.search_paths.push(SearchPath::from_cli_opt(&handler, "crate=def")); + v2.search_paths.push(SearchPath::from_cli_opt(&handler, "framework=jkl")); + v2.search_paths.push(SearchPath::from_cli_opt(&handler, "all=mno")); - v3.search_paths.push(SearchPath::from_cli_opt("crate=def", JSON)); - v3.search_paths.push(SearchPath::from_cli_opt("framework=jkl", JSON)); - v3.search_paths.push(SearchPath::from_cli_opt("native=abc", JSON)); - v3.search_paths.push(SearchPath::from_cli_opt("dependency=ghi", JSON)); - v3.search_paths.push(SearchPath::from_cli_opt("all=mno", JSON)); + v3.search_paths.push(SearchPath::from_cli_opt(&handler, "crate=def")); + v3.search_paths.push(SearchPath::from_cli_opt(&handler, "framework=jkl")); + v3.search_paths.push(SearchPath::from_cli_opt(&handler, "native=abc")); + v3.search_paths.push(SearchPath::from_cli_opt(&handler, "dependency=ghi")); + v3.search_paths.push(SearchPath::from_cli_opt(&handler, "all=mno")); - v4.search_paths.push(SearchPath::from_cli_opt("all=mno", JSON)); - v4.search_paths.push(SearchPath::from_cli_opt("native=abc", JSON)); - v4.search_paths.push(SearchPath::from_cli_opt("crate=def", JSON)); - v4.search_paths.push(SearchPath::from_cli_opt("dependency=ghi", JSON)); - v4.search_paths.push(SearchPath::from_cli_opt("framework=jkl", JSON)); + v4.search_paths.push(SearchPath::from_cli_opt(&handler, "all=mno")); + v4.search_paths.push(SearchPath::from_cli_opt(&handler, "native=abc")); + v4.search_paths.push(SearchPath::from_cli_opt(&handler, "crate=def")); + v4.search_paths.push(SearchPath::from_cli_opt(&handler, "dependency=ghi")); + v4.search_paths.push(SearchPath::from_cli_opt(&handler, "framework=jkl")); assert_same_hash(&v1, &v2); assert_same_hash(&v1, &v3); @@ -851,7 +870,9 @@ fn test_edition_parsing() { let options = Options::default(); assert!(options.edition == DEFAULT_EDITION); + let mut handler = EarlyErrorHandler::new(ErrorOutputType::default()); + let matches = optgroups().parse(&["--edition=2018".to_string()]).unwrap(); - let (sessopts, _) = build_session_options_and_crate_config(matches); + let (sessopts, _) = build_session_options_and_crate_config(&mut handler, matches); assert!(sessopts.edition == Edition::Edition2018) } diff --git a/compiler/rustc_interface/src/util.rs b/compiler/rustc_interface/src/util.rs index 87252fefb1e2..035ea2414f76 100644 --- a/compiler/rustc_interface/src/util.rs +++ b/compiler/rustc_interface/src/util.rs @@ -11,16 +11,16 @@ use rustc_parse::validate_attr; use rustc_session as session; use rustc_session::config::CheckCfg; use rustc_session::config::{self, CrateType}; -use rustc_session::config::{ErrorOutputType, OutFileName, OutputFilenames, OutputTypes}; +use rustc_session::config::{OutFileName, OutputFilenames, OutputTypes}; use rustc_session::filesearch::sysroot_candidates; use rustc_session::lint::{self, BuiltinLintDiagnostics, LintBuffer}; use rustc_session::parse::CrateConfig; -use rustc_session::{early_error, filesearch, output, Session}; +use rustc_session::{filesearch, output, Session}; use rustc_span::edit_distance::find_best_match_for_name; use rustc_span::edition::Edition; use rustc_span::source_map::FileLoader; use rustc_span::symbol::{sym, Symbol}; -use session::CompilerIO; +use session::{CompilerIO, EarlyErrorHandler}; use std::env; use std::env::consts::{DLL_PREFIX, DLL_SUFFIX}; use std::mem; @@ -58,6 +58,7 @@ pub fn add_configuration( } pub fn create_session( + handler: &EarlyErrorHandler, sopts: config::Options, cfg: FxHashSet<(String, Option)>, check_cfg: CheckCfg, @@ -73,7 +74,11 @@ pub fn create_session( let codegen_backend = if let Some(make_codegen_backend) = make_codegen_backend { make_codegen_backend(&sopts) } else { - get_codegen_backend(&sopts.maybe_sysroot, sopts.unstable_opts.codegen_backend.as_deref()) + get_codegen_backend( + handler, + &sopts.maybe_sysroot, + sopts.unstable_opts.codegen_backend.as_deref(), + ) }; // target_override is documented to be called before init(), so this is okay @@ -88,7 +93,7 @@ pub fn create_session( ) { Ok(bundle) => bundle, Err(e) => { - early_error(sopts.error_format, format!("failed to load fluent bundle: {e}")); + handler.early_error(format!("failed to load fluent bundle: {e}")); } }; @@ -96,6 +101,7 @@ pub fn create_session( locale_resources.push(codegen_backend.locale_resource()); let mut sess = session::build_session( + handler, sopts, io, bundle, @@ -218,16 +224,16 @@ pub(crate) fn run_in_thread_pool_with_globals R + Send, R: Send>( }) } -fn load_backend_from_dylib(path: &Path) -> MakeBackendFn { +fn load_backend_from_dylib(handler: &EarlyErrorHandler, path: &Path) -> MakeBackendFn { let lib = unsafe { Library::new(path) }.unwrap_or_else(|err| { let err = format!("couldn't load codegen backend {path:?}: {err}"); - early_error(ErrorOutputType::default(), err); + handler.early_error(err); }); let backend_sym = unsafe { lib.get::(b"__rustc_codegen_backend") } .unwrap_or_else(|e| { let err = format!("couldn't load codegen backend: {e}"); - early_error(ErrorOutputType::default(), err); + handler.early_error(err); }); // Intentionally leak the dynamic library. We can't ever unload it @@ -242,6 +248,7 @@ fn load_backend_from_dylib(path: &Path) -> MakeBackendFn { /// /// A name of `None` indicates that the default backend should be used. pub fn get_codegen_backend( + handler: &EarlyErrorHandler, maybe_sysroot: &Option, backend_name: Option<&str>, ) -> Box { @@ -251,10 +258,12 @@ pub fn get_codegen_backend( let default_codegen_backend = option_env!("CFG_DEFAULT_CODEGEN_BACKEND").unwrap_or("llvm"); match backend_name.unwrap_or(default_codegen_backend) { - filename if filename.contains('.') => load_backend_from_dylib(filename.as_ref()), + filename if filename.contains('.') => { + load_backend_from_dylib(handler, filename.as_ref()) + } #[cfg(feature = "llvm")] "llvm" => rustc_codegen_llvm::LlvmCodegenBackend::new, - backend_name => get_codegen_sysroot(maybe_sysroot, backend_name), + backend_name => get_codegen_sysroot(handler, maybe_sysroot, backend_name), } }); @@ -286,7 +295,11 @@ fn get_rustc_path_inner(bin_path: &str) -> Option { }) } -fn get_codegen_sysroot(maybe_sysroot: &Option, backend_name: &str) -> MakeBackendFn { +fn get_codegen_sysroot( + handler: &EarlyErrorHandler, + maybe_sysroot: &Option, + backend_name: &str, +) -> MakeBackendFn { // For now we only allow this function to be called once as it'll dlopen a // few things, which seems to work best if we only do that once. In // general this assertion never trips due to the once guard in `get_codegen_backend`, @@ -321,7 +334,7 @@ fn get_codegen_sysroot(maybe_sysroot: &Option, backend_name: &str) -> M "failed to find a `codegen-backends` folder \ in the sysroot candidates:\n* {candidates}" ); - early_error(ErrorOutputType::default(), err); + handler.early_error(err); }); info!("probing {} for a codegen backend", sysroot.display()); @@ -332,7 +345,7 @@ fn get_codegen_sysroot(maybe_sysroot: &Option, backend_name: &str) -> M sysroot.display(), e ); - early_error(ErrorOutputType::default(), err); + handler.early_error(err); }); let mut file: Option = None; @@ -360,16 +373,16 @@ fn get_codegen_sysroot(maybe_sysroot: &Option, backend_name: &str) -> M prev.display(), path.display() ); - early_error(ErrorOutputType::default(), err); + handler.early_error(err); } file = Some(path.clone()); } match file { - Some(ref s) => load_backend_from_dylib(s), + Some(ref s) => load_backend_from_dylib(handler, s), None => { let err = format!("unsupported builtin codegen backend `{backend_name}`"); - early_error(ErrorOutputType::default(), err); + handler.early_error(err); } } } diff --git a/compiler/rustc_lint/src/builtin.rs b/compiler/rustc_lint/src/builtin.rs index 5c5ec4528504..53aad6d8b31f 100644 --- a/compiler/rustc_lint/src/builtin.rs +++ b/compiler/rustc_lint/src/builtin.rs @@ -1593,33 +1593,25 @@ declare_lint_pass!( impl<'tcx> LateLintPass<'tcx> for TrivialConstraints { fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx hir::Item<'tcx>) { use rustc_middle::ty::ClauseKind; - use rustc_middle::ty::PredicateKind::*; if cx.tcx.features().trivial_bounds { let predicates = cx.tcx.predicates_of(item.owner_id); for &(predicate, span) in predicates.predicates { let predicate_kind_name = match predicate.kind().skip_binder() { - Clause(ClauseKind::Trait(..)) => "trait", - Clause(ClauseKind::TypeOutlives(..)) | - Clause(ClauseKind::RegionOutlives(..)) => "lifetime", + ClauseKind::Trait(..) => "trait", + ClauseKind::TypeOutlives(..) | + ClauseKind::RegionOutlives(..) => "lifetime", // `ConstArgHasType` is never global as `ct` is always a param - Clause(ClauseKind::ConstArgHasType(..)) | + ClauseKind::ConstArgHasType(..) // Ignore projections, as they can only be global // if the trait bound is global - Clause(ClauseKind::Projection(..)) | + | ClauseKind::Projection(..) // Ignore bounds that a user can't type - Clause(ClauseKind::WellFormed(..)) | + | ClauseKind::WellFormed(..) // FIXME(generic_const_exprs): `ConstEvaluatable` can be written - Clause(ClauseKind::ConstEvaluatable(..)) | - AliasRelate(..) | - ObjectSafe(..) | - ClosureKind(..) | - Subtype(..) | - Coerce(..) | - ConstEquate(..) | - Ambiguous | - TypeWellFormedFromEnv(..) => continue, + | ClauseKind::ConstEvaluatable(..) + | ClauseKind::TypeWellFormedFromEnv(_) => continue, }; if predicate.is_global() { cx.emit_spanned_lint( diff --git a/compiler/rustc_lint/src/lints.rs b/compiler/rustc_lint/src/lints.rs index 49597516b360..0613ef2c5e95 100644 --- a/compiler/rustc_lint/src/lints.rs +++ b/compiler/rustc_lint/src/lints.rs @@ -10,7 +10,7 @@ use rustc_errors::{ use rustc_hir::def_id::DefId; use rustc_macros::{LintDiagnostic, Subdiagnostic}; use rustc_middle::ty::{ - inhabitedness::InhabitedPredicate, PolyExistentialTraitRef, Predicate, Ty, TyCtxt, + inhabitedness::InhabitedPredicate, Clause, PolyExistentialTraitRef, Ty, TyCtxt, }; use rustc_session::parse::ParseSess; use rustc_span::{edition::Edition, sym, symbol::Ident, Span, Symbol}; @@ -352,7 +352,7 @@ impl AddToDiagnostic for BuiltinTypeAliasGenericBoundsSuggestion { #[diag(lint_builtin_trivial_bounds)] pub struct BuiltinTrivialBounds<'a> { pub predicate_kind_name: &'a str, - pub predicate: Predicate<'a>, + pub predicate: Clause<'a>, } #[derive(LintDiagnostic)] @@ -1262,7 +1262,7 @@ pub struct RedundantSemicolonsDiag { // traits.rs pub struct DropTraitConstraintsDiag<'a> { - pub predicate: Predicate<'a>, + pub predicate: Clause<'a>, pub tcx: TyCtxt<'a>, pub def_id: DefId, } diff --git a/compiler/rustc_lint/src/multiple_supertrait_upcastable.rs b/compiler/rustc_lint/src/multiple_supertrait_upcastable.rs index c2ed0e19f401..53fe0ceb2340 100644 --- a/compiler/rustc_lint/src/multiple_supertrait_upcastable.rs +++ b/compiler/rustc_lint/src/multiple_supertrait_upcastable.rs @@ -45,7 +45,7 @@ impl<'tcx> LateLintPass<'tcx> for MultipleSupertraitUpcastable { .super_predicates_of(def_id) .predicates .into_iter() - .filter_map(|(pred, _)| pred.to_opt_poly_trait_pred()); + .filter_map(|(pred, _)| pred.as_trait_clause()); if direct_super_traits_iter.count() > 1 { cx.emit_spanned_lint( MULTIPLE_SUPERTRAIT_UPCASTABLE, diff --git a/compiler/rustc_lint/src/traits.rs b/compiler/rustc_lint/src/traits.rs index 8aba53495785..de11208062dc 100644 --- a/compiler/rustc_lint/src/traits.rs +++ b/compiler/rustc_lint/src/traits.rs @@ -88,11 +88,10 @@ declare_lint_pass!( impl<'tcx> LateLintPass<'tcx> for DropTraitConstraints { fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx hir::Item<'tcx>) { use rustc_middle::ty::ClauseKind; - use rustc_middle::ty::PredicateKind::*; let predicates = cx.tcx.explicit_predicates_of(item.owner_id); for &(predicate, span) in predicates.predicates { - let Clause(ClauseKind::Trait(trait_predicate)) = predicate.kind().skip_binder() else { + let ClauseKind::Trait(trait_predicate) = predicate.kind().skip_binder() else { continue }; let def_id = trait_predicate.trait_ref.def_id; diff --git a/compiler/rustc_macros/src/diagnostics/diagnostic.rs b/compiler/rustc_macros/src/diagnostics/diagnostic.rs index 12a954258d1d..04b7c5feebe5 100644 --- a/compiler/rustc_macros/src/diagnostics/diagnostic.rs +++ b/compiler/rustc_macros/src/diagnostics/diagnostic.rs @@ -1,5 +1,7 @@ #![deny(unused_must_use)] +use std::cell::RefCell; + use crate::diagnostics::diagnostic_builder::{DiagnosticDeriveBuilder, DiagnosticDeriveKind}; use crate::diagnostics::error::{span_err, DiagnosticDeriveError}; use crate::diagnostics::utils::SetOnce; @@ -28,6 +30,7 @@ impl<'a> DiagnosticDerive<'a> { pub(crate) fn into_tokens(self) -> TokenStream { let DiagnosticDerive { mut structure, mut builder } = self; + let slugs = RefCell::new(Vec::new()); let implementation = builder.each_variant(&mut structure, |mut builder, variant| { let preamble = builder.preamble(variant); let body = builder.body(variant); @@ -56,6 +59,7 @@ impl<'a> DiagnosticDerive<'a> { return DiagnosticDeriveError::ErrorHandled.to_compile_error(); } Some(slug) => { + slugs.borrow_mut().push(slug.clone()); quote! { let mut #diag = #handler.struct_diagnostic(crate::fluent_generated::#slug); } @@ -73,7 +77,8 @@ impl<'a> DiagnosticDerive<'a> { }); let DiagnosticDeriveKind::Diagnostic { handler } = &builder.kind else { unreachable!() }; - structure.gen_impl(quote! { + + let mut imp = structure.gen_impl(quote! { gen impl<'__diagnostic_handler_sess, G> rustc_errors::IntoDiagnostic<'__diagnostic_handler_sess, G> for @Self @@ -89,7 +94,11 @@ impl<'a> DiagnosticDerive<'a> { #implementation } } - }) + }); + for test in slugs.borrow().iter().map(|s| generate_test(s, &structure)) { + imp.extend(test); + } + imp } } @@ -124,6 +133,7 @@ impl<'a> LintDiagnosticDerive<'a> { } }); + let slugs = RefCell::new(Vec::new()); let msg = builder.each_variant(&mut structure, |mut builder, variant| { // Collect the slug by generating the preamble. let _ = builder.preamble(variant); @@ -148,6 +158,7 @@ impl<'a> LintDiagnosticDerive<'a> { DiagnosticDeriveError::ErrorHandled.to_compile_error() } Some(slug) => { + slugs.borrow_mut().push(slug.clone()); quote! { crate::fluent_generated::#slug.into() } @@ -156,7 +167,7 @@ impl<'a> LintDiagnosticDerive<'a> { }); let diag = &builder.diag; - structure.gen_impl(quote! { + let mut imp = structure.gen_impl(quote! { gen impl<'__a> rustc_errors::DecorateLint<'__a, ()> for @Self { #[track_caller] fn decorate_lint<'__b>( @@ -171,7 +182,12 @@ impl<'a> LintDiagnosticDerive<'a> { #msg } } - }) + }); + for test in slugs.borrow().iter().map(|s| generate_test(s, &structure)) { + imp.extend(test); + } + + imp } } @@ -198,3 +214,40 @@ impl Mismatch { } } } + +/// Generates a `#[test]` that verifies that all referenced variables +/// exist on this structure. +fn generate_test(slug: &syn::Path, structure: &Structure<'_>) -> TokenStream { + // FIXME: We can't identify variables in a subdiagnostic + for field in structure.variants().iter().flat_map(|v| v.ast().fields.iter()) { + for attr_name in field.attrs.iter().filter_map(|at| at.path().get_ident()) { + if attr_name == "subdiagnostic" { + return quote!(); + } + } + } + use std::sync::atomic::{AtomicUsize, Ordering}; + // We need to make sure that the same diagnostic slug can be used multiple times without causing an + // error, so just have a global counter here. + static COUNTER: AtomicUsize = AtomicUsize::new(0); + let slug = slug.get_ident().unwrap(); + let ident = quote::format_ident!("verify_{slug}_{}", COUNTER.fetch_add(1, Ordering::Relaxed)); + let ref_slug = quote::format_ident!("{slug}_refs"); + let struct_name = &structure.ast().ident; + let variables: Vec<_> = structure + .variants() + .iter() + .flat_map(|v| v.ast().fields.iter().filter_map(|f| f.ident.as_ref().map(|i| i.to_string()))) + .collect(); + // tidy errors on `#[test]` outside of test files, so we use `#[test ]` to work around this + quote! { + #[cfg(test)] + #[test ] + fn #ident() { + let variables = [#(#variables),*]; + for vref in crate::fluent_generated::#ref_slug { + assert!(variables.contains(vref), "{}: variable `{vref}` not found ({})", stringify!(#struct_name), stringify!(#slug)); + } + } + } +} diff --git a/compiler/rustc_metadata/src/rmeta/decoder.rs b/compiler/rustc_metadata/src/rmeta/decoder.rs index 90014bd92671..b9318aee5813 100644 --- a/compiler/rustc_metadata/src/rmeta/decoder.rs +++ b/compiler/rustc_metadata/src/rmeta/decoder.rs @@ -636,12 +636,6 @@ impl<'a, 'tcx> Decodable> for Symbol { } } -impl<'a, 'tcx> Decodable> for &'tcx [(ty::Predicate<'tcx>, Span)] { - fn decode(d: &mut DecodeContext<'a, 'tcx>) -> Self { - ty::codec::RefDecodable::decode(d) - } -} - impl<'a, 'tcx> Decodable> for &'tcx [(ty::Clause<'tcx>, Span)] { fn decode(d: &mut DecodeContext<'a, 'tcx>) -> Self { ty::codec::RefDecodable::decode(d) diff --git a/compiler/rustc_middle/src/arena.rs b/compiler/rustc_middle/src/arena.rs index ac4cef34fdd3..5a320865c95a 100644 --- a/compiler/rustc_middle/src/arena.rs +++ b/compiler/rustc_middle/src/arena.rs @@ -83,9 +83,9 @@ macro_rules! arena_types { rustc_middle::infer::canonical::Canonical<'tcx, rustc_middle::infer::canonical::QueryResponse<'tcx, rustc_middle::ty::FnSig<'tcx>> >, - [] type_op_normalize_predicate: + [] type_op_normalize_clause: rustc_middle::infer::canonical::Canonical<'tcx, - rustc_middle::infer::canonical::QueryResponse<'tcx, rustc_middle::ty::Predicate<'tcx>> + rustc_middle::infer::canonical::QueryResponse<'tcx, rustc_middle::ty::Clause<'tcx>> >, [] type_op_normalize_ty: rustc_middle::infer::canonical::Canonical<'tcx, diff --git a/compiler/rustc_middle/src/lint.rs b/compiler/rustc_middle/src/lint.rs index caf3fc26039a..81c1ae4f6300 100644 --- a/compiler/rustc_middle/src/lint.rs +++ b/compiler/rustc_middle/src/lint.rs @@ -388,10 +388,11 @@ pub fn struct_lint_level( // it'll become a hard error, so we have to emit *something*. Also, // if this lint occurs in the expansion of a macro from an external crate, // allow individual lints to opt-out from being reported. - let not_future_incompatible = - future_incompatible.map(|f| f.reason.edition().is_some()).unwrap_or(true); - if not_future_incompatible && !lint.report_in_external_macro { + let incompatible = future_incompatible.is_some_and(|f| f.reason.edition().is_none()); + + if !incompatible && !lint.report_in_external_macro { err.cancel(); + // Don't continue further, since we don't want to have // `diag_span_note_once` called for a diagnostic that isn't emitted. return; diff --git a/compiler/rustc_middle/src/mir/terminator.rs b/compiler/rustc_middle/src/mir/terminator.rs index 561ef371b090..1b9c1438f406 100644 --- a/compiler/rustc_middle/src/mir/terminator.rs +++ b/compiler/rustc_middle/src/mir/terminator.rs @@ -272,7 +272,8 @@ impl<'tcx> Debug for TerminatorKind<'tcx> { let unwind = match self.unwind() { // Not needed or included in successors - None | Some(UnwindAction::Continue) | Some(UnwindAction::Cleanup(_)) => None, + None | Some(UnwindAction::Cleanup(_)) => None, + Some(UnwindAction::Continue) => Some("unwind continue"), Some(UnwindAction::Unreachable) => Some("unwind unreachable"), Some(UnwindAction::Terminate) => Some("unwind terminate"), }; diff --git a/compiler/rustc_middle/src/mir/visit.rs b/compiler/rustc_middle/src/mir/visit.rs index b030d1e6c3ed..205dc9ec7465 100644 --- a/compiler/rustc_middle/src/mir/visit.rs +++ b/compiler/rustc_middle/src/mir/visit.rs @@ -1133,13 +1133,12 @@ macro_rules! visit_place_fns { fn visit_projection_elem( &mut self, - local: Local, - proj_base: &[PlaceElem<'tcx>], + place_ref: PlaceRef<'tcx>, elem: PlaceElem<'tcx>, context: PlaceContext, location: Location, ) { - self.super_projection_elem(local, proj_base, elem, context, location); + self.super_projection_elem(place_ref, elem, context, location); } fn super_place(&mut self, place: &Place<'tcx>, context: PlaceContext, location: Location) { @@ -1168,15 +1167,13 @@ macro_rules! visit_place_fns { location: Location, ) { for (base, elem) in place_ref.iter_projections().rev() { - let base_proj = base.projection; - self.visit_projection_elem(place_ref.local, base_proj, elem, context, location); + self.visit_projection_elem(base, elem, context, location); } } fn super_projection_elem( &mut self, - _local: Local, - _proj_base: &[PlaceElem<'tcx>], + _place_ref: PlaceRef<'tcx>, elem: PlaceElem<'tcx>, _context: PlaceContext, location: Location, diff --git a/compiler/rustc_middle/src/query/keys.rs b/compiler/rustc_middle/src/query/keys.rs index fa62b7f32b1a..4006a6cd1cc1 100644 --- a/compiler/rustc_middle/src/query/keys.rs +++ b/compiler/rustc_middle/src/query/keys.rs @@ -420,7 +420,7 @@ impl<'tcx> Key for (Ty<'tcx>, Ty<'tcx>) { } } -impl<'tcx> Key for &'tcx ty::List> { +impl<'tcx> Key for &'tcx ty::List> { type CacheSelector = DefaultCacheSelector; fn default_span(&self, _: TyCtxt<'_>) -> Span { diff --git a/compiler/rustc_middle/src/query/mod.rs b/compiler/rustc_middle/src/query/mod.rs index 5d6a477b9ad9..15215552f528 100644 --- a/compiler/rustc_middle/src/query/mod.rs +++ b/compiler/rustc_middle/src/query/mod.rs @@ -2031,10 +2031,10 @@ rustc_queries! { } /// Do not call this query directly: part of the `Normalize` type-op - query type_op_normalize_predicate( - goal: CanonicalTypeOpNormalizeGoal<'tcx, ty::Predicate<'tcx>> + query type_op_normalize_clause( + goal: CanonicalTypeOpNormalizeGoal<'tcx, ty::Clause<'tcx>> ) -> Result< - &'tcx Canonical<'tcx, canonical::QueryResponse<'tcx, ty::Predicate<'tcx>>>, + &'tcx Canonical<'tcx, canonical::QueryResponse<'tcx, ty::Clause<'tcx>>>, NoSolution, > { desc { "normalizing `{:?}`", goal.value.value.value } @@ -2125,7 +2125,7 @@ rustc_queries! { desc { "resolving instance `{}`", ty::Instance::new(key.value.0, key.value.1) } } - query reveal_opaque_types_in_bounds(key: &'tcx ty::List>) -> &'tcx ty::List> { + query reveal_opaque_types_in_bounds(key: &'tcx ty::List>) -> &'tcx ty::List> { desc { "revealing opaque types in `{:?}`", key } } diff --git a/compiler/rustc_middle/src/query/on_disk_cache.rs b/compiler/rustc_middle/src/query/on_disk_cache.rs index 220118ae5ccb..8751d3b78901 100644 --- a/compiler/rustc_middle/src/query/on_disk_cache.rs +++ b/compiler/rustc_middle/src/query/on_disk_cache.rs @@ -791,13 +791,6 @@ impl<'a, 'tcx> Decodable> } } -impl<'a, 'tcx> Decodable> for &'tcx [(ty::Predicate<'tcx>, Span)] { - #[inline] - fn decode(d: &mut CacheDecoder<'a, 'tcx>) -> Self { - RefDecodable::decode(d) - } -} - impl<'a, 'tcx> Decodable> for &'tcx [(ty::Clause<'tcx>, Span)] { #[inline] fn decode(d: &mut CacheDecoder<'a, 'tcx>) -> Self { diff --git a/compiler/rustc_middle/src/thir.rs b/compiler/rustc_middle/src/thir.rs index 813e109c41e1..0f3ad6d0151d 100644 --- a/compiler/rustc_middle/src/thir.rs +++ b/compiler/rustc_middle/src/thir.rs @@ -410,6 +410,10 @@ pub enum ExprKind<'tcx> { Return { value: Option, }, + /// A `become` expression. + Become { + value: ExprId, + }, /// An inline `const` block, e.g. `const {}`. ConstBlock { did: DefId, diff --git a/compiler/rustc_middle/src/thir/visit.rs b/compiler/rustc_middle/src/thir/visit.rs index 5c7ec31cf93d..9cc07677e0e3 100644 --- a/compiler/rustc_middle/src/thir/visit.rs +++ b/compiler/rustc_middle/src/thir/visit.rs @@ -100,6 +100,7 @@ pub fn walk_expr<'a, 'tcx: 'a, V: Visitor<'a, 'tcx>>(visitor: &mut V, expr: &Exp visitor.visit_expr(&visitor.thir()[value]) } } + Become { value } => visitor.visit_expr(&visitor.thir()[value]), ConstBlock { did: _, substs: _ } => {} Repeat { value, count: _ } => { visitor.visit_expr(&visitor.thir()[value]); diff --git a/compiler/rustc_middle/src/traits/chalk.rs b/compiler/rustc_middle/src/traits/chalk.rs index fcc8f457a8b7..6e3d2d91ae96 100644 --- a/compiler/rustc_middle/src/traits/chalk.rs +++ b/compiler/rustc_middle/src/traits/chalk.rs @@ -385,7 +385,7 @@ impl<'tcx> chalk_ir::interner::HasInterner for RustInterner<'tcx> { /// A chalk environment and goal. #[derive(Copy, Clone, PartialEq, Eq, Hash, Debug, HashStable, TypeFoldable, TypeVisitable)] pub struct ChalkEnvironmentAndGoal<'tcx> { - pub environment: &'tcx ty::List>, + pub environment: &'tcx ty::List>, pub goal: ty::Predicate<'tcx>, } diff --git a/compiler/rustc_middle/src/traits/util.rs b/compiler/rustc_middle/src/traits/util.rs index d54b8c599d95..05c06efaf163 100644 --- a/compiler/rustc_middle/src/traits/util.rs +++ b/compiler/rustc_middle/src/traits/util.rs @@ -25,9 +25,7 @@ impl<'tcx> Elaborator<'tcx> { .super_predicates_of(trait_ref.def_id()) .predicates .into_iter() - .flat_map(|(pred, _)| { - pred.subst_supertrait(self.tcx, &trait_ref).to_opt_poly_trait_pred() - }) + .flat_map(|(pred, _)| pred.subst_supertrait(self.tcx, &trait_ref).as_trait_clause()) .map(|t| t.map_bound(|pred| pred.trait_ref)) .filter(|supertrait_ref| self.visited.insert(*supertrait_ref)); diff --git a/compiler/rustc_middle/src/ty/codec.rs b/compiler/rustc_middle/src/ty/codec.rs index 248251e1ef5a..22bed6ad1c5e 100644 --- a/compiler/rustc_middle/src/ty/codec.rs +++ b/compiler/rustc_middle/src/ty/codec.rs @@ -368,16 +368,6 @@ impl<'tcx, D: TyDecoder>> Decodable for AdtDef<'tcx> { } } -impl<'tcx, D: TyDecoder>> RefDecodable<'tcx, D> - for [(ty::Predicate<'tcx>, Span)] -{ - fn decode(decoder: &mut D) -> &'tcx Self { - decoder.interner().arena.alloc_from_iter( - (0..decoder.read_usize()).map(|_| Decodable::decode(decoder)).collect::>(), - ) - } -} - impl<'tcx, D: TyDecoder>> RefDecodable<'tcx, D> for [(ty::Clause<'tcx>, Span)] { fn decode(decoder: &mut D) -> &'tcx Self { decoder.interner().arena.alloc_from_iter( @@ -406,11 +396,11 @@ impl<'tcx, D: TyDecoder>> RefDecodable<'tcx, D> for ty::List>> RefDecodable<'tcx, D> for ty::List> { +impl<'tcx, D: TyDecoder>> RefDecodable<'tcx, D> for ty::List> { fn decode(decoder: &mut D) -> &'tcx Self { let len = decoder.read_usize(); - decoder.interner().mk_predicates_from_iter( - (0..len).map::, _>(|_| Decodable::decode(decoder)), + decoder.interner().mk_clauses_from_iter( + (0..len).map::, _>(|_| Decodable::decode(decoder)), ) } } @@ -434,7 +424,7 @@ impl_decodable_via_ref! { &'tcx mir::BorrowCheckResult<'tcx>, &'tcx mir::coverage::CodeRegion, &'tcx ty::List, - &'tcx ty::List>, + &'tcx ty::List>, &'tcx ty::List, } diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs index 1f9cf2c64489..1c610d6891b7 100644 --- a/compiler/rustc_middle/src/ty/context.rs +++ b/compiler/rustc_middle/src/ty/context.rs @@ -141,8 +141,6 @@ pub struct CtxtInterners<'tcx> { region: InternedSet<'tcx, RegionKind<'tcx>>, poly_existential_predicates: InternedSet<'tcx, List>>, predicate: InternedSet<'tcx, WithCachedTypeInfo>>>, - // FIXME(clause): remove this when all usages are moved to predicate - predicates: InternedSet<'tcx, List>>, clauses: InternedSet<'tcx, List>>, projs: InternedSet<'tcx, List>, place_elems: InternedSet<'tcx, List>>, @@ -168,7 +166,6 @@ impl<'tcx> CtxtInterners<'tcx> { poly_existential_predicates: Default::default(), canonical_var_infos: Default::default(), predicate: Default::default(), - predicates: Default::default(), clauses: Default::default(), projs: Default::default(), place_elems: Default::default(), @@ -1260,10 +1257,11 @@ nop_lift! {region; Region<'a> => Region<'tcx>} nop_lift! {const_; Const<'a> => Const<'tcx>} nop_lift! {const_allocation; ConstAllocation<'a> => ConstAllocation<'tcx>} nop_lift! {predicate; Predicate<'a> => Predicate<'tcx>} +nop_lift! {predicate; Clause<'a> => Clause<'tcx>} nop_list_lift! {type_lists; Ty<'a> => Ty<'tcx>} nop_list_lift! {poly_existential_predicates; PolyExistentialPredicate<'a> => PolyExistentialPredicate<'tcx>} -nop_list_lift! {predicates; Predicate<'a> => Predicate<'tcx>} +nop_list_lift! {clauses; Clause<'a> => Clause<'tcx>} nop_list_lift! {canonical_var_infos; CanonicalVarInfo<'a> => CanonicalVarInfo<'tcx>} nop_list_lift! {projs; ProjectionKind => ProjectionKind} nop_list_lift! {bound_variable_kinds; ty::BoundVariableKind => ty::BoundVariableKind} @@ -1541,7 +1539,6 @@ slice_interners!( type_lists: pub mk_type_list(Ty<'tcx>), canonical_var_infos: pub mk_canonical_var_infos(CanonicalVarInfo<'tcx>), poly_existential_predicates: intern_poly_existential_predicates(PolyExistentialPredicate<'tcx>), - predicates: intern_predicates(Predicate<'tcx>), clauses: intern_clauses(Clause<'tcx>), projs: pub mk_projs(ProjectionKind), place_elems: pub mk_place_elems(PlaceElem<'tcx>), @@ -1597,9 +1594,7 @@ impl<'tcx> TyCtxt<'tcx> { let generic_predicates = self.super_predicates_of(trait_did); for (predicate, _) in generic_predicates.predicates { - if let ty::PredicateKind::Clause(ty::ClauseKind::Trait(data)) = - predicate.kind().skip_binder() - { + if let ty::ClauseKind::Trait(data) = predicate.kind().skip_binder() { if set.insert(data.def_id()) { stack.push(data.def_id()); } @@ -2087,18 +2082,11 @@ impl<'tcx> TyCtxt<'tcx> { self.intern_poly_existential_predicates(eps) } - pub fn mk_predicates(self, preds: &[Predicate<'tcx>]) -> &'tcx List> { + pub fn mk_clauses(self, clauses: &[Clause<'tcx>]) -> &'tcx List> { // FIXME consider asking the input slice to be sorted to avoid // re-interning permutations, in which case that would be asserted // here. - self.intern_predicates(preds) - } - - pub fn mk_clauses(self, preds: &[Clause<'tcx>]) -> &'tcx List> { - // FIXME consider asking the input slice to be sorted to avoid - // re-interning permutations, in which case that would be asserted - // here. - self.intern_clauses(preds) + self.intern_clauses(clauses) } pub fn mk_const_list_from_iter(self, iter: I) -> T::Output @@ -2144,14 +2132,6 @@ impl<'tcx> TyCtxt<'tcx> { T::collect_and_apply(iter, |xs| self.mk_poly_existential_predicates(xs)) } - pub fn mk_predicates_from_iter(self, iter: I) -> T::Output - where - I: Iterator, - T: CollectAndApply, &'tcx List>>, - { - T::collect_and_apply(iter, |xs| self.mk_predicates(xs)) - } - pub fn mk_clauses_from_iter(self, iter: I) -> T::Output where I: Iterator, diff --git a/compiler/rustc_middle/src/ty/flags.rs b/compiler/rustc_middle/src/ty/flags.rs index cc982045c46b..06a8e34cbabb 100644 --- a/compiler/rustc_middle/src/ty/flags.rs +++ b/compiler/rustc_middle/src/ty/flags.rs @@ -287,7 +287,7 @@ impl FlagComputation { self.add_const(expected); self.add_const(found); } - ty::PredicateKind::TypeWellFormedFromEnv(ty) => { + ty::PredicateKind::Clause(ty::ClauseKind::TypeWellFormedFromEnv(ty)) => { self.add_ty(ty); } ty::PredicateKind::Ambiguous => {} diff --git a/compiler/rustc_middle/src/ty/generics.rs b/compiler/rustc_middle/src/ty/generics.rs index 30f92b91cb7a..58fd6e1aa272 100644 --- a/compiler/rustc_middle/src/ty/generics.rs +++ b/compiler/rustc_middle/src/ty/generics.rs @@ -6,7 +6,7 @@ use rustc_hir::def_id::DefId; use rustc_span::symbol::{kw, Symbol}; use rustc_span::Span; -use super::{EarlyBoundRegion, InstantiatedPredicates, ParamConst, ParamTy, Predicate, TyCtxt}; +use super::{Clause, EarlyBoundRegion, InstantiatedPredicates, ParamConst, ParamTy, TyCtxt}; #[derive(Clone, Debug, TyEncodable, TyDecodable, HashStable)] pub enum GenericParamDefKind { @@ -323,7 +323,7 @@ impl<'tcx> Generics { #[derive(Copy, Clone, Default, Debug, TyEncodable, TyDecodable, HashStable)] pub struct GenericPredicates<'tcx> { pub parent: Option, - pub predicates: &'tcx [(Predicate<'tcx>, Span)], + pub predicates: &'tcx [(Clause<'tcx>, Span)], } impl<'tcx> GenericPredicates<'tcx> { @@ -341,8 +341,7 @@ impl<'tcx> GenericPredicates<'tcx> { &self, tcx: TyCtxt<'tcx>, substs: SubstsRef<'tcx>, - ) -> impl Iterator, Span)> + DoubleEndedIterator + ExactSizeIterator - { + ) -> impl Iterator, Span)> + DoubleEndedIterator + ExactSizeIterator { EarlyBinder::bind(self.predicates).subst_iter_copied(tcx, substs) } diff --git a/compiler/rustc_middle/src/ty/inhabitedness/inhabited_predicate.rs b/compiler/rustc_middle/src/ty/inhabitedness/inhabited_predicate.rs index d48672b2baae..018fa2271540 100644 --- a/compiler/rustc_middle/src/ty/inhabitedness/inhabited_predicate.rs +++ b/compiler/rustc_middle/src/ty/inhabitedness/inhabited_predicate.rs @@ -62,7 +62,18 @@ impl<'tcx> InhabitedPredicate<'tcx> { Some(1..) => Ok(false), }, Self::NotInModule(id) => in_module(id).map(|in_mod| !in_mod), - Self::GenericType(_) => Ok(true), + // `t` may be a projection, for which `inhabited_predicate` returns a `GenericType`. As + // we have a param_env available, we can do better. + Self::GenericType(t) => { + let normalized_pred = tcx + .try_normalize_erasing_regions(param_env, t) + .map_or(self, |t| t.inhabited_predicate(tcx)); + match normalized_pred { + // We don't have more information than we started with, so consider inhabited. + Self::GenericType(_) => Ok(true), + pred => pred.apply_inner(tcx, param_env, in_module), + } + } Self::And([a, b]) => try_and(a, b, |x| x.apply_inner(tcx, param_env, in_module)), Self::Or([a, b]) => try_or(a, b, |x| x.apply_inner(tcx, param_env, in_module)), } diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs index 0e604fdf6f49..7bd49ad07eaf 100644 --- a/compiler/rustc_middle/src/ty/mod.rs +++ b/compiler/rustc_middle/src/ty/mod.rs @@ -555,7 +555,7 @@ impl<'tcx> Predicate<'tcx> { | PredicateKind::Clause(ClauseKind::ConstEvaluatable(_)) | PredicateKind::ConstEquate(_, _) | PredicateKind::Ambiguous - | PredicateKind::TypeWellFormedFromEnv(_) => true, + | PredicateKind::Clause(ClauseKind::TypeWellFormedFromEnv(_)) => true, } } } @@ -566,6 +566,12 @@ impl rustc_errors::IntoDiagnosticArg for Predicate<'_> { } } +impl rustc_errors::IntoDiagnosticArg for Clause<'_> { + fn into_diagnostic_arg(self) -> rustc_errors::DiagnosticArgValue<'static> { + rustc_errors::DiagnosticArgValue::Str(std::borrow::Cow::Owned(self.to_string())) + } +} + /// A subset of predicates which can be assumed by the trait solver. They show up in /// an item's where clauses, hence the name `Clause`, and may either be user-written /// (such as traits) or may be inserted during lowering. @@ -620,6 +626,10 @@ impl<'tcx> Clause<'tcx> { None } } + + pub fn without_const(self, tcx: TyCtxt<'tcx>) -> Clause<'tcx> { + self.as_predicate().without_const(tcx).expect_clause() + } } #[derive(Clone, Copy, PartialEq, Eq, Hash, TyEncodable, TyDecodable)] @@ -651,6 +661,11 @@ pub enum ClauseKind<'tcx> { /// Constant initializer must evaluate successfully. ConstEvaluatable(ty::Const<'tcx>), + + /// Represents a type found in the environment that we can use for implied bounds. + /// + /// Only used for Chalk. + TypeWellFormedFromEnv(Ty<'tcx>), } #[derive(Clone, Copy, PartialEq, Eq, Hash, TyEncodable, TyDecodable)] @@ -687,11 +702,6 @@ pub enum PredicateKind<'tcx> { /// Constants must be equal. The first component is the const that is expected. ConstEquate(Const<'tcx>, Const<'tcx>), - /// Represents a type found in the environment that we can use for implied bounds. - /// - /// Only used for Chalk. - TypeWellFormedFromEnv(Ty<'tcx>), - /// A marker predicate that is always ambiguous. /// Used for coherence to mark opaque types as possibly equal to each other but ambiguous. Ambiguous, @@ -730,11 +740,10 @@ pub struct CratePredicatesMap<'tcx> { /// For each struct with outlive bounds, maps to a vector of the /// predicate of its outlive bounds. If an item has no outlives /// bounds, it will have no entry. - // FIXME(clause): should this be a `Clause`? pub predicates: FxHashMap, Span)]>, } -impl<'tcx> Predicate<'tcx> { +impl<'tcx> Clause<'tcx> { /// Performs a substitution suitable for going from a /// poly-trait-ref to supertraits that must hold if that /// poly-trait-ref holds. This is slightly different from a normal @@ -744,7 +753,7 @@ impl<'tcx> Predicate<'tcx> { self, tcx: TyCtxt<'tcx>, trait_ref: &ty::PolyTraitRef<'tcx>, - ) -> Predicate<'tcx> { + ) -> Clause<'tcx> { // The interaction between HRTB and supertraits is not entirely // obvious. Let me walk you (and myself) through an example. // @@ -830,7 +839,13 @@ impl<'tcx> Predicate<'tcx> { // 3) ['x] + ['b] -> ['x, 'b] let bound_vars = tcx.mk_bound_variable_kinds_from_iter(trait_bound_vars.iter().chain(pred_bound_vars)); - tcx.reuse_or_mk_predicate(self, ty::Binder::bind_with_vars(new, bound_vars)) + + // FIXME: Is it really perf sensitive to use reuse_or_mk_predicate here? + tcx.reuse_or_mk_predicate( + self.as_predicate(), + ty::Binder::bind_with_vars(PredicateKind::Clause(new), bound_vars), + ) + .expect_clause() } } @@ -1301,6 +1316,14 @@ impl<'tcx> ToPredicate<'tcx, Clause<'tcx>> for TraitRef<'tcx> { } } +impl<'tcx> ToPredicate<'tcx, Clause<'tcx>> for TraitPredicate<'tcx> { + #[inline(always)] + fn to_predicate(self, tcx: TyCtxt<'tcx>) -> Clause<'tcx> { + let p: Predicate<'tcx> = self.to_predicate(tcx); + p.expect_clause() + } +} + impl<'tcx> ToPredicate<'tcx> for Binder<'tcx, TraitRef<'tcx>> { #[inline(always)] fn to_predicate(self, tcx: TyCtxt<'tcx>) -> Predicate<'tcx> { @@ -1402,7 +1425,7 @@ impl<'tcx> Predicate<'tcx> { | PredicateKind::Clause(ClauseKind::ConstEvaluatable(..)) | PredicateKind::ConstEquate(..) | PredicateKind::Ambiguous - | PredicateKind::TypeWellFormedFromEnv(..) => None, + | PredicateKind::Clause(ClauseKind::TypeWellFormedFromEnv(..)) => None, } } @@ -1423,7 +1446,7 @@ impl<'tcx> Predicate<'tcx> { | PredicateKind::Clause(ClauseKind::ConstEvaluatable(..)) | PredicateKind::ConstEquate(..) | PredicateKind::Ambiguous - | PredicateKind::TypeWellFormedFromEnv(..) => None, + | PredicateKind::Clause(ClauseKind::TypeWellFormedFromEnv(..)) => None, } } @@ -1444,7 +1467,7 @@ impl<'tcx> Predicate<'tcx> { | PredicateKind::Clause(ClauseKind::ConstEvaluatable(..)) | PredicateKind::ConstEquate(..) | PredicateKind::Ambiguous - | PredicateKind::TypeWellFormedFromEnv(..) => None, + | PredicateKind::Clause(ClauseKind::TypeWellFormedFromEnv(..)) => None, } } @@ -1456,12 +1479,11 @@ impl<'tcx> Predicate<'tcx> { } } - /// Turns a predicate into a clause without checking that it is a `PredicateKind::Clause` - /// first. This will ICE when methods are called on `Clause`. + /// Assert that the predicate is a clause. pub fn expect_clause(self) -> Clause<'tcx> { match self.kind().skip_binder() { PredicateKind::Clause(..) => Clause(self.0), - _ => bug!(), + _ => bug!("{self} is not a clause"), } } } @@ -1487,7 +1509,7 @@ impl<'tcx> Predicate<'tcx> { /// [usize:Bar]]`. #[derive(Clone, Debug, TypeFoldable, TypeVisitable)] pub struct InstantiatedPredicates<'tcx> { - pub predicates: Vec>, + pub predicates: Vec>, pub spans: Vec, } @@ -1506,9 +1528,9 @@ impl<'tcx> InstantiatedPredicates<'tcx> { } impl<'tcx> IntoIterator for InstantiatedPredicates<'tcx> { - type Item = (Predicate<'tcx>, Span); + type Item = (Clause<'tcx>, Span); - type IntoIter = std::iter::Zip>, std::vec::IntoIter>; + type IntoIter = std::iter::Zip>, std::vec::IntoIter>; fn into_iter(self) -> Self::IntoIter { debug_assert_eq!(self.predicates.len(), self.spans.len()); @@ -1517,10 +1539,10 @@ impl<'tcx> IntoIterator for InstantiatedPredicates<'tcx> { } impl<'a, 'tcx> IntoIterator for &'a InstantiatedPredicates<'tcx> { - type Item = (Predicate<'tcx>, Span); + type Item = (Clause<'tcx>, Span); type IntoIter = std::iter::Zip< - std::iter::Copied>>, + std::iter::Copied>>, std::iter::Copied>, >; @@ -1670,7 +1692,7 @@ pub struct ParamEnv<'tcx> { /// want `Reveal::All`. /// /// Note: This is packed, use the reveal() method to access it. - packed: CopyTaggedPtr<&'tcx List>, ParamTag, true>, + packed: CopyTaggedPtr<&'tcx List>, ParamTag, true>, } #[derive(Copy, Clone)] @@ -1736,7 +1758,7 @@ impl<'tcx> ParamEnv<'tcx> { } #[inline] - pub fn caller_bounds(self) -> &'tcx List> { + pub fn caller_bounds(self) -> &'tcx List> { self.packed.pointer() } @@ -1770,7 +1792,7 @@ impl<'tcx> ParamEnv<'tcx> { /// Construct a trait environment with the given set of predicates. #[inline] pub fn new( - caller_bounds: &'tcx List>, + caller_bounds: &'tcx List>, reveal: Reveal, constness: hir::Constness, ) -> Self { diff --git a/compiler/rustc_middle/src/ty/print/pretty.rs b/compiler/rustc_middle/src/ty/print/pretty.rs index 7afda73862d2..a5848b98da0b 100644 --- a/compiler/rustc_middle/src/ty/print/pretty.rs +++ b/compiler/rustc_middle/src/ty/print/pretty.rs @@ -2864,20 +2864,38 @@ define_print_and_forward_display! { p!(print(binder)) } + ty::Clause<'tcx> { + p!(print(self.kind())) + } + + ty::ClauseKind<'tcx> { + match *self { + ty::ClauseKind::Trait(ref data) => { + p!(print(data)) + } + ty::ClauseKind::RegionOutlives(predicate) => p!(print(predicate)), + ty::ClauseKind::TypeOutlives(predicate) => p!(print(predicate)), + ty::ClauseKind::Projection(predicate) => p!(print(predicate)), + ty::ClauseKind::ConstArgHasType(ct, ty) => { + p!("the constant `", print(ct), "` has type `", print(ty), "`") + }, + ty::ClauseKind::WellFormed(arg) => p!(print(arg), " well-formed"), + ty::ClauseKind::ConstEvaluatable(ct) => { + p!("the constant `", print(ct), "` can be evaluated") + } + ty::ClauseKind::TypeWellFormedFromEnv(ty) => { + p!("the type `", print(ty), "` is found in the environment") + } + } + } + ty::PredicateKind<'tcx> { match *self { - ty::PredicateKind::Clause(ty::ClauseKind::Trait(ref data)) => { + ty::PredicateKind::Clause(data) => { p!(print(data)) } ty::PredicateKind::Subtype(predicate) => p!(print(predicate)), ty::PredicateKind::Coerce(predicate) => p!(print(predicate)), - ty::PredicateKind::Clause(ty::ClauseKind::RegionOutlives(predicate)) => p!(print(predicate)), - ty::PredicateKind::Clause(ty::ClauseKind::TypeOutlives(predicate)) => p!(print(predicate)), - ty::PredicateKind::Clause(ty::ClauseKind::Projection(predicate)) => p!(print(predicate)), - ty::PredicateKind::Clause(ty::ClauseKind::ConstArgHasType(ct, ty)) => { - p!("the constant `", print(ct), "` has type `", print(ty), "`") - }, - ty::PredicateKind::Clause(ty::ClauseKind::WellFormed(arg)) => p!(print(arg), " well-formed"), ty::PredicateKind::ObjectSafe(trait_def_id) => { p!("the trait `", print_def_path(trait_def_id, &[]), "` is object-safe") } @@ -2886,15 +2904,9 @@ define_print_and_forward_display! { print_value_path(closure_def_id, &[]), write("` implements the trait `{}`", kind) ), - ty::PredicateKind::Clause(ty::ClauseKind::ConstEvaluatable(ct)) => { - p!("the constant `", print(ct), "` can be evaluated") - } ty::PredicateKind::ConstEquate(c1, c2) => { p!("the constant `", print(c1), "` equals `", print(c2), "`") } - ty::PredicateKind::TypeWellFormedFromEnv(ty) => { - p!("the type `", print(ty), "` is found in the environment") - } ty::PredicateKind::Ambiguous => p!("ambiguous"), ty::PredicateKind::AliasRelate(t1, t2, dir) => p!(print(t1), write(" {} ", dir), print(t2)), } diff --git a/compiler/rustc_middle/src/ty/structural_impls.rs b/compiler/rustc_middle/src/ty/structural_impls.rs index 959bf032a83e..113328de176e 100644 --- a/compiler/rustc_middle/src/ty/structural_impls.rs +++ b/compiler/rustc_middle/src/ty/structural_impls.rs @@ -189,6 +189,9 @@ impl<'tcx> fmt::Debug for ty::ClauseKind<'tcx> { ty::ClauseKind::ConstEvaluatable(ct) => { write!(f, "ConstEvaluatable({ct:?})") } + ty::ClauseKind::TypeWellFormedFromEnv(ty) => { + write!(f, "TypeWellFormedFromEnv({:?})", ty) + } } } } @@ -206,9 +209,6 @@ impl<'tcx> fmt::Debug for ty::PredicateKind<'tcx> { write!(f, "ClosureKind({:?}, {:?}, {:?})", closure_def_id, closure_substs, kind) } ty::PredicateKind::ConstEquate(c1, c2) => write!(f, "ConstEquate({:?}, {:?})", c1, c2), - ty::PredicateKind::TypeWellFormedFromEnv(ty) => { - write!(f, "TypeWellFormedFromEnv({:?})", ty) - } ty::PredicateKind::Ambiguous => write!(f, "Ambiguous"), ty::PredicateKind::AliasRelate(t1, t2, dir) => { write!(f, "AliasRelate({t1:?}, {dir:?}, {t2:?})") @@ -701,15 +701,6 @@ impl<'tcx> TypeSuperVisitable> for ty::Predicate<'tcx> { } } -impl<'tcx> TypeFoldable> for &'tcx ty::List> { - fn try_fold_with>>( - self, - folder: &mut F, - ) -> Result { - ty::util::fold_list(self, folder, |tcx, v| tcx.mk_predicates(v)) - } -} - impl<'tcx> TypeFoldable> for &'tcx ty::List> { fn try_fold_with>>( self, diff --git a/compiler/rustc_middle/src/ty/sty.rs b/compiler/rustc_middle/src/ty/sty.rs index c0627ab5c01e..bb6d49e17735 100644 --- a/compiler/rustc_middle/src/ty/sty.rs +++ b/compiler/rustc_middle/src/ty/sty.rs @@ -715,7 +715,7 @@ impl<'tcx> PolyExistentialPredicate<'tcx> { /// Given an existential predicate like `?Self: PartialEq` (e.g., derived from `dyn PartialEq`), /// and a concrete type `self_ty`, returns a full predicate where the existentially quantified variable `?Self` /// has been replaced with `self_ty` (e.g., `self_ty: PartialEq`, in our example). - pub fn with_self_ty(&self, tcx: TyCtxt<'tcx>, self_ty: Ty<'tcx>) -> ty::Predicate<'tcx> { + pub fn with_self_ty(&self, tcx: TyCtxt<'tcx>, self_ty: Ty<'tcx>) -> ty::Clause<'tcx> { use crate::ty::ToPredicate; match self.skip_binder() { ExistentialPredicate::Trait(tr) => { diff --git a/compiler/rustc_middle/src/ty/util.rs b/compiler/rustc_middle/src/ty/util.rs index fcd624b3fefa..bb08deff294c 100644 --- a/compiler/rustc_middle/src/ty/util.rs +++ b/compiler/rustc_middle/src/ty/util.rs @@ -1419,8 +1419,8 @@ pub struct AlwaysRequiresDrop; /// with their underlying types. pub fn reveal_opaque_types_in_bounds<'tcx>( tcx: TyCtxt<'tcx>, - val: &'tcx ty::List>, -) -> &'tcx ty::List> { + val: &'tcx ty::List>, +) -> &'tcx ty::List> { let mut visitor = OpaqueTypeExpander { seen_opaque_tys: FxHashSet::default(), expanded_cache: FxHashMap::default(), diff --git a/compiler/rustc_mir_build/src/build/custom/mod.rs b/compiler/rustc_mir_build/src/build/custom/mod.rs index 32c618828c9b..e5c2cc6c7bbc 100644 --- a/compiler/rustc_mir_build/src/build/custom/mod.rs +++ b/compiler/rustc_mir_build/src/build/custom/mod.rs @@ -118,7 +118,11 @@ fn parse_attribute(attr: &Attribute) -> MirPhase { phase = Some(value); } other => { - panic!("Unexpected key {}", other); + span_bug!( + nested.span(), + "Unexpected key while parsing custom_mir attribute: '{}'", + other + ); } } } diff --git a/compiler/rustc_mir_build/src/build/expr/as_place.rs b/compiler/rustc_mir_build/src/build/expr/as_place.rs index 7ec57add66b5..783f6e2085cb 100644 --- a/compiler/rustc_mir_build/src/build/expr/as_place.rs +++ b/compiler/rustc_mir_build/src/build/expr/as_place.rs @@ -549,6 +549,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { | ExprKind::Break { .. } | ExprKind::Continue { .. } | ExprKind::Return { .. } + | ExprKind::Become { .. } | ExprKind::Literal { .. } | ExprKind::NamedConst { .. } | ExprKind::NonHirLiteral { .. } @@ -677,21 +678,15 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { // check that we just did stays valid. Since we can't assign to // unsized values, we only need to ensure that none of the // pointers in the base place are modified. - for (idx, elem) in base_place.projection.iter().enumerate().rev() { + for (base_place, elem) in base_place.iter_projections().rev() { match elem { ProjectionElem::Deref => { - let fake_borrow_deref_ty = Place::ty_from( - base_place.local, - &base_place.projection[..idx], - &self.local_decls, - tcx, - ) - .ty; + let fake_borrow_deref_ty = base_place.ty(&self.local_decls, tcx).ty; let fake_borrow_ty = tcx.mk_imm_ref(tcx.lifetimes.re_erased, fake_borrow_deref_ty); let fake_borrow_temp = self.local_decls.push(LocalDecl::new(fake_borrow_ty, expr_span)); - let projection = tcx.mk_place_elems(&base_place.projection[..idx]); + let projection = tcx.mk_place_elems(&base_place.projection); self.cfg.push_assign( block, source_info, @@ -705,12 +700,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { fake_borrow_temps.push(fake_borrow_temp); } ProjectionElem::Index(_) => { - let index_ty = Place::ty_from( - base_place.local, - &base_place.projection[..idx], - &self.local_decls, - tcx, - ); + let index_ty = base_place.ty(&self.local_decls, tcx); match index_ty.ty.kind() { // The previous index expression has already // done any index expressions needed here. diff --git a/compiler/rustc_mir_build/src/build/expr/as_rvalue.rs b/compiler/rustc_mir_build/src/build/expr/as_rvalue.rs index ec00f9a96be2..27b1b58d2e90 100644 --- a/compiler/rustc_mir_build/src/build/expr/as_rvalue.rs +++ b/compiler/rustc_mir_build/src/build/expr/as_rvalue.rs @@ -532,6 +532,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { | ExprKind::Break { .. } | ExprKind::Continue { .. } | ExprKind::Return { .. } + | ExprKind::Become { .. } | ExprKind::InlineAsm { .. } | ExprKind::PlaceTypeAscription { .. } | ExprKind::ValueTypeAscription { .. } => { diff --git a/compiler/rustc_mir_build/src/build/expr/category.rs b/compiler/rustc_mir_build/src/build/expr/category.rs index d9aa461c19d4..2fe9cac63780 100644 --- a/compiler/rustc_mir_build/src/build/expr/category.rs +++ b/compiler/rustc_mir_build/src/build/expr/category.rs @@ -82,7 +82,8 @@ impl Category { | ExprKind::Block { .. } | ExprKind::Break { .. } | ExprKind::Continue { .. } - | ExprKind::Return { .. } => + | ExprKind::Return { .. } + | ExprKind::Become { .. } => // FIXME(#27840) these probably want their own // category, like "nonterminating" { diff --git a/compiler/rustc_mir_build/src/build/expr/into.rs b/compiler/rustc_mir_build/src/build/expr/into.rs index 731f3996244c..91c464252f1c 100644 --- a/compiler/rustc_mir_build/src/build/expr/into.rs +++ b/compiler/rustc_mir_build/src/build/expr/into.rs @@ -493,7 +493,10 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { block.unit() } - ExprKind::Continue { .. } | ExprKind::Break { .. } | ExprKind::Return { .. } => { + ExprKind::Continue { .. } + | ExprKind::Break { .. } + | ExprKind::Return { .. } + | ExprKind::Become { .. } => { unpack!(block = this.stmt_expr(block, expr, None)); // No assign, as these have type `!`. block.unit() diff --git a/compiler/rustc_mir_build/src/build/expr/stmt.rs b/compiler/rustc_mir_build/src/build/expr/stmt.rs index ea5aeb67d857..396f82c27cd8 100644 --- a/compiler/rustc_mir_build/src/build/expr/stmt.rs +++ b/compiler/rustc_mir_build/src/build/expr/stmt.rs @@ -99,6 +99,13 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { BreakableTarget::Return, source_info, ), + // FIXME(explicit_tail_calls): properly lower tail calls here + ExprKind::Become { value } => this.break_scope( + block, + Some(&this.thir[value]), + BreakableTarget::Return, + source_info, + ), _ => { assert!( statement_scope.is_some(), diff --git a/compiler/rustc_mir_build/src/check_unsafety.rs b/compiler/rustc_mir_build/src/check_unsafety.rs index 4f3a574031db..105564b78742 100644 --- a/compiler/rustc_mir_build/src/check_unsafety.rs +++ b/compiler/rustc_mir_build/src/check_unsafety.rs @@ -316,6 +316,7 @@ impl<'a, 'tcx> Visitor<'a, 'tcx> for UnsafetyVisitor<'a, 'tcx> { | ExprKind::Closure { .. } | ExprKind::Continue { .. } | ExprKind::Return { .. } + | ExprKind::Become { .. } | ExprKind::Yield { .. } | ExprKind::Loop { .. } | ExprKind::Let { .. } diff --git a/compiler/rustc_mir_build/src/thir/cx/expr.rs b/compiler/rustc_mir_build/src/thir/cx/expr.rs index 7f0c2e9ca3fb..791c10c1748d 100644 --- a/compiler/rustc_mir_build/src/thir/cx/expr.rs +++ b/compiler/rustc_mir_build/src/thir/cx/expr.rs @@ -694,7 +694,8 @@ impl<'tcx> Cx<'tcx> { ExprKind::Repeat { value: self.mirror_expr(v), count: *count } } - hir::ExprKind::Ret(ref v) => ExprKind::Return { value: v.map(|v| self.mirror_expr(v)) }, + hir::ExprKind::Ret(v) => ExprKind::Return { value: v.map(|v| self.mirror_expr(v)) }, + hir::ExprKind::Become(call) => ExprKind::Become { value: self.mirror_expr(call) }, hir::ExprKind::Break(dest, ref value) => match dest.target_id { Ok(target_id) => ExprKind::Break { label: region::Scope { id: target_id.local_id, data: region::ScopeData::Node }, diff --git a/compiler/rustc_mir_build/src/thir/print.rs b/compiler/rustc_mir_build/src/thir/print.rs index b2f2a64e29c8..0b6029bf3882 100644 --- a/compiler/rustc_mir_build/src/thir/print.rs +++ b/compiler/rustc_mir_build/src/thir/print.rs @@ -421,6 +421,12 @@ impl<'a, 'tcx> ThirPrinter<'a, 'tcx> { print_indented!(self, "}", depth_lvl); } + Become { value } => { + print_indented!(self, "Become {", depth_lvl); + print_indented!(self, "value:", depth_lvl + 1); + self.print_expr(*value, depth_lvl + 2); + print_indented!(self, "}", depth_lvl); + } ConstBlock { did, substs } => { print_indented!(self, "ConstBlock {", depth_lvl); print_indented!(self, format!("did: {:?}", did), depth_lvl + 1); diff --git a/compiler/rustc_mir_dataflow/src/framework/mod.rs b/compiler/rustc_mir_dataflow/src/framework/mod.rs index e5e9c1507ba8..58df9b9a768b 100644 --- a/compiler/rustc_mir_dataflow/src/framework/mod.rs +++ b/compiler/rustc_mir_dataflow/src/framework/mod.rs @@ -45,7 +45,7 @@ pub mod graphviz; pub mod lattice; mod visitor; -pub use self::cursor::{ResultsClonedCursor, ResultsCursor, ResultsRefCursor}; +pub use self::cursor::{AnalysisResults, ResultsClonedCursor, ResultsCursor, ResultsRefCursor}; pub use self::direction::{Backward, Direction, Forward}; pub use self::engine::{Engine, EntrySets, Results, ResultsCloned}; pub use self::lattice::{JoinSemiLattice, MeetSemiLattice}; diff --git a/compiler/rustc_mir_dataflow/src/lib.rs b/compiler/rustc_mir_dataflow/src/lib.rs index 3494a37c3cf2..900d438f8d53 100644 --- a/compiler/rustc_mir_dataflow/src/lib.rs +++ b/compiler/rustc_mir_dataflow/src/lib.rs @@ -27,10 +27,10 @@ pub use self::drop_flag_effects::{ on_lookup_result_bits, }; pub use self::framework::{ - fmt, graphviz, lattice, visit_results, Analysis, AnalysisDomain, Backward, CallReturnPlaces, - CloneAnalysis, Direction, Engine, Forward, GenKill, GenKillAnalysis, JoinSemiLattice, Results, - ResultsCloned, ResultsClonedCursor, ResultsCursor, ResultsRefCursor, ResultsVisitable, - ResultsVisitor, SwitchIntEdgeEffects, + fmt, graphviz, lattice, visit_results, Analysis, AnalysisDomain, AnalysisResults, Backward, + CallReturnPlaces, CloneAnalysis, Direction, Engine, Forward, GenKill, GenKillAnalysis, + JoinSemiLattice, Results, ResultsCloned, ResultsClonedCursor, ResultsCursor, ResultsRefCursor, + ResultsVisitable, ResultsVisitor, SwitchIntEdgeEffects, }; use self::move_paths::MoveData; diff --git a/compiler/rustc_mir_dataflow/src/move_paths/builder.rs b/compiler/rustc_mir_dataflow/src/move_paths/builder.rs index fe9631653ea7..2b37b55d2784 100644 --- a/compiler/rustc_mir_dataflow/src/move_paths/builder.rs +++ b/compiler/rustc_mir_dataflow/src/move_paths/builder.rs @@ -113,22 +113,16 @@ impl<'b, 'a, 'tcx> Gatherer<'b, 'a, 'tcx> { // from `*(u.f: &_)` isn't allowed. let mut union_path = None; - for (i, elem) in place.projection.iter().enumerate() { - let proj_base = &place.projection[..i]; + for (place_ref, elem) in place.as_ref().iter_projections() { let body = self.builder.body; let tcx = self.builder.tcx; - let place_ty = Place::ty_from(place.local, proj_base, body, tcx).ty; + let place_ty = place_ref.ty(body, tcx).ty; + match place_ty.kind() { ty::Ref(..) | ty::RawPtr(..) => { - let proj = &place.projection[..i + 1]; return Err(MoveError::cannot_move_out_of( self.loc, - BorrowedContent { - target_place: Place { - local: place.local, - projection: tcx.mk_place_elems(proj), - }, - }, + BorrowedContent { target_place: place_ref.project_deeper(&[elem], tcx) }, )); } ty::Adt(adt, _) if adt.has_dtor(tcx) && !adt.is_box() => { @@ -163,10 +157,7 @@ impl<'b, 'a, 'tcx> Gatherer<'b, 'a, 'tcx> { }; if union_path.is_none() { - base = self.add_move_path(base, elem, |tcx| Place { - local: place.local, - projection: tcx.mk_place_elems(&place.projection[..i + 1]), - }); + base = self.add_move_path(base, elem, |tcx| place_ref.project_deeper(&[elem], tcx)); } } diff --git a/compiler/rustc_mir_transform/src/check_alignment.rs b/compiler/rustc_mir_transform/src/check_alignment.rs index 856327e6ce65..05c54ab3097f 100644 --- a/compiler/rustc_mir_transform/src/check_alignment.rs +++ b/compiler/rustc_mir_transform/src/check_alignment.rs @@ -240,9 +240,9 @@ fn insert_alignment_check<'tcx>( required: Operand::Copy(alignment), found: Operand::Copy(addr), }), - // The panic symbol that this calls is #[rustc_nounwind]. We never want to insert an - // unwind into unsafe code, because unwinding could make a failing UB check turn into - // much worse UB when we start unwinding. + // This calls panic_misaligned_pointer_dereference, which is #[rustc_nounwind]. + // We never want to insert an unwind into unsafe code, because unwinding could + // make a failing UB check turn into much worse UB when we start unwinding. unwind: UnwindAction::Unreachable, }, }); diff --git a/compiler/rustc_mir_transform/src/coverage/debug.rs b/compiler/rustc_mir_transform/src/coverage/debug.rs index 6a3d42511ac1..7ad981441592 100644 --- a/compiler/rustc_mir_transform/src/coverage/debug.rs +++ b/compiler/rustc_mir_transform/src/coverage/debug.rs @@ -277,14 +277,7 @@ impl DebugCounters { pub fn add_counter(&mut self, counter_kind: &CoverageKind, some_block_label: Option) { if let Some(counters) = &mut self.some_counters { - let id: ExpressionOperandId = match *counter_kind { - CoverageKind::Counter { id, .. } => id.into(), - CoverageKind::Expression { id, .. } => id.into(), - _ => bug!( - "the given `CoverageKind` is not an counter or expression: {:?}", - counter_kind - ), - }; + let id = counter_kind.as_operand_id(); counters .try_insert(id, DebugCounter::new(counter_kind.clone(), some_block_label)) .expect("attempt to add the same counter_kind to DebugCounters more than once"); @@ -330,13 +323,7 @@ impl DebugCounters { } } - let id: ExpressionOperandId = match *counter_kind { - CoverageKind::Counter { id, .. } => id.into(), - CoverageKind::Expression { id, .. } => id.into(), - _ => { - bug!("the given `CoverageKind` is not an counter or expression: {:?}", counter_kind) - } - }; + let id = counter_kind.as_operand_id(); if self.some_counters.is_some() && (counter_format.block || !counter_format.id) { let counters = self.some_counters.as_ref().unwrap(); if let Some(DebugCounter { some_block_label: Some(block_label), .. }) = diff --git a/compiler/rustc_mir_transform/src/coverage/graph.rs b/compiler/rustc_mir_transform/src/coverage/graph.rs index ea1223fbca64..d2a854b26756 100644 --- a/compiler/rustc_mir_transform/src/coverage/graph.rs +++ b/compiler/rustc_mir_transform/src/coverage/graph.rs @@ -387,7 +387,7 @@ impl BasicCoverageBlockData { // If the BCB has an edge counter (to be injected into a new `BasicBlock`), it can also // have an expression (to be injected into an existing `BasicBlock` represented by this // `BasicCoverageBlock`). - if !self.counter_kind.as_ref().map_or(true, |c| c.is_expression()) { + if self.counter_kind.as_ref().is_some_and(|c| !c.is_expression()) { return Error::from_string(format!( "attempt to add an incoming edge counter from {:?} when the target BCB already \ has a `Counter`", diff --git a/compiler/rustc_mir_transform/src/coverage/spans.rs b/compiler/rustc_mir_transform/src/coverage/spans.rs index d27200419e2c..35cf9ea5f91c 100644 --- a/compiler/rustc_mir_transform/src/coverage/spans.rs +++ b/compiler/rustc_mir_transform/src/coverage/spans.rs @@ -480,9 +480,10 @@ impl<'a, 'tcx> CoverageSpans<'a, 'tcx> { fn check_invoked_macro_name_span(&mut self) { if let Some(visible_macro) = self.curr().visible_macro(self.body_span) { - if self.prev_expn_span.map_or(true, |prev_expn_span| { - self.curr().expn_span.ctxt() != prev_expn_span.ctxt() - }) { + if !self + .prev_expn_span + .is_some_and(|prev_expn_span| self.curr().expn_span.ctxt() == prev_expn_span.ctxt()) + { let merged_prefix_len = self.curr_original_span.lo() - self.curr().span.lo(); let after_macro_bang = merged_prefix_len + BytePos(visible_macro.as_str().len() as u32 + 1); diff --git a/compiler/rustc_mir_transform/src/dest_prop.rs b/compiler/rustc_mir_transform/src/dest_prop.rs index 78758e2db28a..a31551cf6199 100644 --- a/compiler/rustc_mir_transform/src/dest_prop.rs +++ b/compiler/rustc_mir_transform/src/dest_prop.rs @@ -37,6 +37,10 @@ //! if they do not consistently refer to the same place in memory. This is satisfied if they do //! not contain any indirection through a pointer or any indexing projections. //! +//! * `p` and `q` must have the **same type**. If we replace a local with a subtype or supertype, +//! we may end up with a differnet vtable for that local. See the `subtyping-impacts-selection` +//! tests for an example where that causes issues. +//! //! * We need to make sure that the goal of "merging the memory" is actually structurally possible //! in MIR. For example, even if all the other conditions are satisfied, there is no way to //! "merge" `_5.foo` and `_6.bar`. For now, we ensure this by requiring that both `p` and `q` are @@ -134,6 +138,7 @@ use crate::MirPass; use rustc_data_structures::fx::FxHashMap; use rustc_index::bit_set::BitSet; use rustc_middle::mir::visit::{MutVisitor, PlaceContext, Visitor}; +use rustc_middle::mir::HasLocalDecls; use rustc_middle::mir::{dump_mir, PassWhere}; use rustc_middle::mir::{ traversal, Body, InlineAsmOperand, Local, LocalKind, Location, Operand, Place, Rvalue, @@ -763,12 +768,22 @@ impl<'tcx> Visitor<'tcx> for FindAssignments<'_, '_, 'tcx> { return; }; - // As described at the top of the file, we do not go near things that have their address - // taken. + // As described at the top of the file, we do not go near things that have + // their address taken. if self.borrowed.contains(src) || self.borrowed.contains(dest) { return; } + // As described at the top of this file, we do not touch locals which have + // different types. + let src_ty = self.body.local_decls()[src].ty; + let dest_ty = self.body.local_decls()[dest].ty; + if src_ty != dest_ty { + // FIXME(#112651): This can be removed afterwards. Also update the module description. + trace!("skipped `{src:?} = {dest:?}` due to subtyping: {src_ty} != {dest_ty}"); + return; + } + // Also, we need to make sure that MIR actually allows the `src` to be removed if is_local_required(src, self.body) { return; diff --git a/compiler/rustc_mir_transform/src/function_item_references.rs b/compiler/rustc_mir_transform/src/function_item_references.rs index 502f367dcb6c..0b41e57be3b3 100644 --- a/compiler/rustc_mir_transform/src/function_item_references.rs +++ b/compiler/rustc_mir_transform/src/function_item_references.rs @@ -2,7 +2,7 @@ use itertools::Itertools; use rustc_hir::def_id::DefId; use rustc_middle::mir::visit::Visitor; use rustc_middle::mir::*; -use rustc_middle::ty::{self, EarlyBinder, PredicateKind, SubstsRef, Ty, TyCtxt}; +use rustc_middle::ty::{self, EarlyBinder, SubstsRef, Ty, TyCtxt}; use rustc_session::lint::builtin::FUNCTION_ITEM_REFERENCES; use rustc_span::{symbol::sym, Span}; use rustc_target::spec::abi::Abi; @@ -74,7 +74,7 @@ impl<'tcx> FunctionItemRefChecker<'_, 'tcx> { let param_env = self.tcx.param_env(def_id); let bounds = param_env.caller_bounds(); for bound in bounds { - if let Some(bound_ty) = self.is_pointer_trait(&bound.kind().skip_binder()) { + if let Some(bound_ty) = self.is_pointer_trait(bound) { // Get the argument types as they appear in the function signature. let arg_defs = self.tcx.fn_sig(def_id).subst_identity().skip_binder().inputs(); for (arg_num, arg_def) in arg_defs.iter().enumerate() { @@ -104,8 +104,8 @@ impl<'tcx> FunctionItemRefChecker<'_, 'tcx> { } /// If the given predicate is the trait `fmt::Pointer`, returns the bound parameter type. - fn is_pointer_trait(&self, bound: &PredicateKind<'tcx>) -> Option> { - if let ty::PredicateKind::Clause(ty::ClauseKind::Trait(predicate)) = bound { + fn is_pointer_trait(&self, bound: ty::Clause<'tcx>) -> Option> { + if let ty::ClauseKind::Trait(predicate) = bound.kind().skip_binder() { self.tcx .is_diagnostic_item(sym::Pointer, predicate.def_id()) .then(|| predicate.trait_ref.self_ty()) diff --git a/compiler/rustc_mir_transform/src/inline.rs b/compiler/rustc_mir_transform/src/inline.rs index 703824f5bdac..240beabfc1a9 100644 --- a/compiler/rustc_mir_transform/src/inline.rs +++ b/compiler/rustc_mir_transform/src/inline.rs @@ -839,15 +839,13 @@ impl<'tcx> Visitor<'tcx> for CostChecker<'_, 'tcx> { /// to normalization failure. fn visit_projection_elem( &mut self, - local: Local, - proj_base: &[PlaceElem<'tcx>], + place_ref: PlaceRef<'tcx>, elem: PlaceElem<'tcx>, context: PlaceContext, location: Location, ) { if let ProjectionElem::Field(f, ty) = elem { - let parent = Place { local, projection: self.tcx.mk_place_elems(proj_base) }; - let parent_ty = parent.ty(&self.callee_body.local_decls, self.tcx); + let parent_ty = place_ref.ty(&self.callee_body.local_decls, self.tcx); let check_equal = |this: &mut Self, f_ty| { if !util::is_equal_up_to_subtyping(this.tcx, this.param_env, ty, f_ty) { trace!(?ty, ?f_ty); @@ -926,7 +924,7 @@ impl<'tcx> Visitor<'tcx> for CostChecker<'_, 'tcx> { } } - self.super_projection_elem(local, proj_base, elem, context, location); + self.super_projection_elem(place_ref, elem, context, location); } } diff --git a/compiler/rustc_mir_transform/src/shim.rs b/compiler/rustc_mir_transform/src/shim.rs index 2ae5ec4d9e6c..500595e9f507 100644 --- a/compiler/rustc_mir_transform/src/shim.rs +++ b/compiler/rustc_mir_transform/src/shim.rs @@ -32,13 +32,15 @@ fn make_shim<'tcx>(tcx: TyCtxt<'tcx>, instance: ty::InstanceDef<'tcx>) -> Body<' let mut result = match instance { ty::InstanceDef::Item(..) => bug!("item {:?} passed to make_shim", instance), ty::InstanceDef::VTableShim(def_id) => { - build_call_shim(tcx, instance, Some(Adjustment::Deref), CallKind::Direct(def_id)) + let adjustment = Adjustment::Deref { source: DerefSource::MutPtr }; + build_call_shim(tcx, instance, Some(adjustment), CallKind::Direct(def_id)) } ty::InstanceDef::FnPtrShim(def_id, ty) => { let trait_ = tcx.trait_of_item(def_id).unwrap(); let adjustment = match tcx.fn_trait_kind_from_def_id(trait_) { Some(ty::ClosureKind::FnOnce) => Adjustment::Identity, - Some(ty::ClosureKind::FnMut | ty::ClosureKind::Fn) => Adjustment::Deref, + Some(ty::ClosureKind::Fn) => Adjustment::Deref { source: DerefSource::ImmRef }, + Some(ty::ClosureKind::FnMut) => Adjustment::Deref { source: DerefSource::MutRef }, None => bug!("fn pointer {:?} is not an fn", ty), }; @@ -107,16 +109,26 @@ fn make_shim<'tcx>(tcx: TyCtxt<'tcx>, instance: ty::InstanceDef<'tcx>) -> Body<' result } +#[derive(Copy, Clone, Debug, PartialEq)] +enum DerefSource { + /// `fn shim(&self) { inner(*self )}`. + ImmRef, + /// `fn shim(&mut self) { inner(*self )}`. + MutRef, + /// `fn shim(*mut self) { inner(*self )}`. + MutPtr, +} + #[derive(Copy, Clone, Debug, PartialEq)] enum Adjustment { /// Pass the receiver as-is. Identity, - /// We get passed `&[mut] self` and call the target with `*self`. + /// We get passed a reference or a raw pointer to `self` and call the target with `*self`. /// /// This either copies `self` (if `Self: Copy`, eg. for function items), or moves out of it /// (for `VTableShim`, which effectively is passed `&own Self`). - Deref, + Deref { source: DerefSource }, /// We get passed `self: Self` and call the target with `&mut self`. /// @@ -667,8 +679,12 @@ fn build_call_shim<'tcx>( let self_arg = &mut inputs_and_output[0]; *self_arg = match rcvr_adjustment.unwrap() { Adjustment::Identity => fnty, - Adjustment::Deref => tcx.mk_imm_ptr(fnty), - Adjustment::RefMut => tcx.mk_mut_ptr(fnty), + Adjustment::Deref { source } => match source { + DerefSource::ImmRef => tcx.mk_imm_ref(tcx.lifetimes.re_erased, fnty), + DerefSource::MutRef => tcx.mk_mut_ref(tcx.lifetimes.re_erased, fnty), + DerefSource::MutPtr => tcx.mk_mut_ptr(fnty), + }, + Adjustment::RefMut => bug!("`RefMut` is never used with indirect calls: {instance:?}"), }; sig.inputs_and_output = tcx.mk_type_list(&inputs_and_output); } @@ -699,7 +715,7 @@ fn build_call_shim<'tcx>( let rcvr = rcvr_adjustment.map(|rcvr_adjustment| match rcvr_adjustment { Adjustment::Identity => Operand::Move(rcvr_place()), - Adjustment::Deref => Operand::Move(tcx.mk_place_deref(rcvr_place())), + Adjustment::Deref { source: _ } => Operand::Move(tcx.mk_place_deref(rcvr_place())), Adjustment::RefMut => { // let rcvr = &mut rcvr; let ref_rcvr = local_decls.push( diff --git a/compiler/rustc_mir_transform/src/ssa.rs b/compiler/rustc_mir_transform/src/ssa.rs index 7a0d3a025f36..8dc2dfe13bd3 100644 --- a/compiler/rustc_mir_transform/src/ssa.rs +++ b/compiler/rustc_mir_transform/src/ssa.rs @@ -271,6 +271,14 @@ fn compute_copy_classes(ssa: &mut SsaLocals, body: &Body<'_>) { else { continue }; let Some(rhs) = place.as_local() else { continue }; + let local_ty = body.local_decls()[local].ty; + let rhs_ty = body.local_decls()[rhs].ty; + if local_ty != rhs_ty { + // FIXME(#112651): This can be removed afterwards. + trace!("skipped `{local:?} = {rhs:?}` due to subtyping: {local_ty} != {rhs_ty}"); + continue; + } + if !ssa.is_ssa(rhs) { continue; } diff --git a/compiler/rustc_parse/messages.ftl b/compiler/rustc_parse/messages.ftl index 35eec2c8e1b1..9787d98c1a49 100644 --- a/compiler/rustc_parse/messages.ftl +++ b/compiler/rustc_parse/messages.ftl @@ -353,6 +353,7 @@ parse_int_literal_too_large = integer literal is too large parse_invalid_block_macro_segment = cannot use a `block` macro fragment here .label = the `block` fragment is within this context + .suggestion = wrap this in another block parse_invalid_char_in_escape = {parse_invalid_char_in_escape_msg}: `{$ch}` .label = {parse_invalid_char_in_escape_msg} diff --git a/compiler/rustc_parse/src/errors.rs b/compiler/rustc_parse/src/errors.rs index 84494eab855c..96e1c0e3c6d9 100644 --- a/compiler/rustc_parse/src/errors.rs +++ b/compiler/rustc_parse/src/errors.rs @@ -333,6 +333,17 @@ pub(crate) struct InvalidBlockMacroSegment { pub span: Span, #[label] pub context: Span, + #[subdiagnostic] + pub wrap: WrapInExplicitBlock, +} + +#[derive(Subdiagnostic)] +#[multipart_suggestion(parse_suggestion, applicability = "machine-applicable")] +pub(crate) struct WrapInExplicitBlock { + #[suggestion_part(code = "{{ ")] + pub lo: Span, + #[suggestion_part(code = " }}")] + pub hi: Span, } #[derive(Diagnostic)] diff --git a/compiler/rustc_parse/src/parser/attr.rs b/compiler/rustc_parse/src/parser/attr.rs index e1db19557cfe..ee0abba1c175 100644 --- a/compiler/rustc_parse/src/parser/attr.rs +++ b/compiler/rustc_parse/src/parser/attr.rs @@ -422,15 +422,12 @@ impl<'a> Parser<'a> { } } -pub fn maybe_needs_tokens(attrs: &[ast::Attribute]) -> bool { - // One of the attributes may either itself be a macro, - // or expand to macro attributes (`cfg_attr`). - attrs.iter().any(|attr| { - if attr.is_doc_comment() { - return false; - } - attr.ident().map_or(true, |ident| { - ident.name == sym::cfg_attr || !rustc_feature::is_builtin_attr_name(ident.name) - }) +/// The attributes are complete if all attributes are either a doc comment or a builtin attribute other than `cfg_attr` +pub fn is_complete(attrs: &[ast::Attribute]) -> bool { + attrs.iter().all(|attr| { + attr.is_doc_comment() + || attr.ident().is_some_and(|ident| { + ident.name != sym::cfg_attr && rustc_feature::is_builtin_attr_name(ident.name) + }) }) } diff --git a/compiler/rustc_parse/src/parser/attr_wrapper.rs b/compiler/rustc_parse/src/parser/attr_wrapper.rs index 1e6ac54964f9..b579da098d8a 100644 --- a/compiler/rustc_parse/src/parser/attr_wrapper.rs +++ b/compiler/rustc_parse/src/parser/attr_wrapper.rs @@ -61,8 +61,8 @@ impl AttrWrapper { self.attrs.is_empty() } - pub fn maybe_needs_tokens(&self) -> bool { - crate::parser::attr::maybe_needs_tokens(&self.attrs) + pub fn is_complete(&self) -> bool { + crate::parser::attr::is_complete(&self.attrs) } } @@ -201,7 +201,7 @@ impl<'a> Parser<'a> { // by definition if matches!(force_collect, ForceCollect::No) // None of our outer attributes can require tokens (e.g. a proc-macro) - && !attrs.maybe_needs_tokens() + && attrs.is_complete() // If our target supports custom inner attributes, then we cannot bail // out early, since we may need to capture tokens for a custom inner attribute // invocation. @@ -244,9 +244,9 @@ impl<'a> Parser<'a> { // Now that we've parsed an AST node, we have more information available. if matches!(force_collect, ForceCollect::No) // We now have inner attributes available, so this check is more precise - // than `attrs.maybe_needs_tokens()` at the start of the function. + // than `attrs.is_complete()` at the start of the function. // As a result, we don't need to check `R::SUPPORTS_CUSTOM_INNER_ATTRS` - && !crate::parser::attr::maybe_needs_tokens(ret.attrs()) + && crate::parser::attr::is_complete(ret.attrs()) // Subtle: We call `has_cfg_or_cfg_attr` with the attrs from `ret`. // This ensures that we consider inner attributes (e.g. `#![cfg]`), // which require us to have tokens available diff --git a/compiler/rustc_parse/src/parser/expr.rs b/compiler/rustc_parse/src/parser/expr.rs index 5f2f86e8113e..7ede4fbc3d90 100644 --- a/compiler/rustc_parse/src/parser/expr.rs +++ b/compiler/rustc_parse/src/parser/expr.rs @@ -2192,6 +2192,10 @@ impl<'a> Parser<'a> { self.sess.emit_err(errors::InvalidBlockMacroSegment { span: self.token.span, context: lo.to(self.token.span), + wrap: errors::WrapInExplicitBlock { + lo: self.token.span.shrink_to_lo(), + hi: self.token.span.shrink_to_hi(), + }, }); } diff --git a/compiler/rustc_passes/src/errors.rs b/compiler/rustc_passes/src/errors.rs index 7890c93d5ff0..3fe7feb9dfa1 100644 --- a/compiler/rustc_passes/src/errors.rs +++ b/compiler/rustc_passes/src/errors.rs @@ -1150,14 +1150,6 @@ pub struct UnixSigpipeValues { pub span: Span, } -#[derive(Diagnostic)] -#[diag(passes_no_main_function, code = "E0601")] -pub struct NoMainFunction { - #[primary_span] - pub span: Span, - pub crate_name: String, -} - pub struct NoMainErr { pub sp: Span, pub crate_name: Symbol, diff --git a/compiler/rustc_passes/src/hir_stats.rs b/compiler/rustc_passes/src/hir_stats.rs index 90809270118d..6c748147abe0 100644 --- a/compiler/rustc_passes/src/hir_stats.rs +++ b/compiler/rustc_passes/src/hir_stats.rs @@ -302,8 +302,8 @@ impl<'v> hir_visit::Visitor<'v> for StatCollector<'v> { [ ConstBlock, Array, Call, MethodCall, Tup, Binary, Unary, Lit, Cast, Type, DropTemps, Let, If, Loop, Match, Closure, Block, Assign, AssignOp, Field, Index, - Path, AddrOf, Break, Continue, Ret, InlineAsm, OffsetOf, Struct, Repeat, Yield, - Err + Path, AddrOf, Break, Continue, Ret, Become, InlineAsm, OffsetOf, Struct, Repeat, + Yield, Err ] ); hir_visit::walk_expr(self, e) diff --git a/compiler/rustc_passes/src/liveness.rs b/compiler/rustc_passes/src/liveness.rs index 63b1578d43fd..803ca05b2025 100644 --- a/compiler/rustc_passes/src/liveness.rs +++ b/compiler/rustc_passes/src/liveness.rs @@ -463,6 +463,7 @@ impl<'tcx> Visitor<'tcx> for IrMaps<'tcx> { | hir::ExprKind::Lit(_) | hir::ExprKind::ConstBlock(..) | hir::ExprKind::Ret(..) + | hir::ExprKind::Become(..) | hir::ExprKind::Block(..) | hir::ExprKind::Assign(..) | hir::ExprKind::AssignOp(..) @@ -967,6 +968,11 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> { self.propagate_through_opt_expr(o_e.as_deref(), self.exit_ln) } + hir::ExprKind::Become(ref e) => { + // Ignore succ and subst exit_ln. + self.propagate_through_expr(e, self.exit_ln) + } + hir::ExprKind::Break(label, ref opt_expr) => { // Find which label this break jumps to let target = match label.target_id { @@ -1408,6 +1414,7 @@ fn check_expr<'tcx>(this: &mut Liveness<'_, 'tcx>, expr: &'tcx Expr<'tcx>) { | hir::ExprKind::DropTemps(..) | hir::ExprKind::Unary(..) | hir::ExprKind::Ret(..) + | hir::ExprKind::Become(..) | hir::ExprKind::Break(..) | hir::ExprKind::Continue(..) | hir::ExprKind::Lit(_) diff --git a/compiler/rustc_passes/src/naked_functions.rs b/compiler/rustc_passes/src/naked_functions.rs index a849d61edfea..769b389009b7 100644 --- a/compiler/rustc_passes/src/naked_functions.rs +++ b/compiler/rustc_passes/src/naked_functions.rs @@ -204,6 +204,7 @@ impl<'tcx> CheckInlineAssembly<'tcx> { | ExprKind::Continue(..) | ExprKind::Ret(..) | ExprKind::OffsetOf(..) + | ExprKind::Become(..) | ExprKind::Struct(..) | ExprKind::Repeat(..) | ExprKind::Yield(..) => { diff --git a/compiler/rustc_privacy/src/lib.rs b/compiler/rustc_privacy/src/lib.rs index 8a848e5db629..5f7313dcca62 100644 --- a/compiler/rustc_privacy/src/lib.rs +++ b/compiler/rustc_privacy/src/lib.rs @@ -112,13 +112,13 @@ trait DefIdVisitor<'tcx> { &mut self, predicates: ty::GenericPredicates<'tcx>, ) -> ControlFlow { - self.skeleton().visit_predicates(predicates) + self.skeleton().visit_clauses(predicates.predicates) } fn visit_clauses( &mut self, - predicates: &[(ty::Clause<'tcx>, Span)], + clauses: &[(ty::Clause<'tcx>, Span)], ) -> ControlFlow { - self.skeleton().visit_clauses(predicates) + self.skeleton().visit_clauses(clauses) } } @@ -182,24 +182,12 @@ where } ty::ClauseKind::ConstEvaluatable(ct) => ct.visit_with(self), ty::ClauseKind::WellFormed(arg) => arg.visit_with(self), + ty::ClauseKind::TypeWellFormedFromEnv(_) => bug!("unexpected clause: {clause}"), } } - fn visit_predicates( - &mut self, - predicates: ty::GenericPredicates<'tcx>, - ) -> ControlFlow { - let ty::GenericPredicates { parent: _, predicates } = predicates; - predicates.iter().try_for_each(|&(predicate, _span)| { - let clause = predicate - .as_clause() - .unwrap_or_else(|| bug!("unexpected predicate: {:?}", predicate)); - self.visit_clause(clause) - }) - } - fn visit_clauses(&mut self, clauses: &[(ty::Clause<'tcx>, Span)]) -> ControlFlow { - clauses.iter().try_for_each(|&(clause, _span)| self.visit_clause(clause)) + clauses.into_iter().try_for_each(|&(clause, _span)| self.visit_clause(clause)) } } diff --git a/compiler/rustc_resolve/messages.ftl b/compiler/rustc_resolve/messages.ftl index 60b6d74da7b9..f98918cba880 100644 --- a/compiler/rustc_resolve/messages.ftl +++ b/compiler/rustc_resolve/messages.ftl @@ -44,13 +44,26 @@ resolve_binding_shadows_something_unacceptable = resolve_binding_shadows_something_unacceptable_suggestion = try specify the pattern arguments +resolve_cannot_be_reexported_crate_public = + `{$ident}` is only public within the crate, and cannot be re-exported outside + +resolve_cannot_be_reexported_private = + `{$ident}` is private, and cannot be re-exported + resolve_cannot_capture_dynamic_environment_in_fn_item = can't capture dynamic environment in a fn item .help = use the `|| {"{"} ... {"}"}` closure form instead +resolve_cannot_determine_import_resolution = + cannot determine resolution for the import + .note = import resolution is stuck, try simplifying other imports + resolve_cannot_find_ident_in_this_scope = cannot find {$expected} `{$ident}` in this scope +resolve_cannot_glob_import_possible_crates = + cannot glob-import all possible crates + resolve_cannot_use_self_type_here = can't use `Self` here @@ -60,6 +73,15 @@ resolve_change_import_binding = resolve_consider_adding_a_derive = consider adding a derive +resolve_consider_adding_macro_export = + consider adding a `#[macro_export]` to the macro in the imported module + +resolve_consider_declaring_with_pub = + consider declaring type or module `{$ident}` with `pub` + +resolve_consider_marking_as_pub = + consider marking `{$ident}` as `pub` in the imported module + resolve_const_not_member_of_trait = const `{$const_}` is not a member of trait `{$trait_}` .label = not a member of trait `{$trait_}` @@ -98,6 +120,9 @@ resolve_generic_params_from_outer_function = .label = use of generic parameter from outer function .suggestion = try using a local generic parameter instead +resolve_glob_import_doesnt_reexport = + glob import doesn't reexport anything because no candidate is public enough + resolve_help_try_using_local_generic_param = try using a local generic parameter instead @@ -122,6 +147,13 @@ resolve_invalid_asm_sym = .label = is a local variable .help = `sym` operands must refer to either a function or a static +resolve_is_not_directly_importable = + `{$target}` is not directly importable + .label = cannot be imported directly + +resolve_items_in_traits_are_not_importable = + items in traits are not importable + resolve_label_with_similar_name_reachable = a label with a similar name is reachable @@ -176,6 +208,12 @@ resolve_parent_module_reset_for_binding = resolve_proc_macro_same_crate = can't use a procedural macro from the same crate that defines it .help = you can define integration tests in a directory named `tests` +resolve_reexport_of_crate_public = + re-export of crate public `{$ident}` + +resolve_reexport_of_private = + re-export of private `{$ident}` + resolve_relative_2018 = relative paths are not supported in visibilities in 2018 edition or later .suggestion = try diff --git a/compiler/rustc_resolve/src/errors.rs b/compiler/rustc_resolve/src/errors.rs index 93b626c77941..e4b89c65853d 100644 --- a/compiler/rustc_resolve/src/errors.rs +++ b/compiler/rustc_resolve/src/errors.rs @@ -646,3 +646,84 @@ pub(crate) struct ConsiderAddingADerive { pub(crate) span: Span, pub(crate) suggestion: String, } + +#[derive(Diagnostic)] +#[diag(resolve_cannot_determine_import_resolution)] +pub(crate) struct CannotDetermineImportResolution { + #[primary_span] + pub(crate) span: Span, +} + +#[derive(Diagnostic)] +#[diag(resolve_cannot_be_reexported_private, code = "E0364")] +pub(crate) struct CannotBeReexportedPrivate { + #[primary_span] + pub(crate) span: Span, + pub(crate) ident: Ident, +} + +#[derive(Diagnostic)] +#[diag(resolve_cannot_be_reexported_crate_public, code = "E0364")] +pub(crate) struct CannotBeReexportedCratePublic { + #[primary_span] + pub(crate) span: Span, + pub(crate) ident: Ident, +} + +#[derive(Diagnostic)] +#[diag(resolve_cannot_be_reexported_private, code = "E0365")] +#[note(resolve_consider_declaring_with_pub)] +pub(crate) struct CannotBeReexportedPrivateNS { + #[primary_span] + #[label(resolve_reexport_of_private)] + pub(crate) span: Span, + pub(crate) ident: Ident, +} + +#[derive(Diagnostic)] +#[diag(resolve_cannot_be_reexported_crate_public, code = "E0365")] +#[note(resolve_consider_declaring_with_pub)] +pub(crate) struct CannotBeReexportedCratePublicNS { + #[primary_span] + #[label(resolve_reexport_of_crate_public)] + pub(crate) span: Span, + pub(crate) ident: Ident, +} + +#[derive(Subdiagnostic)] +#[help(resolve_consider_adding_macro_export)] +pub(crate) struct ConsiderAddingMacroExport { + #[primary_span] + pub(crate) span: Span, +} + +#[derive(Subdiagnostic)] +#[note(resolve_consider_marking_as_pub)] +pub(crate) struct ConsiderMarkingAsPub { + #[primary_span] + pub(crate) span: Span, + pub(crate) ident: Ident, +} + +#[derive(Diagnostic)] +#[diag(resolve_cannot_glob_import_possible_crates)] +pub(crate) struct CannotGlobImportAllCrates { + #[primary_span] + pub(crate) span: Span, +} + +#[derive(Diagnostic)] +#[diag(resolve_items_in_traits_are_not_importable)] +pub(crate) struct ItemsInTraitsAreNotImportable { + #[primary_span] + pub(crate) span: Span, +} + +#[derive(Diagnostic)] +#[diag(resolve_is_not_directly_importable, code = "E0253")] +pub(crate) struct IsNotDirectlyImportable { + #[primary_span] + #[label] + pub(crate) span: Span, + pub(crate) target: Ident, +} diff --git a/compiler/rustc_resolve/src/imports.rs b/compiler/rustc_resolve/src/imports.rs index 444533099200..35491ebe10cf 100644 --- a/compiler/rustc_resolve/src/imports.rs +++ b/compiler/rustc_resolve/src/imports.rs @@ -1,8 +1,14 @@ //! A bunch of methods and structures more or less related to resolving imports. use crate::diagnostics::{import_candidates, DiagnosticMode, Suggestion}; +use crate::errors::{ + CannotBeReexportedCratePublic, CannotBeReexportedCratePublicNS, CannotBeReexportedPrivate, + CannotBeReexportedPrivateNS, CannotDetermineImportResolution, CannotGlobImportAllCrates, + ConsiderAddingMacroExport, ConsiderMarkingAsPub, IsNotDirectlyImportable, + ItemsInTraitsAreNotImportable, +}; use crate::Determinacy::{self, *}; -use crate::Namespace::*; +use crate::{fluent_generated as fluent, Namespace::*}; use crate::{module_to_string, names_to_string, ImportSuggestion}; use crate::{ AmbiguityError, AmbiguityErrorMisc, AmbiguityKind, BindingKey, ModuleKind, ResolutionError, @@ -609,7 +615,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { } } - fn throw_unresolved_import_error(&self, errors: Vec<(&Import<'_>, UnresolvedImportError)>) { + fn throw_unresolved_import_error(&mut self, errors: Vec<(&Import<'_>, UnresolvedImportError)>) { if errors.is_empty() { return; } @@ -679,6 +685,17 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { _ => {} } } + + match &import.kind { + ImportKind::Single { source, .. } => { + if let Some(ModuleOrUniformRoot::Module(module)) = import.imported_module.get() + && let Some(module) = module.opt_def_id() + { + self.find_cfg_stripped(&mut diag, &source.name, module) + } + }, + _ => {} + } } diag.emit(); @@ -763,9 +780,9 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { } source_binding @ (Ok(..) | Err(Determined)) => { if source_binding.is_ok() { - let msg = format!("`{}` is not directly importable", target); - struct_span_err!(this.tcx.sess, import.span, E0253, "{}", &msg) - .span_label(import.span, "cannot be imported directly") + this.tcx + .sess + .create_err(IsNotDirectlyImportable { span: import.span, target }) .emit(); } let key = BindingKey::new(target, ns); @@ -814,9 +831,10 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { span_bug!(import.span, "inconsistent resolution for an import"); } } else if self.privacy_errors.is_empty() { - let msg = "cannot determine resolution for the import"; - let msg_note = "import resolution is stuck, try simplifying other imports"; - self.tcx.sess.struct_span_err(import.span, msg).note(msg_note).emit(); + self.tcx + .sess + .create_err(CannotDetermineImportResolution { span: import.span }) + .emit(); } module @@ -927,8 +945,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { && let Some(max_vis) = max_vis.get() && !max_vis.is_at_least(import.expect_vis(), self.tcx) { - let msg = "glob import doesn't reexport anything because no candidate is public enough"; - self.lint_buffer.buffer_lint(UNUSED_IMPORTS, id, import.span, msg); + self.lint_buffer.buffer_lint(UNUSED_IMPORTS, id, import.span, fluent::resolve_glob_import_doesnt_reexport); } return None; } @@ -1000,10 +1017,10 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { && this.ambiguity_errors.is_empty() && this.privacy_errors.is_empty() { - let msg = "cannot determine resolution for the import"; - let msg_note = - "import resolution is stuck, try simplifying other imports"; - this.tcx.sess.struct_span_err(import.span, msg).note(msg_note).emit(); + this.tcx + .sess + .create_err(CannotDetermineImportResolution { span: import.span }) + .emit(); } } Err(..) => { @@ -1161,46 +1178,43 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { msg, ); } else { - let error_msg = if crate_private_reexport { - format!( - "`{}` is only public within the crate, and cannot be re-exported outside", - ident - ) - } else { - format!("`{}` is private, and cannot be re-exported", ident) - }; - if ns == TypeNS { - let label_msg = if crate_private_reexport { - format!("re-export of crate public `{}`", ident) + let mut err = if crate_private_reexport { + self.tcx.sess.create_err(CannotBeReexportedCratePublicNS { + span: import.span, + ident, + }) } else { - format!("re-export of private `{}`", ident) + self.tcx + .sess + .create_err(CannotBeReexportedPrivateNS { span: import.span, ident }) + }; + err.emit(); + } else { + let mut err = if crate_private_reexport { + self.tcx + .sess + .create_err(CannotBeReexportedCratePublic { span: import.span, ident }) + } else { + self.tcx + .sess + .create_err(CannotBeReexportedPrivate { span: import.span, ident }) }; - struct_span_err!(self.tcx.sess, import.span, E0365, "{}", error_msg) - .span_label(import.span, label_msg) - .note(format!("consider declaring type or module `{}` with `pub`", ident)) - .emit(); - } else { - let mut err = - struct_span_err!(self.tcx.sess, import.span, E0364, "{error_msg}"); match binding.kind { NameBindingKind::Res(Res::Def(DefKind::Macro(_), def_id)) // exclude decl_macro if self.get_macro_by_def_id(def_id).macro_rules => { - err.span_help( - binding.span, - "consider adding a `#[macro_export]` to the macro in the imported module", - ); + err.subdiagnostic(ConsiderAddingMacroExport { + span: binding.span, + }); } _ => { - err.span_note( - import.span, - format!( - "consider marking `{ident}` as `pub` in the imported module" - ), - ); + err.subdiagnostic(ConsiderMarkingAsPub { + span: import.span, + ident, + }); } } err.emit(); @@ -1306,12 +1320,14 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { let ImportKind::Glob { id, is_prelude, .. } = import.kind else { unreachable!() }; let ModuleOrUniformRoot::Module(module) = import.imported_module.get().unwrap() else { - self.tcx.sess.span_err(import.span, "cannot glob-import all possible crates"); + self.tcx.sess.create_err(CannotGlobImportAllCrates { + span: import.span, + }).emit(); return; }; if module.is_trait() { - self.tcx.sess.span_err(import.span, "items in traits are not importable"); + self.tcx.sess.create_err(ItemsInTraitsAreNotImportable { span: import.span }).emit(); return; } else if ptr::eq(module, import.parent_scope.module) { return; diff --git a/compiler/rustc_resolve/src/late/diagnostics.rs b/compiler/rustc_resolve/src/late/diagnostics.rs index 475772734ff8..c62fc031a16b 100644 --- a/compiler/rustc_resolve/src/late/diagnostics.rs +++ b/compiler/rustc_resolve/src/late/diagnostics.rs @@ -2183,10 +2183,9 @@ impl<'a: 'ast, 'ast, 'tcx> LateResolutionVisitor<'a, '_, 'ast, 'tcx> { None => { debug!(?param.ident, ?param.ident.span); let deletion_span = deletion_span(); - // the give lifetime originates from expanded code so we won't be able to remove it #104432 - let lifetime_only_in_expanded_code = - deletion_span.map(|sp| sp.in_derive_expansion()).unwrap_or(true); - if !lifetime_only_in_expanded_code { + + // if the lifetime originates from expanded code, we won't be able to remove it #104432 + if deletion_span.is_some_and(|sp| !sp.in_derive_expansion()) { self.r.lint_buffer.buffer_lint_with_diagnostic( lint::builtin::UNUSED_LIFETIMES, param.id, diff --git a/compiler/rustc_session/src/config.rs b/compiler/rustc_session/src/config.rs index a9668ae48289..480d2478e817 100644 --- a/compiler/rustc_session/src/config.rs +++ b/compiler/rustc_session/src/config.rs @@ -5,8 +5,8 @@ pub use crate::options::*; use crate::search_paths::SearchPath; use crate::utils::{CanonicalizedPath, NativeLib, NativeLibKind}; -use crate::{early_error, early_warn, Session}; use crate::{lint, HashStableContext}; +use crate::{EarlyErrorHandler, Session}; use rustc_data_structures::fx::{FxHashMap, FxHashSet}; @@ -1389,6 +1389,7 @@ pub fn build_configuration(sess: &Session, mut user_cfg: CrateConfig) -> CrateCo } pub(super) fn build_target_config( + handler: &EarlyErrorHandler, opts: &Options, target_override: Option, sysroot: &Path, @@ -1398,27 +1399,21 @@ pub(super) fn build_target_config( |t| Ok((t, TargetWarnings::empty())), ); let (target, target_warnings) = target_result.unwrap_or_else(|e| { - early_error( - opts.error_format, - format!( - "Error loading target specification: {}. \ + handler.early_error(format!( + "Error loading target specification: {}. \ Run `rustc --print target-list` for a list of built-in targets", - e - ), - ) + e + )) }); for warning in target_warnings.warning_messages() { - early_warn(opts.error_format, warning) + handler.early_warn(warning) } if !matches!(target.pointer_width, 16 | 32 | 64) { - early_error( - opts.error_format, - format!( - "target specification was invalid: unrecognized target-pointer-width {}", - target.pointer_width - ), - ) + handler.early_error(format!( + "target specification was invalid: unrecognized target-pointer-width {}", + target.pointer_width + )) } target @@ -1654,8 +1649,8 @@ pub fn rustc_optgroups() -> Vec { } pub fn get_cmd_lint_options( + handler: &EarlyErrorHandler, matches: &getopts::Matches, - error_format: ErrorOutputType, ) -> (Vec<(String, lint::Level)>, bool, Option) { let mut lint_opts_with_position = vec![]; let mut describe_lints = false; @@ -1679,14 +1674,14 @@ pub fn get_cmd_lint_options( let lint_cap = matches.opt_str("cap-lints").map(|cap| { lint::Level::from_str(&cap) - .unwrap_or_else(|| early_error(error_format, format!("unknown lint level: `{cap}`"))) + .unwrap_or_else(|| handler.early_error(format!("unknown lint level: `{cap}`"))) }); (lint_opts, describe_lints, lint_cap) } /// Parses the `--color` flag. -pub fn parse_color(matches: &getopts::Matches) -> ColorConfig { +pub fn parse_color(handler: &EarlyErrorHandler, matches: &getopts::Matches) -> ColorConfig { match matches.opt_str("color").as_deref() { Some("auto") => ColorConfig::Auto, Some("always") => ColorConfig::Always, @@ -1694,13 +1689,10 @@ pub fn parse_color(matches: &getopts::Matches) -> ColorConfig { None => ColorConfig::Auto, - Some(arg) => early_error( - ErrorOutputType::default(), - format!( - "argument for `--color` must be auto, \ + Some(arg) => handler.early_error(format!( + "argument for `--color` must be auto, \ always or never (instead was `{arg}`)" - ), - ), + )), } } @@ -1743,7 +1735,7 @@ impl JsonUnusedExterns { /// /// The first value returned is how to render JSON diagnostics, and the second /// is whether or not artifact notifications are enabled. -pub fn parse_json(matches: &getopts::Matches) -> JsonConfig { +pub fn parse_json(handler: &EarlyErrorHandler, matches: &getopts::Matches) -> JsonConfig { let mut json_rendered: fn(ColorConfig) -> HumanReadableErrorType = HumanReadableErrorType::Default; let mut json_color = ColorConfig::Never; @@ -1755,10 +1747,7 @@ pub fn parse_json(matches: &getopts::Matches) -> JsonConfig { // won't actually be emitting any colors and anything colorized is // embedded in a diagnostic message anyway. if matches.opt_str("color").is_some() { - early_error( - ErrorOutputType::default(), - "cannot specify the `--color` option with `--json`", - ); + handler.early_error("cannot specify the `--color` option with `--json`"); } for sub_option in option.split(',') { @@ -1769,10 +1758,7 @@ pub fn parse_json(matches: &getopts::Matches) -> JsonConfig { "unused-externs" => json_unused_externs = JsonUnusedExterns::Loud, "unused-externs-silent" => json_unused_externs = JsonUnusedExterns::Silent, "future-incompat" => json_future_incompat = true, - s => early_error( - ErrorOutputType::default(), - format!("unknown `--json` option `{s}`"), - ), + s => handler.early_error(format!("unknown `--json` option `{s}`")), } } } @@ -1787,6 +1773,7 @@ pub fn parse_json(matches: &getopts::Matches) -> JsonConfig { /// Parses the `--error-format` flag. pub fn parse_error_format( + handler: &mut EarlyErrorHandler, matches: &getopts::Matches, color: ColorConfig, json_rendered: HumanReadableErrorType, @@ -1807,13 +1794,15 @@ pub fn parse_error_format( Some("pretty-json") => ErrorOutputType::Json { pretty: true, json_rendered }, Some("short") => ErrorOutputType::HumanReadable(HumanReadableErrorType::Short(color)), - Some(arg) => early_error( - ErrorOutputType::HumanReadable(HumanReadableErrorType::Default(color)), - format!( + Some(arg) => { + handler.abort_if_error_and_set_error_format(ErrorOutputType::HumanReadable( + HumanReadableErrorType::Default(color), + )); + handler.early_error(format!( "argument for `--error-format` must be `human`, `json` or \ `short` (instead was `{arg}`)" - ), - ), + )) + } } } else { ErrorOutputType::HumanReadable(HumanReadableErrorType::Default(color)) @@ -1826,10 +1815,7 @@ pub fn parse_error_format( // `--error-format=json`. This means that `--json` is specified we // should actually be emitting JSON blobs. _ if !matches.opt_strs("json").is_empty() => { - early_error( - ErrorOutputType::default(), - "using `--json` requires also using `--error-format=json`", - ); + handler.early_error("using `--json` requires also using `--error-format=json`"); } _ => {} @@ -1838,16 +1824,13 @@ pub fn parse_error_format( error_format } -pub fn parse_crate_edition(matches: &getopts::Matches) -> Edition { +pub fn parse_crate_edition(handler: &EarlyErrorHandler, matches: &getopts::Matches) -> Edition { let edition = match matches.opt_str("edition") { Some(arg) => Edition::from_str(&arg).unwrap_or_else(|_| { - early_error( - ErrorOutputType::default(), - format!( - "argument for `--edition` must be one of: \ + handler.early_error(format!( + "argument for `--edition` must be one of: \ {EDITION_NAME_LIST}. (instead was `{arg}`)" - ), - ) + )) }), None => DEFAULT_EDITION, }; @@ -1862,39 +1845,42 @@ pub fn parse_crate_edition(matches: &getopts::Matches) -> Edition { } else { format!("edition {edition} is unstable and only available with -Z unstable-options") }; - early_error(ErrorOutputType::default(), msg) + handler.early_error(msg) } edition } fn check_error_format_stability( + handler: &mut EarlyErrorHandler, unstable_opts: &UnstableOptions, error_format: ErrorOutputType, json_rendered: HumanReadableErrorType, ) { if !unstable_opts.unstable_options { if let ErrorOutputType::Json { pretty: true, json_rendered } = error_format { - early_error( - ErrorOutputType::Json { pretty: false, json_rendered }, - "`--error-format=pretty-json` is unstable", - ); + handler.abort_if_error_and_set_error_format(ErrorOutputType::Json { + pretty: false, + json_rendered, + }); + handler.early_error("`--error-format=pretty-json` is unstable"); } if let ErrorOutputType::HumanReadable(HumanReadableErrorType::AnnotateSnippet(_)) = error_format { - early_error( - ErrorOutputType::Json { pretty: false, json_rendered }, - "`--error-format=human-annotate-rs` is unstable", - ); + handler.abort_if_error_and_set_error_format(ErrorOutputType::Json { + pretty: false, + json_rendered, + }); + handler.early_error("`--error-format=human-annotate-rs` is unstable"); } } } fn parse_output_types( + handler: &EarlyErrorHandler, unstable_opts: &UnstableOptions, matches: &getopts::Matches, - error_format: ErrorOutputType, ) -> OutputTypes { let mut output_types = BTreeMap::new(); if !unstable_opts.parse_only { @@ -1908,13 +1894,10 @@ fn parse_output_types( } }; let output_type = OutputType::from_shorthand(shorthand).unwrap_or_else(|| { - early_error( - error_format, - format!( - "unknown emission type: `{shorthand}` - expected one of: {display}", - display = OutputType::shorthands_display(), - ), - ) + handler.early_error(format!( + "unknown emission type: `{shorthand}` - expected one of: {display}", + display = OutputType::shorthands_display(), + )) }); output_types.insert(output_type, path); } @@ -1927,9 +1910,9 @@ fn parse_output_types( } fn should_override_cgus_and_disable_thinlto( + handler: &EarlyErrorHandler, output_types: &OutputTypes, matches: &getopts::Matches, - error_format: ErrorOutputType, mut codegen_units: Option, ) -> (bool, Option) { let mut disable_local_thinlto = false; @@ -1947,15 +1930,12 @@ fn should_override_cgus_and_disable_thinlto( Some(n) if n > 1 => { if matches.opt_present("o") { for ot in &incompatible { - early_warn( - error_format, - format!( - "`--emit={ot}` with `-o` incompatible with \ + handler.early_warn(format!( + "`--emit={ot}` with `-o` incompatible with \ `-C codegen-units=N` for N > 1", - ), - ); + )); } - early_warn(error_format, "resetting to default -C codegen-units=1"); + handler.early_warn("resetting to default -C codegen-units=1"); codegen_units = Some(1); disable_local_thinlto = true; } @@ -1968,27 +1948,27 @@ fn should_override_cgus_and_disable_thinlto( } if codegen_units == Some(0) { - early_error(error_format, "value for codegen units must be a positive non-zero integer"); + handler.early_error("value for codegen units must be a positive non-zero integer"); } (disable_local_thinlto, codegen_units) } -fn check_thread_count(unstable_opts: &UnstableOptions, error_format: ErrorOutputType) { +fn check_thread_count(handler: &EarlyErrorHandler, unstable_opts: &UnstableOptions) { if unstable_opts.threads == 0 { - early_error(error_format, "value for threads must be a positive non-zero integer"); + handler.early_error("value for threads must be a positive non-zero integer"); } if unstable_opts.threads > 1 && unstable_opts.fuel.is_some() { - early_error(error_format, "optimization fuel is incompatible with multiple threads"); + handler.early_error("optimization fuel is incompatible with multiple threads"); } } fn collect_print_requests( + handler: &EarlyErrorHandler, cg: &mut CodegenOptions, unstable_opts: &mut UnstableOptions, matches: &getopts::Matches, - error_format: ErrorOutputType, ) -> Vec { let mut prints = Vec::::new(); if cg.target_cpu.as_ref().is_some_and(|s| s == "help") { @@ -2028,8 +2008,7 @@ fn collect_print_requests( if unstable_opts.unstable_options { PrintRequest::TargetSpec } else { - early_error( - error_format, + handler.early_error( "the `-Z unstable-options` flag must also be passed to \ enable the target-spec-json print option", ); @@ -2039,8 +2018,7 @@ fn collect_print_requests( if unstable_opts.unstable_options { PrintRequest::AllTargetSpecs } else { - early_error( - error_format, + handler.early_error( "the `-Z unstable-options` flag must also be passed to \ enable the all-target-specs-json print option", ); @@ -2051,10 +2029,9 @@ fn collect_print_requests( let prints = PRINT_REQUESTS.iter().map(|(name, _)| format!("`{name}`")).collect::>(); let prints = prints.join(", "); - early_error( - error_format, - format!("unknown print request `{req}`. Valid print requests are: {prints}"), - ); + handler.early_error(format!( + "unknown print request `{req}`. Valid print requests are: {prints}" + )); } } })); @@ -2063,14 +2040,14 @@ fn collect_print_requests( } pub fn parse_target_triple( + handler: &EarlyErrorHandler, matches: &getopts::Matches, - error_format: ErrorOutputType, ) -> TargetTriple { match matches.opt_str("target") { Some(target) if target.ends_with(".json") => { let path = Path::new(&target); TargetTriple::from_path(path).unwrap_or_else(|_| { - early_error(error_format, format!("target file {path:?} does not exist")) + handler.early_error(format!("target file {path:?} does not exist")) }) } Some(target) => TargetTriple::TargetTriple(target), @@ -2079,9 +2056,9 @@ pub fn parse_target_triple( } fn parse_opt_level( + handler: &EarlyErrorHandler, matches: &getopts::Matches, cg: &CodegenOptions, - error_format: ErrorOutputType, ) -> OptLevel { // The `-O` and `-C opt-level` flags specify the same setting, so we want to be able // to use them interchangeably. However, because they're technically different flags, @@ -2109,13 +2086,10 @@ fn parse_opt_level( "s" => OptLevel::Size, "z" => OptLevel::SizeMin, arg => { - early_error( - error_format, - format!( - "optimization level needs to be \ + handler.early_error(format!( + "optimization level needs to be \ between 0-3, s or z (instead was `{arg}`)" - ), - ); + )); } } } @@ -2135,23 +2109,23 @@ fn select_debuginfo(matches: &getopts::Matches, cg: &CodegenOptions) -> DebugInf } pub(crate) fn parse_assert_incr_state( + handler: &EarlyErrorHandler, opt_assertion: &Option, - error_format: ErrorOutputType, ) -> Option { match opt_assertion { Some(s) if s.as_str() == "loaded" => Some(IncrementalStateAssertion::Loaded), Some(s) if s.as_str() == "not-loaded" => Some(IncrementalStateAssertion::NotLoaded), Some(s) => { - early_error(error_format, format!("unexpected incremental state assertion value: {s}")) + handler.early_error(format!("unexpected incremental state assertion value: {s}")) } None => None, } } fn parse_native_lib_kind( + handler: &EarlyErrorHandler, matches: &getopts::Matches, kind: &str, - error_format: ErrorOutputType, ) -> (NativeLibKind, Option) { let (kind, modifiers) = match kind.split_once(':') { None => (kind, None), @@ -2169,35 +2143,31 @@ fn parse_native_lib_kind( } else { ", the `-Z unstable-options` flag must also be passed to use it" }; - early_error(error_format, format!("library kind `link-arg` is unstable{why}")) + handler.early_error(format!("library kind `link-arg` is unstable{why}")) } NativeLibKind::LinkArg } - _ => early_error( - error_format, - format!( - "unknown library kind `{kind}`, expected one of: static, dylib, framework, link-arg" - ), - ), + _ => handler.early_error(format!( + "unknown library kind `{kind}`, expected one of: static, dylib, framework, link-arg" + )), }; match modifiers { None => (kind, None), - Some(modifiers) => parse_native_lib_modifiers(kind, modifiers, error_format, matches), + Some(modifiers) => parse_native_lib_modifiers(handler, kind, modifiers, matches), } } fn parse_native_lib_modifiers( + handler: &EarlyErrorHandler, mut kind: NativeLibKind, modifiers: &str, - error_format: ErrorOutputType, matches: &getopts::Matches, ) -> (NativeLibKind, Option) { let mut verbatim = None; for modifier in modifiers.split(',') { let (modifier, value) = match modifier.strip_prefix(['+', '-']) { Some(m) => (m, modifier.starts_with('+')), - None => early_error( - error_format, + None => handler.early_error( "invalid linking modifier syntax, expected '+' or '-' prefix \ before one of: bundle, verbatim, whole-archive, as-needed", ), @@ -2210,21 +2180,20 @@ fn parse_native_lib_modifiers( } else { ", the `-Z unstable-options` flag must also be passed to use it" }; - early_error(error_format, format!("linking modifier `{modifier}` is unstable{why}")) + handler.early_error(format!("linking modifier `{modifier}` is unstable{why}")) } }; let assign_modifier = |dst: &mut Option| { if dst.is_some() { let msg = format!("multiple `{modifier}` modifiers in a single `-l` option"); - early_error(error_format, msg) + handler.early_error(msg) } else { *dst = Some(value); } }; match (modifier, &mut kind) { ("bundle", NativeLibKind::Static { bundle, .. }) => assign_modifier(bundle), - ("bundle", _) => early_error( - error_format, + ("bundle", _) => handler.early_error( "linking modifier `bundle` is only compatible with `static` linking kind", ), @@ -2233,8 +2202,7 @@ fn parse_native_lib_modifiers( ("whole-archive", NativeLibKind::Static { whole_archive, .. }) => { assign_modifier(whole_archive) } - ("whole-archive", _) => early_error( - error_format, + ("whole-archive", _) => handler.early_error( "linking modifier `whole-archive` is only compatible with `static` linking kind", ), @@ -2243,28 +2211,24 @@ fn parse_native_lib_modifiers( report_unstable_modifier(); assign_modifier(as_needed) } - ("as-needed", _) => early_error( - error_format, + ("as-needed", _) => handler.early_error( "linking modifier `as-needed` is only compatible with \ `dylib` and `framework` linking kinds", ), // Note: this error also excludes the case with empty modifier // string, like `modifiers = ""`. - _ => early_error( - error_format, - format!( - "unknown linking modifier `{modifier}`, expected one \ + _ => handler.early_error(format!( + "unknown linking modifier `{modifier}`, expected one \ of: bundle, verbatim, whole-archive, as-needed" - ), - ), + )), } } (kind, verbatim) } -fn parse_libs(matches: &getopts::Matches, error_format: ErrorOutputType) -> Vec { +fn parse_libs(handler: &EarlyErrorHandler, matches: &getopts::Matches) -> Vec { matches .opt_strs("l") .into_iter() @@ -2278,7 +2242,7 @@ fn parse_libs(matches: &getopts::Matches, error_format: ErrorOutputType) -> Vec< let (name, kind, verbatim) = match s.split_once('=') { None => (s, NativeLibKind::Unspecified, None), Some((kind, name)) => { - let (kind, verbatim) = parse_native_lib_kind(matches, kind, error_format); + let (kind, verbatim) = parse_native_lib_kind(handler, matches, kind); (name.to_string(), kind, verbatim) } }; @@ -2288,7 +2252,7 @@ fn parse_libs(matches: &getopts::Matches, error_format: ErrorOutputType) -> Vec< Some((name, new_name)) => (name.to_string(), Some(new_name.to_owned())), }; if name.is_empty() { - early_error(error_format, "library name must not be empty"); + handler.early_error("library name must not be empty"); } NativeLib { name, new_name, kind, verbatim } }) @@ -2296,9 +2260,9 @@ fn parse_libs(matches: &getopts::Matches, error_format: ErrorOutputType) -> Vec< } pub fn parse_externs( + handler: &EarlyErrorHandler, matches: &getopts::Matches, unstable_opts: &UnstableOptions, - error_format: ErrorOutputType, ) -> Externs { let is_unstable_enabled = unstable_opts.unstable_options; let mut externs: BTreeMap = BTreeMap::new(); @@ -2362,8 +2326,7 @@ pub fn parse_externs( let mut force = false; if let Some(opts) = options { if !is_unstable_enabled { - early_error( - error_format, + handler.early_error( "the `-Z unstable-options` flag must also be passed to \ enable `--extern` options", ); @@ -2375,15 +2338,14 @@ pub fn parse_externs( if let ExternLocation::ExactPaths(_) = &entry.location { add_prelude = false; } else { - early_error( - error_format, + handler.early_error( "the `noprelude` --extern option requires a file path", ); } } "nounused" => nounused_dep = true, "force" => force = true, - _ => early_error(error_format, format!("unknown --extern option `{opt}`")), + _ => handler.early_error(format!("unknown --extern option `{opt}`")), } } } @@ -2402,18 +2364,15 @@ pub fn parse_externs( } fn parse_remap_path_prefix( + handler: &EarlyErrorHandler, matches: &getopts::Matches, unstable_opts: &UnstableOptions, - error_format: ErrorOutputType, ) -> Vec<(PathBuf, PathBuf)> { let mut mapping: Vec<(PathBuf, PathBuf)> = matches .opt_strs("remap-path-prefix") .into_iter() .map(|remap| match remap.rsplit_once('=') { - None => early_error( - error_format, - "--remap-path-prefix must contain '=' between FROM and TO", - ), + None => handler.early_error("--remap-path-prefix must contain '=' between FROM and TO"), Some((from, to)) => (PathBuf::from(from), PathBuf::from(to)), }) .collect(); @@ -2429,86 +2388,75 @@ fn parse_remap_path_prefix( // JUSTIFICATION: before wrapper fn is available #[allow(rustc::bad_opt_access)] -pub fn build_session_options(matches: &getopts::Matches) -> Options { - let color = parse_color(matches); +pub fn build_session_options( + handler: &mut EarlyErrorHandler, + matches: &getopts::Matches, +) -> Options { + let color = parse_color(handler, matches); - let edition = parse_crate_edition(matches); + let edition = parse_crate_edition(handler, matches); let JsonConfig { json_rendered, json_artifact_notifications, json_unused_externs, json_future_incompat, - } = parse_json(matches); + } = parse_json(handler, matches); - let error_format = parse_error_format(matches, color, json_rendered); + let error_format = parse_error_format(handler, matches, color, json_rendered); let diagnostic_width = matches.opt_get("diagnostic-width").unwrap_or_else(|_| { - early_error(error_format, "`--diagnostic-width` must be an positive integer"); + handler.early_error("`--diagnostic-width` must be an positive integer"); }); let unparsed_crate_types = matches.opt_strs("crate-type"); let crate_types = parse_crate_types_from_list(unparsed_crate_types) - .unwrap_or_else(|e| early_error(error_format, e)); + .unwrap_or_else(|e| handler.early_error(e)); - let mut unstable_opts = UnstableOptions::build(matches, error_format); - let (lint_opts, describe_lints, lint_cap) = get_cmd_lint_options(matches, error_format); + let mut unstable_opts = UnstableOptions::build(handler, matches); + let (lint_opts, describe_lints, lint_cap) = get_cmd_lint_options(handler, matches); - check_error_format_stability(&unstable_opts, error_format, json_rendered); + check_error_format_stability(handler, &unstable_opts, error_format, json_rendered); if !unstable_opts.unstable_options && json_unused_externs.is_enabled() { - early_error( - error_format, + handler.early_error( "the `-Z unstable-options` flag must also be passed to enable \ the flag `--json=unused-externs`", ); } - let output_types = parse_output_types(&unstable_opts, matches, error_format); + let output_types = parse_output_types(handler, &unstable_opts, matches); - let mut cg = CodegenOptions::build(matches, error_format); - let (disable_local_thinlto, mut codegen_units) = should_override_cgus_and_disable_thinlto( - &output_types, - matches, - error_format, - cg.codegen_units, - ); + let mut cg = CodegenOptions::build(handler, matches); + let (disable_local_thinlto, mut codegen_units) = + should_override_cgus_and_disable_thinlto(handler, &output_types, matches, cg.codegen_units); - check_thread_count(&unstable_opts, error_format); + check_thread_count(handler, &unstable_opts); let incremental = cg.incremental.as_ref().map(PathBuf::from); - let assert_incr_state = parse_assert_incr_state(&unstable_opts.assert_incr_state, error_format); + let assert_incr_state = parse_assert_incr_state(handler, &unstable_opts.assert_incr_state); if unstable_opts.profile && incremental.is_some() { - early_error( - error_format, - "can't instrument with gcov profiling when compiling incrementally", - ); + handler.early_error("can't instrument with gcov profiling when compiling incrementally"); } if unstable_opts.profile { match codegen_units { Some(1) => {} None => codegen_units = Some(1), - Some(_) => early_error( - error_format, - "can't instrument with gcov profiling with multiple codegen units", - ), + Some(_) => handler + .early_error("can't instrument with gcov profiling with multiple codegen units"), } } if cg.profile_generate.enabled() && cg.profile_use.is_some() { - early_error( - error_format, - "options `-C profile-generate` and `-C profile-use` are exclusive", - ); + handler.early_error("options `-C profile-generate` and `-C profile-use` are exclusive"); } if unstable_opts.profile_sample_use.is_some() && (cg.profile_generate.enabled() || cg.profile_use.is_some()) { - early_error( - error_format, + handler.early_error( "option `-Z profile-sample-use` cannot be used with `-C profile-generate` or `-C profile-use`", ); } @@ -2517,23 +2465,19 @@ pub fn build_session_options(matches: &getopts::Matches) -> Options { // precedence. match (cg.symbol_mangling_version, unstable_opts.symbol_mangling_version) { (Some(smv_c), Some(smv_z)) if smv_c != smv_z => { - early_error( - error_format, + handler.early_error( "incompatible values passed for `-C symbol-mangling-version` \ and `-Z symbol-mangling-version`", ); } (Some(SymbolManglingVersion::V0), _) => {} (Some(_), _) if !unstable_opts.unstable_options => { - early_error( - error_format, - "`-C symbol-mangling-version=legacy` requires `-Z unstable-options`", - ); + handler + .early_error("`-C symbol-mangling-version=legacy` requires `-Z unstable-options`"); } (None, None) => {} (None, smv) => { - early_warn( - error_format, + handler.early_warn( "`-Z symbol-mangling-version` is deprecated; use `-C symbol-mangling-version`", ); cg.symbol_mangling_version = smv; @@ -2545,25 +2489,19 @@ pub fn build_session_options(matches: &getopts::Matches) -> Options { // precedence. match (cg.instrument_coverage, unstable_opts.instrument_coverage) { (Some(ic_c), Some(ic_z)) if ic_c != ic_z => { - early_error( - error_format, + handler.early_error( "incompatible values passed for `-C instrument-coverage` \ and `-Z instrument-coverage`", ); } (Some(InstrumentCoverage::Off | InstrumentCoverage::All), _) => {} (Some(_), _) if !unstable_opts.unstable_options => { - early_error( - error_format, - "`-C instrument-coverage=except-*` requires `-Z unstable-options`", - ); + handler.early_error("`-C instrument-coverage=except-*` requires `-Z unstable-options`"); } (None, None) => {} (None, ic) => { - early_warn( - error_format, - "`-Z instrument-coverage` is deprecated; use `-C instrument-coverage`", - ); + handler + .early_warn("`-Z instrument-coverage` is deprecated; use `-C instrument-coverage`"); cg.instrument_coverage = ic; } _ => {} @@ -2571,8 +2509,7 @@ pub fn build_session_options(matches: &getopts::Matches) -> Options { if cg.instrument_coverage.is_some() && cg.instrument_coverage != Some(InstrumentCoverage::Off) { if cg.profile_generate.enabled() || cg.profile_use.is_some() { - early_error( - error_format, + handler.early_error( "option `-C instrument-coverage` is not compatible with either `-C profile-use` \ or `-C profile-generate`", ); @@ -2585,8 +2522,7 @@ pub fn build_session_options(matches: &getopts::Matches) -> Options { match cg.symbol_mangling_version { None => cg.symbol_mangling_version = Some(SymbolManglingVersion::V0), Some(SymbolManglingVersion::Legacy) => { - early_warn( - error_format, + handler.early_warn( "-C instrument-coverage requires symbol mangling version `v0`, \ but `-C symbol-mangling-version=legacy` was specified", ); @@ -2602,10 +2538,9 @@ pub fn build_session_options(matches: &getopts::Matches) -> Options { if !cg.embed_bitcode { match cg.lto { LtoCli::No | LtoCli::Unspecified => {} - LtoCli::Yes | LtoCli::NoParam | LtoCli::Thin | LtoCli::Fat => early_error( - error_format, - "options `-C embed-bitcode=no` and `-C lto` are incompatible", - ), + LtoCli::Yes | LtoCli::NoParam | LtoCli::Thin | LtoCli::Fat => { + handler.early_error("options `-C embed-bitcode=no` and `-C lto` are incompatible") + } } } @@ -2618,17 +2553,17 @@ pub fn build_session_options(matches: &getopts::Matches) -> Options { flag must also be passed to explicitly use it", flavor.desc() ); - early_error(error_format, msg); + handler.early_error(msg); } } - let prints = collect_print_requests(&mut cg, &mut unstable_opts, matches, error_format); + let prints = collect_print_requests(handler, &mut cg, &mut unstable_opts, matches); let cg = cg; let sysroot_opt = matches.opt_str("sysroot").map(|m| PathBuf::from(&m)); - let target_triple = parse_target_triple(matches, error_format); - let opt_level = parse_opt_level(matches, &cg, error_format); + let target_triple = parse_target_triple(handler, matches); + let opt_level = parse_opt_level(handler, matches, &cg); // The `-g` and `-C debuginfo` flags specify the same setting, so we want to be able // to use them interchangeably. See the note above (regarding `-O` and `-C opt-level`) // for more details. @@ -2637,28 +2572,28 @@ pub fn build_session_options(matches: &getopts::Matches) -> Options { let mut search_paths = vec![]; for s in &matches.opt_strs("L") { - search_paths.push(SearchPath::from_cli_opt(s, error_format)); + search_paths.push(SearchPath::from_cli_opt(handler, s)); } - let libs = parse_libs(matches, error_format); + let libs = parse_libs(handler, matches); let test = matches.opt_present("test"); if !cg.remark.is_empty() && debuginfo == DebugInfo::None { - early_warn(error_format, "-C remark requires \"-C debuginfo=n\" to show source locations"); + handler.early_warn("-C remark requires \"-C debuginfo=n\" to show source locations"); } - let externs = parse_externs(matches, &unstable_opts, error_format); + let externs = parse_externs(handler, matches, &unstable_opts); let crate_name = matches.opt_str("crate-name"); - let remap_path_prefix = parse_remap_path_prefix(matches, &unstable_opts, error_format); + let remap_path_prefix = parse_remap_path_prefix(handler, matches, &unstable_opts); - let pretty = parse_pretty(&unstable_opts, error_format); + let pretty = parse_pretty(handler, &unstable_opts); // query-dep-graph is required if dump-dep-graph is given #106736 if unstable_opts.dump_dep_graph && !unstable_opts.query_dep_graph { - early_error(error_format, "can't dump dependency graph without `-Z query-dep-graph`"); + handler.early_error("can't dump dependency graph without `-Z query-dep-graph`"); } // Try to find a directory containing the Rust `src`, for more details see @@ -2690,7 +2625,7 @@ pub fn build_session_options(matches: &getopts::Matches) -> Options { }; let working_dir = std::env::current_dir().unwrap_or_else(|e| { - early_error(error_format, format!("Current directory is invalid: {e}")); + handler.early_error(format!("Current directory is invalid: {e}")); }); let remap = FilePathMapping::new(remap_path_prefix.clone()); @@ -2741,7 +2676,7 @@ pub fn build_session_options(matches: &getopts::Matches) -> Options { } } -fn parse_pretty(unstable_opts: &UnstableOptions, efmt: ErrorOutputType) -> Option { +fn parse_pretty(handler: &EarlyErrorHandler, unstable_opts: &UnstableOptions) -> Option { use PpMode::*; let first = match unstable_opts.unpretty.as_deref()? { @@ -2760,16 +2695,13 @@ fn parse_pretty(unstable_opts: &UnstableOptions, efmt: ErrorOutputType) -> Optio "thir-flat" => ThirFlat, "mir" => Mir, "mir-cfg" => MirCFG, - name => early_error( - efmt, - format!( - "argument to `unpretty` must be one of `normal`, `identified`, \ + name => handler.early_error(format!( + "argument to `unpretty` must be one of `normal`, `identified`, \ `expanded`, `expanded,identified`, `expanded,hygiene`, \ `ast-tree`, `ast-tree,expanded`, `hir`, `hir,identified`, \ `hir,typed`, `hir-tree`, `thir-tree`, `thir-flat`, `mir` or \ `mir-cfg`; got {name}" - ), - ), + )), }; debug!("got unpretty option: {first:?}"); Some(first) @@ -2809,8 +2741,8 @@ pub fn parse_crate_types_from_list(list_list: Vec) -> Result bool { @@ -2826,7 +2758,11 @@ pub mod nightly_options { UnstableFeatures::from_environment(krate).is_nightly_build() } - pub fn check_nightly_options(matches: &getopts::Matches, flags: &[RustcOptGroup]) { + pub fn check_nightly_options( + handler: &EarlyErrorHandler, + matches: &getopts::Matches, + flags: &[RustcOptGroup], + ) { let has_z_unstable_option = matches.opt_strs("Z").iter().any(|x| *x == "unstable-options"); let really_allows_unstable_options = match_is_nightly_build(matches); @@ -2838,14 +2774,11 @@ pub mod nightly_options { continue; } if opt.name != "Z" && !has_z_unstable_option { - early_error( - ErrorOutputType::default(), - format!( - "the `-Z unstable-options` flag must also be passed to enable \ + handler.early_error(format!( + "the `-Z unstable-options` flag must also be passed to enable \ the flag `{}`", - opt.name - ), - ); + opt.name + )); } if really_allows_unstable_options { continue; @@ -2856,7 +2789,12 @@ pub mod nightly_options { "the option `{}` is only accepted on the nightly compiler", opt.name ); - early_error(ErrorOutputType::default(), msg); + let _ = handler.early_error_no_abort(msg); + handler.early_note("selecting a toolchain with `+toolchain` arguments require a rustup proxy; see "); + handler.early_help( + "consider switching to a nightly toolchain: `rustup default nightly`", + ); + handler.early_note("for more information about Rust's stability policy, see "); } OptionStability::Stable => {} } diff --git a/compiler/rustc_session/src/options.rs b/compiler/rustc_session/src/options.rs index 270d83316025..e5063eef47af 100644 --- a/compiler/rustc_session/src/options.rs +++ b/compiler/rustc_session/src/options.rs @@ -1,9 +1,8 @@ use crate::config::*; -use crate::early_error; -use crate::lint; use crate::search_paths::SearchPath; use crate::utils::NativeLib; +use crate::{lint, EarlyErrorHandler}; use rustc_data_structures::profiling::TimePassesFormat; use rustc_errors::{LanguageIdentifier, TerminalUrl}; use rustc_target::spec::{CodeModel, LinkerFlavorCli, MergeFunctions, PanicStrategy, SanitizerSet}; @@ -245,10 +244,10 @@ macro_rules! options { impl $struct_name { pub fn build( + handler: &EarlyErrorHandler, matches: &getopts::Matches, - error_format: ErrorOutputType, ) -> $struct_name { - build_options(matches, $stat, $prefix, $outputname, error_format) + build_options(handler, matches, $stat, $prefix, $outputname) } fn dep_tracking_hash(&self, for_crate_hash: bool, error_format: ErrorOutputType) -> u64 { @@ -309,11 +308,11 @@ type OptionSetter = fn(&mut O, v: Option<&str>) -> bool; type OptionDescrs = &'static [(&'static str, OptionSetter, &'static str, &'static str)]; fn build_options( + handler: &EarlyErrorHandler, matches: &getopts::Matches, descrs: OptionDescrs, prefix: &str, outputname: &str, - error_format: ErrorOutputType, ) -> O { let mut op = O::default(); for option in matches.opt_strs(prefix) { @@ -327,15 +326,13 @@ fn build_options( Some((_, setter, type_desc, _)) => { if !setter(&mut op, value) { match value { - None => early_error( - error_format, + None => handler.early_error( format!( "{0} option `{1}` requires {2} ({3} {1}=)", outputname, key, type_desc, prefix ), ), - Some(value) => early_error( - error_format, + Some(value) => handler.early_error( format!( "incorrect value `{value}` for {outputname} option `{key}` - {type_desc} was expected" ), @@ -343,7 +340,7 @@ fn build_options( } } } - None => early_error(error_format, format!("unknown {outputname} option: `{key}`")), + None => handler.early_error(format!("unknown {outputname} option: `{key}`")), } } return op; diff --git a/compiler/rustc_session/src/parse.rs b/compiler/rustc_session/src/parse.rs index a433e2371c9d..194f7201ff35 100644 --- a/compiler/rustc_session/src/parse.rs +++ b/compiler/rustc_session/src/parse.rs @@ -51,13 +51,6 @@ impl GatedSpans { debug_assert_eq!(span, removed_span); } - /// Is the provided `feature` gate ungated currently? - /// - /// Using this is discouraged unless you have a really good reason to. - pub fn is_ungated(&self, feature: Symbol) -> bool { - self.spans.borrow().get(&feature).map_or(true, |spans| spans.is_empty()) - } - /// Prepend the given set of `spans` onto the set in `self`. pub fn merge(&self, mut spans: FxHashMap>) { let mut inner = self.spans.borrow_mut(); diff --git a/compiler/rustc_session/src/search_paths.rs b/compiler/rustc_session/src/search_paths.rs index 56a6b6f3b03e..07e78d1760e8 100644 --- a/compiler/rustc_session/src/search_paths.rs +++ b/compiler/rustc_session/src/search_paths.rs @@ -1,5 +1,5 @@ use crate::filesearch::make_target_lib_path; -use crate::{config, early_error}; +use crate::EarlyErrorHandler; use std::path::{Path, PathBuf}; #[derive(Clone, Debug)] @@ -46,7 +46,7 @@ impl PathKind { } impl SearchPath { - pub fn from_cli_opt(path: &str, output: config::ErrorOutputType) -> Self { + pub fn from_cli_opt(handler: &EarlyErrorHandler, path: &str) -> Self { let (kind, path) = if let Some(stripped) = path.strip_prefix("native=") { (PathKind::Native, stripped) } else if let Some(stripped) = path.strip_prefix("crate=") { @@ -61,7 +61,7 @@ impl SearchPath { (PathKind::All, path) }; if path.is_empty() { - early_error(output, "empty search path given via `-L`"); + handler.early_error("empty search path given via `-L`"); } let dir = PathBuf::from(path); diff --git a/compiler/rustc_session/src/session.rs b/compiler/rustc_session/src/session.rs index ea5beb6f8beb..5be122ffbdeb 100644 --- a/compiler/rustc_session/src/session.rs +++ b/compiler/rustc_session/src/session.rs @@ -1,10 +1,10 @@ use crate::cgu_reuse_tracker::CguReuseTracker; use crate::code_stats::CodeStats; pub use crate::code_stats::{DataTypeKind, FieldInfo, FieldKind, SizeKind, VariantInfo}; -use crate::config::Input; use crate::config::{ self, CrateType, InstrumentCoverage, OptLevel, OutFileName, OutputType, SwitchWithOptPath, }; +use crate::config::{ErrorOutputType, Input}; use crate::errors; use crate::parse::{add_feature_diagnostics, ParseSess}; use crate::search_paths::{PathKind, SearchPath}; @@ -25,7 +25,7 @@ use rustc_errors::json::JsonEmitter; use rustc_errors::registry::Registry; use rustc_errors::{ error_code, fallback_fluent_bundle, DiagnosticBuilder, DiagnosticId, DiagnosticMessage, - ErrorGuaranteed, FluentBundle, IntoDiagnostic, LazyFallbackBundle, MultiSpan, Noted, + ErrorGuaranteed, FluentBundle, Handler, IntoDiagnostic, LazyFallbackBundle, MultiSpan, Noted, TerminalUrl, }; use rustc_macros::HashStable_Generic; @@ -1382,6 +1382,7 @@ fn default_emitter( // JUSTIFICATION: literally session construction #[allow(rustc::bad_opt_access)] pub fn build_session( + handler: &EarlyErrorHandler, sopts: config::Options, io: CompilerIO, bundle: Option>, @@ -1408,13 +1409,12 @@ pub fn build_session( None => filesearch::get_or_default_sysroot().expect("Failed finding sysroot"), }; - let target_cfg = config::build_target_config(&sopts, target_override, &sysroot); + let target_cfg = config::build_target_config(handler, &sopts, target_override, &sysroot); let host_triple = TargetTriple::from_triple(config::host_triple()); - let (host, target_warnings) = Target::search(&host_triple, &sysroot).unwrap_or_else(|e| { - early_error(sopts.error_format, format!("Error loading host specification: {e}")) - }); + let (host, target_warnings) = Target::search(&host_triple, &sysroot) + .unwrap_or_else(|e| handler.early_error(format!("Error loading host specification: {e}"))); for warning in target_warnings.warning_messages() { - early_warn(sopts.error_format, warning) + handler.early_warn(warning) } let loader = file_loader.unwrap_or_else(|| Box::new(RealFileLoader)); @@ -1456,7 +1456,7 @@ pub fn build_session( match profiler { Ok(profiler) => Some(Arc::new(profiler)), Err(e) => { - early_warn(sopts.error_format, format!("failed to create profiler: {e}")); + handler.early_warn(format!("failed to create profiler: {e}")); None } } @@ -1723,7 +1723,64 @@ pub enum IncrCompSession { InvalidBecauseOfErrors { session_directory: PathBuf }, } -fn early_error_handler(output: config::ErrorOutputType) -> rustc_errors::Handler { +/// A wrapper around an [`Handler`] that is used for early error emissions. +pub struct EarlyErrorHandler { + handler: Handler, +} + +impl EarlyErrorHandler { + pub fn new(output: ErrorOutputType) -> Self { + let emitter = mk_emitter(output); + Self { handler: rustc_errors::Handler::with_emitter(true, None, emitter) } + } + + pub fn abort_if_errors(&self) { + self.handler.abort_if_errors() + } + + /// Swap out the underlying handler once we acquire the user's preference on error emission + /// format. Any errors prior to that will cause an abort and all stashed diagnostics of the + /// previous handler will be emitted. + pub fn abort_if_error_and_set_error_format(&mut self, output: ErrorOutputType) { + self.handler.abort_if_errors(); + + let emitter = mk_emitter(output); + self.handler = Handler::with_emitter(true, None, emitter); + } + + #[allow(rustc::untranslatable_diagnostic)] + #[allow(rustc::diagnostic_outside_of_impl)] + pub fn early_note(&self, msg: impl Into) { + self.handler.struct_note_without_error(msg).emit() + } + + #[allow(rustc::untranslatable_diagnostic)] + #[allow(rustc::diagnostic_outside_of_impl)] + pub fn early_help(&self, msg: impl Into) { + self.handler.struct_help(msg).emit() + } + + #[allow(rustc::untranslatable_diagnostic)] + #[allow(rustc::diagnostic_outside_of_impl)] + #[must_use = "ErrorGuaranteed must be returned from `run_compiler` in order to exit with a non-zero status code"] + pub fn early_error_no_abort(&self, msg: impl Into) -> ErrorGuaranteed { + self.handler.struct_err(msg).emit() + } + + #[allow(rustc::untranslatable_diagnostic)] + #[allow(rustc::diagnostic_outside_of_impl)] + pub fn early_error(&self, msg: impl Into) -> ! { + self.handler.struct_fatal(msg).emit() + } + + #[allow(rustc::untranslatable_diagnostic)] + #[allow(rustc::diagnostic_outside_of_impl)] + pub fn early_warn(&self, msg: impl Into) { + self.handler.struct_warn(msg).emit() + } +} + +fn mk_emitter(output: ErrorOutputType) -> Box { // FIXME(#100717): early errors aren't translated at the moment, so this is fine, but it will // need to reference every crate that might emit an early error for translation to work. let fallback_bundle = @@ -1755,27 +1812,5 @@ fn early_error_handler(output: config::ErrorOutputType) -> rustc_errors::Handler TerminalUrl::No, )), }; - rustc_errors::Handler::with_emitter(true, None, emitter) -} - -#[allow(rustc::untranslatable_diagnostic)] -#[allow(rustc::diagnostic_outside_of_impl)] -#[must_use = "ErrorGuaranteed must be returned from `run_compiler` in order to exit with a non-zero status code"] -pub fn early_error_no_abort( - output: config::ErrorOutputType, - msg: impl Into, -) -> ErrorGuaranteed { - early_error_handler(output).struct_err(msg).emit() -} - -#[allow(rustc::untranslatable_diagnostic)] -#[allow(rustc::diagnostic_outside_of_impl)] -pub fn early_error(output: config::ErrorOutputType, msg: impl Into) -> ! { - early_error_handler(output).struct_fatal(msg).emit() -} - -#[allow(rustc::untranslatable_diagnostic)] -#[allow(rustc::diagnostic_outside_of_impl)] -pub fn early_warn(output: config::ErrorOutputType, msg: impl Into) { - early_error_handler(output).struct_warn(msg).emit() + emitter } diff --git a/compiler/rustc_target/src/spec/aarch64_be_unknown_netbsd.rs b/compiler/rustc_target/src/spec/aarch64_be_unknown_netbsd.rs new file mode 100644 index 000000000000..98ae05974aa8 --- /dev/null +++ b/compiler/rustc_target/src/spec/aarch64_be_unknown_netbsd.rs @@ -0,0 +1,17 @@ +use crate::abi::Endian; +use crate::spec::{Target, TargetOptions}; + +pub fn target() -> Target { + Target { + llvm_target: "aarch64_be-unknown-netbsd".into(), + pointer_width: 64, + data_layout: "E-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128".into(), + arch: "aarch64".into(), + options: TargetOptions { + mcount: "__mcount".into(), + max_atomic_width: Some(128), + endian: Endian::Big, + ..super::netbsd_base::opts() + }, + } +} diff --git a/compiler/rustc_target/src/spec/mod.rs b/compiler/rustc_target/src/spec/mod.rs index c15a330ee746..88fbe2a8be1b 100644 --- a/compiler/rustc_target/src/spec/mod.rs +++ b/compiler/rustc_target/src/spec/mod.rs @@ -1194,6 +1194,7 @@ supported_targets! { ("x86_64-unknown-openbsd", x86_64_unknown_openbsd), ("aarch64-unknown-netbsd", aarch64_unknown_netbsd), + ("aarch64_be-unknown-netbsd", aarch64_be_unknown_netbsd), ("armv6-unknown-netbsd-eabihf", armv6_unknown_netbsd_eabihf), ("armv7-unknown-netbsd-eabihf", armv7_unknown_netbsd_eabihf), ("i686-unknown-netbsd", i686_unknown_netbsd), diff --git a/compiler/rustc_trait_selection/src/solve/assembly/mod.rs b/compiler/rustc_trait_selection/src/solve/assembly/mod.rs index cde8a52cdec9..9e8dbd0cde21 100644 --- a/compiler/rustc_trait_selection/src/solve/assembly/mod.rs +++ b/compiler/rustc_trait_selection/src/solve/assembly/mod.rs @@ -469,13 +469,11 @@ impl<'tcx> EvalCtxt<'_, 'tcx> { candidates: &mut Vec>, ) { for (i, assumption) in goal.param_env.caller_bounds().iter().enumerate() { - if let Some(clause) = assumption.as_clause() { - match G::consider_implied_clause(self, goal, clause, []) { - Ok(result) => { - candidates.push(Candidate { source: CandidateSource::ParamEnv(i), result }) - } - Err(NoSolution) => (), + match G::consider_implied_clause(self, goal, assumption, []) { + Ok(result) => { + candidates.push(Candidate { source: CandidateSource::ParamEnv(i), result }) } + Err(NoSolution) => (), } } } @@ -685,19 +683,15 @@ impl<'tcx> EvalCtxt<'_, 'tcx> { // since that'll cause ambiguity. // // We can remove this when we have implemented lifetime intersections in responses. - if assumption.to_opt_poly_projection_pred().is_some() - && !own_bounds.contains(&assumption) - { + if assumption.as_projection_clause().is_some() && !own_bounds.contains(&assumption) { continue; } - if let Some(clause) = assumption.as_clause() { - match G::consider_object_bound_candidate(self, goal, clause) { - Ok(result) => { - candidates.push(Candidate { source: CandidateSource::BuiltinImpl, result }) - } - Err(NoSolution) => (), + match G::consider_object_bound_candidate(self, goal, assumption) { + Ok(result) => { + candidates.push(Candidate { source: CandidateSource::BuiltinImpl, result }) } + Err(NoSolution) => (), } } } diff --git a/compiler/rustc_trait_selection/src/solve/assembly/structural_traits.rs b/compiler/rustc_trait_selection/src/solve/assembly/structural_traits.rs index 439cf788ab4f..9eac53c39839 100644 --- a/compiler/rustc_trait_selection/src/solve/assembly/structural_traits.rs +++ b/compiler/rustc_trait_selection/src/solve/assembly/structural_traits.rs @@ -343,7 +343,7 @@ pub(in crate::solve) fn predicates_for_object_candidate<'tcx>( param_env: ty::ParamEnv<'tcx>, trait_ref: ty::TraitRef<'tcx>, object_bound: &'tcx ty::List>, -) -> Vec> { +) -> Vec> { let tcx = ecx.tcx(); let mut requirements = vec![]; requirements.extend( @@ -353,11 +353,7 @@ pub(in crate::solve) fn predicates_for_object_candidate<'tcx>( // FIXME(associated_const_equality): Also add associated consts to // the requirements here. if item.kind == ty::AssocKind::Type { - requirements.extend( - tcx.item_bounds(item.def_id) - .subst_iter(tcx, trait_ref.substs) - .map(|clause| clause.as_predicate()), - ); + requirements.extend(tcx.item_bounds(item.def_id).subst_iter(tcx, trait_ref.substs)); } } diff --git a/compiler/rustc_trait_selection/src/solve/eval_ctxt.rs b/compiler/rustc_trait_selection/src/solve/eval_ctxt.rs index b42bbf91e905..6aca40b8dbd9 100644 --- a/compiler/rustc_trait_selection/src/solve/eval_ctxt.rs +++ b/compiler/rustc_trait_selection/src/solve/eval_ctxt.rs @@ -395,7 +395,7 @@ impl<'a, 'tcx> EvalCtxt<'a, 'tcx> { ty::PredicateKind::ConstEquate(_, _) => { bug!("ConstEquate should not be emitted when `-Ztrait-solver=next` is active") } - ty::PredicateKind::TypeWellFormedFromEnv(..) => { + ty::PredicateKind::Clause(ty::ClauseKind::TypeWellFormedFromEnv(..)) => { bug!("TypeWellFormedFromEnv is only used for Chalk") } ty::PredicateKind::AliasRelate(lhs, rhs, direction) => self diff --git a/compiler/rustc_trait_selection/src/solve/fulfill.rs b/compiler/rustc_trait_selection/src/solve/fulfill.rs index f8f1239d5b40..5c62ea64f993 100644 --- a/compiler/rustc_trait_selection/src/solve/fulfill.rs +++ b/compiler/rustc_trait_selection/src/solve/fulfill.rs @@ -132,8 +132,7 @@ impl<'tcx> TraitEngine<'tcx> for FulfillmentCtxt<'tcx> { SelectionError::Unimplemented, ) } - ty::PredicateKind::ConstEquate(..) - | ty::PredicateKind::TypeWellFormedFromEnv(_) => { + ty::PredicateKind::ConstEquate(..) => { bug!("unexpected goal: {goal:?}") } }, diff --git a/compiler/rustc_trait_selection/src/traits/auto_trait.rs b/compiler/rustc_trait_selection/src/traits/auto_trait.rs index 71557e8930df..fb6bf7211b92 100644 --- a/compiler/rustc_trait_selection/src/traits/auto_trait.rs +++ b/compiler/rustc_trait_selection/src/traits/auto_trait.rs @@ -255,7 +255,7 @@ impl<'tcx> AutoTraitFinder<'tcx> { // that are already in the `ParamEnv` (modulo regions): we already // know that they must hold. for predicate in param_env.caller_bounds() { - fresh_preds.insert(self.clean_pred(infcx, predicate)); + fresh_preds.insert(self.clean_pred(infcx, predicate.as_predicate())); } let mut select = SelectionContext::new(&infcx); @@ -270,8 +270,9 @@ impl<'tcx> AutoTraitFinder<'tcx> { polarity: ty::ImplPolarity::Positive, })); - let computed_preds = param_env.caller_bounds().iter(); - let mut user_computed_preds: FxIndexSet<_> = user_env.caller_bounds().iter().collect(); + let computed_preds = param_env.caller_bounds().iter().map(|c| c.as_predicate()); + let mut user_computed_preds: FxIndexSet<_> = + user_env.caller_bounds().iter().map(|c| c.as_predicate()).collect(); let mut new_env = param_env; let dummy_cause = ObligationCause::dummy(); @@ -349,14 +350,14 @@ impl<'tcx> AutoTraitFinder<'tcx> { let normalized_preds = elaborate(tcx, computed_preds.clone().chain(user_computed_preds.iter().cloned())); new_env = ty::ParamEnv::new( - tcx.mk_predicates_from_iter(normalized_preds), + tcx.mk_clauses_from_iter(normalized_preds.filter_map(|p| p.as_clause())), param_env.reveal(), param_env.constness(), ); } let final_user_env = ty::ParamEnv::new( - tcx.mk_predicates_from_iter(user_computed_preds.into_iter()), + tcx.mk_clauses_from_iter(user_computed_preds.into_iter().filter_map(|p| p.as_clause())), user_env.reveal(), user_env.constness(), ); @@ -835,7 +836,7 @@ impl<'tcx> AutoTraitFinder<'tcx> { // FIXME(generic_const_exprs): you can absolutely add this as a where clauses | ty::PredicateKind::Clause(ty::ClauseKind::ConstEvaluatable(..)) | ty::PredicateKind::Coerce(..) => {} - ty::PredicateKind::TypeWellFormedFromEnv(..) => { + ty::PredicateKind::Clause(ty::ClauseKind::TypeWellFormedFromEnv(..)) => { bug!("predicate should only exist in the environment: {bound_predicate:?}") } ty::PredicateKind::Ambiguous => return false, diff --git a/compiler/rustc_trait_selection/src/traits/coherence.rs b/compiler/rustc_trait_selection/src/traits/coherence.rs index 0065c7fc253b..9e1332c1c81d 100644 --- a/compiler/rustc_trait_selection/src/traits/coherence.rs +++ b/compiler/rustc_trait_selection/src/traits/coherence.rs @@ -148,7 +148,12 @@ fn with_fresh_ty_vars<'cx, 'tcx>( impl_def_id, self_ty: tcx.type_of(impl_def_id).subst(tcx, impl_substs), trait_ref: tcx.impl_trait_ref(impl_def_id).map(|i| i.subst(tcx, impl_substs)), - predicates: tcx.predicates_of(impl_def_id).instantiate(tcx, impl_substs).predicates, + predicates: tcx + .predicates_of(impl_def_id) + .instantiate(tcx, impl_substs) + .iter() + .map(|(c, _)| c.as_predicate()) + .collect(), }; let InferOk { value: mut header, obligations } = diff --git a/compiler/rustc_trait_selection/src/traits/const_evaluatable.rs b/compiler/rustc_trait_selection/src/traits/const_evaluatable.rs index f9f242d29f65..ab4727b86972 100644 --- a/compiler/rustc_trait_selection/src/traits/const_evaluatable.rs +++ b/compiler/rustc_trait_selection/src/traits/const_evaluatable.rs @@ -207,7 +207,7 @@ fn satisfied_from_param_env<'tcx>( for pred in param_env.caller_bounds() { match pred.kind().skip_binder() { - ty::PredicateKind::Clause(ty::ClauseKind::ConstEvaluatable(ce)) => { + ty::ClauseKind::ConstEvaluatable(ce) => { let b_ct = tcx.expand_abstract_consts(ce); let mut v = Visitor { ct, infcx, param_env, single_match }; let _ = b_ct.visit_with(&mut v); diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/ambiguity.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/ambiguity.rs index 1351d9bb257e..96c183f9a581 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/ambiguity.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/ambiguity.rs @@ -84,7 +84,7 @@ pub fn recompute_applicable_impls<'tcx>( tcx.predicates_of(obligation.cause.body_id.to_def_id()).instantiate_identity(tcx); for (pred, span) in elaborate(tcx, predicates.into_iter()) { let kind = pred.kind(); - if let ty::PredicateKind::Clause(ty::ClauseKind::Trait(trait_pred)) = kind.skip_binder() + if let ty::ClauseKind::Trait(trait_pred) = kind.skip_binder() && param_env_candidate_may_apply(kind.rebind(trait_pred)) { if kind.rebind(trait_pred.trait_ref) == ty::Binder::dummy(ty::TraitRef::identity(tcx, trait_pred.def_id())) { 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 557341f7ac88..f93d6b1ce88e 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs @@ -1094,10 +1094,12 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> { ty::PredicateKind::Ambiguous => span_bug!(span, "ambiguous"), - ty::PredicateKind::TypeWellFormedFromEnv(..) => span_bug!( - span, - "TypeWellFormedFromEnv predicate should only exist in the environment" - ), + ty::PredicateKind::Clause(ty::ClauseKind::TypeWellFormedFromEnv(..)) => { + span_bug!( + span, + "TypeWellFormedFromEnv predicate should only exist in the environment" + ) + } ty::PredicateKind::AliasRelate(..) => span_bug!( span, 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 71d2380f2347..43b63762ba32 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs @@ -1201,7 +1201,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> { DefIdOrName::Name("type parameter") }; param_env.caller_bounds().iter().find_map(|pred| { - if let ty::PredicateKind::Clause(ty::ClauseKind::Projection(proj)) = pred.kind().skip_binder() + if let ty::ClauseKind::Projection(proj) = pred.kind().skip_binder() && Some(proj.projection_ty.def_id) == self.tcx.lang_items().fn_once_output() && proj.projection_ty.self_ty() == found // args tuple will always be substs[1] @@ -2001,7 +2001,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> { if let ObligationCauseCode::ExprBindingObligation(def_id, _, _, idx) = cause && let predicates = self.tcx.predicates_of(def_id).instantiate_identity(self.tcx) && let Some(pred) = predicates.predicates.get(*idx) - && let ty::PredicateKind::Clause(ty::ClauseKind::Trait(trait_pred)) = pred.kind().skip_binder() + && let ty::ClauseKind::Trait(trait_pred) = pred.kind().skip_binder() && self.tcx.is_fn_trait(trait_pred.def_id()) { let expected_self = @@ -2015,7 +2015,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> { let other_pred = predicates.into_iter() .enumerate() .find(|(other_idx, (pred, _))| match pred.kind().skip_binder() { - ty::PredicateKind::Clause(ty::ClauseKind::Trait(trait_pred)) + ty::ClauseKind::Trait(trait_pred) if self.tcx.is_fn_trait(trait_pred.def_id()) && other_idx != idx // Make sure that the self type matches @@ -3526,7 +3526,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> { && let where_clauses = self.tcx.predicates_of(def_id).instantiate(self.tcx, node_substs) && let Some(where_pred) = where_clauses.predicates.get(*idx) { - if let Some(where_pred) = where_pred.to_opt_poly_trait_pred() + if let Some(where_pred) = where_pred.as_trait_clause() && let Some(failed_pred) = failed_pred.to_opt_poly_trait_pred() { let where_pred = self.instantiate_binder_with_placeholders(where_pred); @@ -3549,7 +3549,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> { } }) }; - } else if let Some(where_pred) = where_pred.to_opt_poly_projection_pred() + } else if let Some(where_pred) = where_pred.as_projection_clause() && let Some(failed_pred) = failed_pred.to_opt_poly_projection_pred() && let Some(found) = failed_pred.skip_binder().term.ty() { diff --git a/compiler/rustc_trait_selection/src/traits/fulfill.rs b/compiler/rustc_trait_selection/src/traits/fulfill.rs index 7c5260fc67bf..f2f99eb60e4d 100644 --- a/compiler/rustc_trait_selection/src/traits/fulfill.rs +++ b/compiler/rustc_trait_selection/src/traits/fulfill.rs @@ -366,7 +366,7 @@ impl<'a, 'tcx> ObligationProcessor for FulfillProcessor<'a, 'tcx> { ProcessResult::Changed(mk_pending(vec![obligation.with(infcx.tcx, pred)])) } ty::PredicateKind::Ambiguous => ProcessResult::Unchanged, - ty::PredicateKind::TypeWellFormedFromEnv(..) => { + ty::PredicateKind::Clause(ty::ClauseKind::TypeWellFormedFromEnv(..)) => { bug!("TypeWellFormedFromEnv is only used for Chalk") } ty::PredicateKind::AliasRelate(..) => { @@ -634,7 +634,7 @@ impl<'a, 'tcx> ObligationProcessor for FulfillProcessor<'a, 'tcx> { } } ty::PredicateKind::Ambiguous => ProcessResult::Unchanged, - ty::PredicateKind::TypeWellFormedFromEnv(..) => { + ty::PredicateKind::Clause(ty::ClauseKind::TypeWellFormedFromEnv(..)) => { bug!("TypeWellFormedFromEnv is only used for Chalk") } ty::PredicateKind::AliasRelate(..) => { diff --git a/compiler/rustc_trait_selection/src/traits/mod.rs b/compiler/rustc_trait_selection/src/traits/mod.rs index a5481714e3e5..ae76651c336a 100644 --- a/compiler/rustc_trait_selection/src/traits/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/mod.rs @@ -114,11 +114,11 @@ pub fn predicates_for_generics<'tcx>( param_env: ty::ParamEnv<'tcx>, generic_bounds: ty::InstantiatedPredicates<'tcx>, ) -> impl Iterator> { - generic_bounds.into_iter().enumerate().map(move |(idx, (predicate, span))| Obligation { + generic_bounds.into_iter().enumerate().map(move |(idx, (clause, span))| Obligation { cause: cause(idx, span), recursion_depth: 0, param_env, - predicate, + predicate: clause.as_predicate(), }) } @@ -185,8 +185,8 @@ fn do_normalize_predicates<'tcx>( tcx: TyCtxt<'tcx>, cause: ObligationCause<'tcx>, elaborated_env: ty::ParamEnv<'tcx>, - predicates: Vec>, -) -> Result>, ErrorGuaranteed> { + predicates: Vec>, +) -> Result>, ErrorGuaranteed> { let span = cause.span; // FIXME. We should really... do something with these region // obligations. But this call just continues the older @@ -330,7 +330,7 @@ pub fn normalize_param_env_or_error<'tcx>( debug!("normalize_param_env_or_error: elaborated-predicates={:?}", predicates); let elaborated_env = ty::ParamEnv::new( - tcx.mk_predicates(&predicates), + tcx.mk_clauses(&predicates), unnormalized_env.reveal(), unnormalized_env.constness(), ); @@ -355,10 +355,7 @@ pub fn normalize_param_env_or_error<'tcx>( // TypeOutlives predicates - these are normally used by regionck. let outlives_predicates: Vec<_> = predicates .extract_if(|predicate| { - matches!( - predicate.kind().skip_binder(), - ty::PredicateKind::Clause(ty::ClauseKind::TypeOutlives(..)) - ) + matches!(predicate.kind().skip_binder(), ty::ClauseKind::TypeOutlives(..)) }) .collect(); @@ -384,7 +381,7 @@ pub fn normalize_param_env_or_error<'tcx>( // predicates here anyway. Keeping them here anyway because it seems safer. let outlives_env = non_outlives_predicates.iter().chain(&outlives_predicates).cloned(); let outlives_env = ty::ParamEnv::new( - tcx.mk_predicates_from_iter(outlives_env), + tcx.mk_clauses_from_iter(outlives_env), unnormalized_env.reveal(), unnormalized_env.constness(), ); @@ -404,7 +401,7 @@ pub fn normalize_param_env_or_error<'tcx>( predicates.extend(outlives_predicates); debug!("normalize_param_env_or_error: final predicates={:?}", predicates); ty::ParamEnv::new( - tcx.mk_predicates(&predicates), + tcx.mk_clauses(&predicates), unnormalized_env.reveal(), unnormalized_env.constness(), ) @@ -439,10 +436,7 @@ where /// Normalizes the predicates and checks whether they hold in an empty environment. If this /// returns true, then either normalize encountered an error or one of the predicates did not /// hold. Used when creating vtables to check for unsatisfiable methods. -pub fn impossible_predicates<'tcx>( - tcx: TyCtxt<'tcx>, - predicates: Vec>, -) -> bool { +pub fn impossible_predicates<'tcx>(tcx: TyCtxt<'tcx>, predicates: Vec>) -> bool { debug!("impossible_predicates(predicates={:?})", predicates); let infcx = tcx.infer_ctxt().build(); diff --git a/compiler/rustc_trait_selection/src/traits/object_safety.rs b/compiler/rustc_trait_selection/src/traits/object_safety.rs index df93c4d45dc8..78270b7d535d 100644 --- a/compiler/rustc_trait_selection/src/traits/object_safety.rs +++ b/compiler/rustc_trait_selection/src/traits/object_safety.rs @@ -271,22 +271,22 @@ fn bounds_reference_self(tcx: TyCtxt<'_>, trait_def_id: DefId) -> SmallVec<[Span .in_definition_order() .filter(|item| item.kind == ty::AssocKind::Type) .flat_map(|item| tcx.explicit_item_bounds(item.def_id).subst_identity_iter_copied()) - .filter_map(|(clause, span)| predicate_references_self(tcx, (clause.as_predicate(), span))) + .filter_map(|c| predicate_references_self(tcx, c)) .collect() } fn predicate_references_self<'tcx>( tcx: TyCtxt<'tcx>, - (predicate, sp): (ty::Predicate<'tcx>, Span), + (predicate, sp): (ty::Clause<'tcx>, Span), ) -> Option { let self_ty = tcx.types.self_param; let has_self_ty = |arg: &GenericArg<'tcx>| arg.walk().any(|arg| arg == self_ty.into()); match predicate.kind().skip_binder() { - ty::PredicateKind::Clause(ty::ClauseKind::Trait(ref data)) => { + ty::ClauseKind::Trait(ref data) => { // In the case of a trait predicate, we can skip the "self" type. data.trait_ref.substs[1..].iter().any(has_self_ty).then_some(sp) } - ty::PredicateKind::Clause(ty::ClauseKind::Projection(ref data)) => { + ty::ClauseKind::Projection(ref data) => { // And similarly for projections. This should be redundant with // the previous check because any projection should have a // matching `Trait` predicate with the same inputs, but we do @@ -304,24 +304,14 @@ fn predicate_references_self<'tcx>( // possible alternatives. data.projection_ty.substs[1..].iter().any(has_self_ty).then_some(sp) } - ty::PredicateKind::Clause(ty::ClauseKind::ConstArgHasType(_ct, ty)) => { - has_self_ty(&ty.into()).then_some(sp) - } + ty::ClauseKind::ConstArgHasType(_ct, ty) => has_self_ty(&ty.into()).then_some(sp), - ty::PredicateKind::AliasRelate(..) => bug!("`AliasRelate` not allowed as assumption"), - - ty::PredicateKind::Clause(ty::ClauseKind::WellFormed(..)) - | ty::PredicateKind::ObjectSafe(..) - | ty::PredicateKind::Clause(ty::ClauseKind::TypeOutlives(..)) - | ty::PredicateKind::Clause(ty::ClauseKind::RegionOutlives(..)) - | ty::PredicateKind::ClosureKind(..) - | ty::PredicateKind::Subtype(..) - | ty::PredicateKind::Coerce(..) + ty::ClauseKind::WellFormed(..) + | ty::ClauseKind::TypeOutlives(..) + | ty::ClauseKind::RegionOutlives(..) // FIXME(generic_const_exprs): this can mention `Self` - | ty::PredicateKind::Clause(ty::ClauseKind::ConstEvaluatable(..)) - | ty::PredicateKind::ConstEquate(..) - | ty::PredicateKind::Ambiguous - | ty::PredicateKind::TypeWellFormedFromEnv(..) => None, + | ty::ClauseKind::ConstEvaluatable(..) + | ty::ClauseKind::TypeWellFormedFromEnv(_) => None, } } @@ -353,23 +343,16 @@ fn generics_require_sized_self(tcx: TyCtxt<'_>, def_id: DefId) -> bool { let predicates = tcx.predicates_of(def_id); let predicates = predicates.instantiate_identity(tcx).predicates; elaborate(tcx, predicates.into_iter()).any(|pred| match pred.kind().skip_binder() { - ty::PredicateKind::Clause(ty::ClauseKind::Trait(ref trait_pred)) => { + ty::ClauseKind::Trait(ref trait_pred) => { trait_pred.def_id() == sized_def_id && trait_pred.self_ty().is_param(0) } - ty::PredicateKind::Clause(ty::ClauseKind::Projection(..)) - | ty::PredicateKind::Clause(ty::ClauseKind::ConstArgHasType(..)) - | ty::PredicateKind::Subtype(..) - | ty::PredicateKind::Coerce(..) - | ty::PredicateKind::Clause(ty::ClauseKind::RegionOutlives(..)) - | ty::PredicateKind::Clause(ty::ClauseKind::WellFormed(..)) - | ty::PredicateKind::ObjectSafe(..) - | ty::PredicateKind::ClosureKind(..) - | ty::PredicateKind::Clause(ty::ClauseKind::TypeOutlives(..)) - | ty::PredicateKind::Clause(ty::ClauseKind::ConstEvaluatable(..)) - | ty::PredicateKind::ConstEquate(..) - | ty::PredicateKind::AliasRelate(..) - | ty::PredicateKind::Ambiguous - | ty::PredicateKind::TypeWellFormedFromEnv(..) => false, + ty::ClauseKind::RegionOutlives(_) + | ty::ClauseKind::TypeOutlives(_) + | ty::ClauseKind::Projection(_) + | ty::ClauseKind::ConstArgHasType(_, _) + | ty::ClauseKind::WellFormed(_) + | ty::ClauseKind::ConstEvaluatable(_) + | ty::ClauseKind::TypeWellFormedFromEnv(_) => false, }) } @@ -575,7 +558,7 @@ fn virtual_call_violation_for_method<'tcx>( // because a trait object can't claim to live longer than the concrete // type. If the lifetime bound holds on dyn Trait then it's guaranteed // to hold as well on the concrete type. - if pred.to_opt_type_outlives().is_some() { + if pred.as_type_outlives_clause().is_some() { return false; } @@ -592,11 +575,11 @@ fn virtual_call_violation_for_method<'tcx>( // only if the autotrait is one of the trait object's trait bounds, like // in `dyn Trait + AutoTrait`. This guarantees that trait objects only // implement auto traits if the underlying type does as well. - if let ty::PredicateKind::Clause(ty::ClauseKind::Trait(ty::TraitPredicate { + if let ty::ClauseKind::Trait(ty::TraitPredicate { trait_ref: pred_trait_ref, constness: ty::BoundConstness::NotConst, polarity: ty::ImplPolarity::Positive, - })) = pred.kind().skip_binder() + }) = pred.kind().skip_binder() && pred_trait_ref.self_ty() == tcx.types.self_param && tcx.trait_is_auto(pred_trait_ref.def_id) { @@ -764,7 +747,6 @@ fn receiver_is_dispatchable<'tcx>( // Self: Unsize let unsize_predicate = ty::TraitRef::new(tcx, unsize_did, [tcx.types.self_param, unsized_self_ty]) - .without_const() .to_predicate(tcx); // U: Trait @@ -781,7 +763,7 @@ fn receiver_is_dispatchable<'tcx>( param_env.caller_bounds().iter().chain([unsize_predicate, trait_predicate]); ty::ParamEnv::new( - tcx.mk_predicates_from_iter(caller_bounds), + tcx.mk_clauses_from_iter(caller_bounds), param_env.reveal(), param_env.constness(), ) diff --git a/compiler/rustc_trait_selection/src/traits/project.rs b/compiler/rustc_trait_selection/src/traits/project.rs index 2a78c5befa4d..c84c75cecdfe 100644 --- a/compiler/rustc_trait_selection/src/traits/project.rs +++ b/compiler/rustc_trait_selection/src/traits/project.rs @@ -1585,7 +1585,7 @@ fn assemble_candidates_from_trait_def<'cx, 'tcx>( obligation, candidate_set, ProjectionCandidate::TraitDef, - bounds.iter().map(|clause| clause.as_predicate()), + bounds.iter(), true, ); } @@ -1648,15 +1648,13 @@ fn assemble_candidates_from_predicates<'cx, 'tcx>( obligation: &ProjectionTyObligation<'tcx>, candidate_set: &mut ProjectionCandidateSet<'tcx>, ctor: fn(ty::PolyProjectionPredicate<'tcx>) -> ProjectionCandidate<'tcx>, - env_predicates: impl Iterator>, + env_predicates: impl Iterator>, potentially_unnormalized_candidates: bool, ) { let infcx = selcx.infcx; for predicate in env_predicates { let bound_predicate = predicate.kind(); - if let ty::PredicateKind::Clause(ty::ClauseKind::Projection(data)) = - predicate.kind().skip_binder() - { + if let ty::ClauseKind::Projection(data) = predicate.kind().skip_binder() { let data = bound_predicate.rebind(data); if data.projection_def_id() != obligation.predicate.def_id { continue; diff --git a/compiler/rustc_trait_selection/src/traits/query/type_op/implied_outlives_bounds.rs b/compiler/rustc_trait_selection/src/traits/query/type_op/implied_outlives_bounds.rs index 7d0dc740cf57..83d536c9ca56 100644 --- a/compiler/rustc_trait_selection/src/traits/query/type_op/implied_outlives_bounds.rs +++ b/compiler/rustc_trait_selection/src/traits/query/type_op/implied_outlives_bounds.rs @@ -134,7 +134,7 @@ pub fn compute_implied_outlives_bounds_inner<'tcx>( | ty::PredicateKind::ConstEquate(..) | ty::PredicateKind::Ambiguous | ty::PredicateKind::AliasRelate(..) - | ty::PredicateKind::TypeWellFormedFromEnv(..) => {} + | ty::PredicateKind::Clause(ty::ClauseKind::TypeWellFormedFromEnv(..)) => {} // We need to search through *all* WellFormed predicates ty::PredicateKind::Clause(ty::ClauseKind::WellFormed(arg)) => { diff --git a/compiler/rustc_trait_selection/src/traits/query/type_op/normalize.rs b/compiler/rustc_trait_selection/src/traits/query/type_op/normalize.rs index 57ca14aa492f..9559f5002f63 100644 --- a/compiler/rustc_trait_selection/src/traits/query/type_op/normalize.rs +++ b/compiler/rustc_trait_selection/src/traits/query/type_op/normalize.rs @@ -50,12 +50,12 @@ impl<'tcx> Normalizable<'tcx> for Ty<'tcx> { } } -impl<'tcx> Normalizable<'tcx> for ty::Predicate<'tcx> { +impl<'tcx> Normalizable<'tcx> for ty::Clause<'tcx> { fn type_op_method( tcx: TyCtxt<'tcx>, canonicalized: Canonical<'tcx, ParamEnvAnd<'tcx, Normalize>>, ) -> Result, NoSolution> { - tcx.type_op_normalize_predicate(canonicalized) + tcx.type_op_normalize_clause(canonicalized) } } diff --git a/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs b/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs index 8eef7d5d63fd..412b601c966f 100644 --- a/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs +++ b/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs @@ -181,7 +181,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { .caller_bounds() .iter() .filter(|p| !p.references_error()) - .filter_map(|p| p.to_opt_poly_trait_pred()); + .filter_map(|p| p.as_trait_clause()); // Micro-optimization: filter out predicates relating to different traits. let matching_bounds = @@ -402,7 +402,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { }; for &(predicate, _) in self.tcx().predicates_of(impl_def_id).predicates { - let ty::PredicateKind::Clause(ty::ClauseKind::Trait(pred)) + let ty::ClauseKind::Trait(pred) = predicate.kind().skip_binder() else { continue }; if fn_ptr_trait != pred.trait_ref.def_id { continue; diff --git a/compiler/rustc_trait_selection/src/traits/select/confirmation.rs b/compiler/rustc_trait_selection/src/traits/select/confirmation.rs index a50af417a443..c94fddc124ff 100644 --- a/compiler/rustc_trait_selection/src/traits/select/confirmation.rs +++ b/compiler/rustc_trait_selection/src/traits/select/confirmation.rs @@ -1108,12 +1108,14 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { obligation.cause.span, [source], ); - nested.push(predicate_to_obligation(tr.without_const().to_predicate(tcx))); + nested.push(predicate_to_obligation(tr.to_predicate(tcx))); // If the type is `Foo + 'a`, ensure that the type // being cast to `Foo + 'a` outlives `'a`: let outlives = ty::OutlivesPredicate(source, r); - nested.push(predicate_to_obligation(ty::Binder::dummy(outlives).to_predicate(tcx))); + nested.push(predicate_to_obligation( + ty::Binder::dummy(ty::ClauseKind::TypeOutlives(outlives)).to_predicate(tcx), + )); } // `[T; n]` -> `[T]` diff --git a/compiler/rustc_trait_selection/src/traits/select/mod.rs b/compiler/rustc_trait_selection/src/traits/select/mod.rs index 0a8b7b688e7f..7406b47e3273 100644 --- a/compiler/rustc_trait_selection/src/traits/select/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/select/mod.rs @@ -967,7 +967,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { } } } - ty::PredicateKind::TypeWellFormedFromEnv(..) => { + ty::PredicateKind::Clause(ty::ClauseKind::TypeWellFormedFromEnv(..)) => { bug!("TypeWellFormedFromEnv is only used for chalk") } ty::PredicateKind::AliasRelate(..) => { @@ -2657,7 +2657,7 @@ impl<'tcx> SelectionContext<'_, 'tcx> { })) }) }; - let predicate = normalize_with_depth_to( + let clause = normalize_with_depth_to( self, param_env, cause.clone(), @@ -2665,7 +2665,12 @@ impl<'tcx> SelectionContext<'_, 'tcx> { predicate, &mut obligations, ); - obligations.push(Obligation { cause, recursion_depth, param_env, predicate }); + obligations.push(Obligation { + cause, + recursion_depth, + param_env, + predicate: clause.as_predicate(), + }); } obligations diff --git a/compiler/rustc_trait_selection/src/traits/specialize/mod.rs b/compiler/rustc_trait_selection/src/traits/specialize/mod.rs index 68ba8ceaa43c..fee38aed0e2f 100644 --- a/compiler/rustc_trait_selection/src/traits/specialize/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/specialize/mod.rs @@ -508,22 +508,14 @@ pub(crate) fn to_pretty_impl_header(tcx: TyCtxt<'_>, impl_def_id: DefId) -> Opti Vec::with_capacity(predicates.len() + types_without_default_bounds.len()); for (mut p, _) in predicates { - if let Some(poly_trait_ref) = p.to_opt_poly_trait_pred() { + if let Some(poly_trait_ref) = p.as_trait_clause() { if Some(poly_trait_ref.def_id()) == sized_trait { types_without_default_bounds.remove(&poly_trait_ref.self_ty().skip_binder()); continue; } if ty::BoundConstness::ConstIfConst == poly_trait_ref.skip_binder().constness { - let new_trait_pred = poly_trait_ref.map_bound(|mut trait_pred| { - trait_pred.constness = ty::BoundConstness::NotConst; - trait_pred - }); - - p = tcx.mk_predicate( - new_trait_pred - .map_bound(|p| ty::PredicateKind::Clause(ty::ClauseKind::Trait(p))), - ) + p = p.without_const(tcx); } } pretty_predicates.push(p.to_string()); diff --git a/compiler/rustc_trait_selection/src/traits/util.rs b/compiler/rustc_trait_selection/src/traits/util.rs index 05a7f3e3b024..72adf3106ab1 100644 --- a/compiler/rustc_trait_selection/src/traits/util.rs +++ b/compiler/rustc_trait_selection/src/traits/util.rs @@ -125,7 +125,7 @@ impl<'tcx> TraitAliasExpander<'tcx> { let items = predicates.predicates.iter().rev().filter_map(|(pred, span)| { pred.subst_supertrait(tcx, &trait_ref) - .to_opt_poly_trait_pred() + .as_trait_clause() .map(|trait_ref| item.clone_and_push(trait_ref.map_bound(|t| t.trait_ref), *span)) }); debug!("expand_trait_aliases: items={:?}", items.clone().collect::>()); @@ -182,7 +182,7 @@ impl Iterator for SupertraitDefIds<'_> { predicates .predicates .iter() - .filter_map(|(pred, _)| pred.to_opt_poly_trait_pred()) + .filter_map(|(pred, _)| pred.as_trait_clause()) .map(|trait_ref| trait_ref.def_id()) .filter(|&super_def_id| visited.insert(super_def_id)), ); diff --git a/compiler/rustc_trait_selection/src/traits/vtable.rs b/compiler/rustc_trait_selection/src/traits/vtable.rs index 96b8e0b82b6a..c05d557b7744 100644 --- a/compiler/rustc_trait_selection/src/traits/vtable.rs +++ b/compiler/rustc_trait_selection/src/traits/vtable.rs @@ -115,7 +115,7 @@ pub fn prepare_vtable_segments<'tcx, T>( .predicates .into_iter() .filter_map(move |(pred, _)| { - pred.subst_supertrait(tcx, &inner_most_trait_ref).to_opt_poly_trait_pred() + pred.subst_supertrait(tcx, &inner_most_trait_ref).as_trait_clause() }); 'diving_in_skip_visited_traits: loop { diff --git a/compiler/rustc_trait_selection/src/traits/wf.rs b/compiler/rustc_trait_selection/src/traits/wf.rs index e96e89ce73ce..8bb4288f80de 100644 --- a/compiler/rustc_trait_selection/src/traits/wf.rs +++ b/compiler/rustc_trait_selection/src/traits/wf.rs @@ -185,7 +185,7 @@ pub fn predicate_obligations<'tcx>( | ty::PredicateKind::ConstEquate(..) | ty::PredicateKind::Ambiguous | ty::PredicateKind::AliasRelate(..) - | ty::PredicateKind::TypeWellFormedFromEnv(..) => { + | ty::PredicateKind::Clause(ty::ClauseKind::TypeWellFormedFromEnv(..)) => { bug!("We should only wf check where clauses, unexpected predicate: {predicate:?}") } } @@ -976,7 +976,7 @@ pub fn object_region_bounds<'tcx>( pub(crate) fn required_region_bounds<'tcx>( tcx: TyCtxt<'tcx>, erased_self_ty: Ty<'tcx>, - predicates: impl Iterator>, + predicates: impl Iterator>, ) -> Vec> { assert!(!erased_self_ty.has_escaping_bound_vars()); @@ -984,24 +984,7 @@ pub(crate) fn required_region_bounds<'tcx>( .filter_map(|pred| { debug!(?pred); match pred.kind().skip_binder() { - ty::PredicateKind::Clause(ty::ClauseKind::Projection(..)) - | ty::PredicateKind::Clause(ty::ClauseKind::Trait(..)) - | ty::PredicateKind::Clause(ty::ClauseKind::ConstArgHasType(..)) - | ty::PredicateKind::Subtype(..) - | ty::PredicateKind::Coerce(..) - | ty::PredicateKind::Clause(ty::ClauseKind::WellFormed(..)) - | ty::PredicateKind::ObjectSafe(..) - | ty::PredicateKind::ClosureKind(..) - | ty::PredicateKind::Clause(ty::ClauseKind::RegionOutlives(..)) - | ty::PredicateKind::Clause(ty::ClauseKind::ConstEvaluatable(..)) - | ty::PredicateKind::ConstEquate(..) - | ty::PredicateKind::Ambiguous - | ty::PredicateKind::AliasRelate(..) - | ty::PredicateKind::TypeWellFormedFromEnv(..) => None, - ty::PredicateKind::Clause(ty::ClauseKind::TypeOutlives(ty::OutlivesPredicate( - ref t, - ref r, - ))) => { + ty::ClauseKind::TypeOutlives(ty::OutlivesPredicate(ref t, ref r)) => { // Search for a bound of the form `erased_self_ty // : 'a`, but be wary of something like `for<'a> // erased_self_ty : 'a` (we interpret a @@ -1017,6 +1000,13 @@ pub(crate) fn required_region_bounds<'tcx>( None } } + ty::ClauseKind::Trait(_) + | ty::ClauseKind::RegionOutlives(_) + | ty::ClauseKind::Projection(_) + | ty::ClauseKind::ConstArgHasType(_, _) + | ty::ClauseKind::WellFormed(_) + | ty::ClauseKind::ConstEvaluatable(_) + | ty::ClauseKind::TypeWellFormedFromEnv(_) => None, } }) .collect() diff --git a/compiler/rustc_traits/src/chalk/db.rs b/compiler/rustc_traits/src/chalk/db.rs index 7e64cbdf54a8..6948151c644b 100644 --- a/compiler/rustc_traits/src/chalk/db.rs +++ b/compiler/rustc_traits/src/chalk/db.rs @@ -42,7 +42,7 @@ impl<'tcx> RustIrDatabase<'tcx> { .tcx .predicates_defined_on(def_id) .instantiate_own(self.interner.tcx, bound_vars) - .filter_map(|(wc, _)| LowerInto::lower_into(wc, self.interner)) + .filter_map(|(wc, _)| LowerInto::lower_into(wc.as_predicate(), self.interner)) .collect() } diff --git a/compiler/rustc_traits/src/chalk/lowering.rs b/compiler/rustc_traits/src/chalk/lowering.rs index aefe57e0ddfa..b7db56d3db8a 100644 --- a/compiler/rustc_traits/src/chalk/lowering.rs +++ b/compiler/rustc_traits/src/chalk/lowering.rs @@ -93,36 +93,28 @@ impl<'tcx> LowerInto<'tcx, chalk_ir::InEnvironment { + ty::ClauseKind::TypeWellFormedFromEnv(ty) => { chalk_ir::DomainGoal::FromEnv(chalk_ir::FromEnv::Ty(ty.lower_into(interner))) } - ty::PredicateKind::Clause(ty::ClauseKind::Trait(predicate)) => { - chalk_ir::DomainGoal::FromEnv(chalk_ir::FromEnv::Trait( - predicate.trait_ref.lower_into(interner), - )) - } - ty::PredicateKind::Clause(ty::ClauseKind::RegionOutlives(predicate)) => { - chalk_ir::DomainGoal::Holds(chalk_ir::WhereClause::LifetimeOutlives( - chalk_ir::LifetimeOutlives { - a: predicate.0.lower_into(interner), - b: predicate.1.lower_into(interner), - }, - )) - } - ty::PredicateKind::Clause(ty::ClauseKind::TypeOutlives(predicate)) => { - chalk_ir::DomainGoal::Holds(chalk_ir::WhereClause::TypeOutlives( - chalk_ir::TypeOutlives { - ty: predicate.0.lower_into(interner), - lifetime: predicate.1.lower_into(interner), - }, - )) - } - ty::PredicateKind::Clause(ty::ClauseKind::Projection(predicate)) => { - chalk_ir::DomainGoal::Holds(chalk_ir::WhereClause::AliasEq( - predicate.lower_into(interner), - )) - } - ty::PredicateKind::Clause(ty::ClauseKind::WellFormed(arg)) => match arg.unpack() { + ty::ClauseKind::Trait(predicate) => chalk_ir::DomainGoal::FromEnv( + chalk_ir::FromEnv::Trait(predicate.trait_ref.lower_into(interner)), + ), + ty::ClauseKind::RegionOutlives(predicate) => chalk_ir::DomainGoal::Holds( + chalk_ir::WhereClause::LifetimeOutlives(chalk_ir::LifetimeOutlives { + a: predicate.0.lower_into(interner), + b: predicate.1.lower_into(interner), + }), + ), + ty::ClauseKind::TypeOutlives(predicate) => chalk_ir::DomainGoal::Holds( + chalk_ir::WhereClause::TypeOutlives(chalk_ir::TypeOutlives { + ty: predicate.0.lower_into(interner), + lifetime: predicate.1.lower_into(interner), + }), + ), + ty::ClauseKind::Projection(predicate) => chalk_ir::DomainGoal::Holds( + chalk_ir::WhereClause::AliasEq(predicate.lower_into(interner)), + ), + ty::ClauseKind::WellFormed(arg) => match arg.unpack() { ty::GenericArgKind::Type(ty) => chalk_ir::DomainGoal::WellFormed( chalk_ir::WellFormed::Ty(ty.lower_into(interner)), ), @@ -131,15 +123,9 @@ impl<'tcx> LowerInto<'tcx, chalk_ir::InEnvironment bug!("unexpected predicate {}", predicate), + ty::ClauseKind::ConstArgHasType(..) | ty::ClauseKind::ConstEvaluatable(_) => { + bug!("unexpected predicate {}", predicate) + } }; let value = chalk_ir::ProgramClauseImplication { consequence, @@ -236,9 +222,11 @@ impl<'tcx> LowerInto<'tcx, chalk_ir::GoalData>> for ty::Predi | ty::PredicateKind::ConstEquate(..) => { chalk_ir::GoalData::All(chalk_ir::Goals::empty(interner)) } - ty::PredicateKind::TypeWellFormedFromEnv(ty) => chalk_ir::GoalData::DomainGoal( - chalk_ir::DomainGoal::FromEnv(chalk_ir::FromEnv::Ty(ty.lower_into(interner))), - ), + ty::PredicateKind::Clause(ty::ClauseKind::TypeWellFormedFromEnv(ty)) => { + chalk_ir::GoalData::DomainGoal(chalk_ir::DomainGoal::FromEnv( + chalk_ir::FromEnv::Ty(ty.lower_into(interner)), + )) + } }; chalk_ir::GoalData::Quantified( @@ -683,7 +671,7 @@ impl<'tcx> LowerInto<'tcx, Option { + | ty::PredicateKind::Clause(ty::ClauseKind::TypeWellFormedFromEnv(..)) => { bug!("unexpected predicate {self}") } }; @@ -819,7 +807,7 @@ impl<'tcx> LowerInto<'tcx, Option { + | ty::PredicateKind::Clause(ty::ClauseKind::TypeWellFormedFromEnv(..)) => { bug!("unexpected predicate {}", &self) } } diff --git a/compiler/rustc_traits/src/normalize_erasing_regions.rs b/compiler/rustc_traits/src/normalize_erasing_regions.rs index 96896526a126..b83abf985928 100644 --- a/compiler/rustc_traits/src/normalize_erasing_regions.rs +++ b/compiler/rustc_traits/src/normalize_erasing_regions.rs @@ -70,6 +70,6 @@ fn not_outlives_predicate(p: ty::Predicate<'_>) -> bool { | ty::PredicateKind::Clause(ty::ClauseKind::ConstEvaluatable(..)) | ty::PredicateKind::ConstEquate(..) | ty::PredicateKind::Ambiguous - | ty::PredicateKind::TypeWellFormedFromEnv(..) => true, + | ty::PredicateKind::Clause(ty::ClauseKind::TypeWellFormedFromEnv(..)) => true, } } diff --git a/compiler/rustc_traits/src/type_op.rs b/compiler/rustc_traits/src/type_op.rs index 98d814d54f28..01b9a5640b86 100644 --- a/compiler/rustc_traits/src/type_op.rs +++ b/compiler/rustc_traits/src/type_op.rs @@ -2,8 +2,8 @@ use rustc_infer::infer::canonical::{Canonical, QueryResponse}; use rustc_infer::infer::TyCtxtInferExt; use rustc_middle::query::Providers; use rustc_middle::traits::query::NoSolution; +use rustc_middle::ty::{Clause, ParamEnvAnd}; use rustc_middle::ty::{FnSig, Lift, PolyFnSig, Ty, TyCtxt, TypeFoldable}; -use rustc_middle::ty::{ParamEnvAnd, Predicate}; use rustc_trait_selection::infer::InferCtxtBuilderExt; use rustc_trait_selection::traits::query::normalize::QueryNormalizeExt; use rustc_trait_selection::traits::query::type_op::ascribe_user_type::{ @@ -23,7 +23,7 @@ pub(crate) fn provide(p: &mut Providers) { type_op_prove_predicate, type_op_subtype, type_op_normalize_ty, - type_op_normalize_predicate, + type_op_normalize_clause, type_op_normalize_fn_sig, type_op_normalize_poly_fn_sig, ..*p @@ -70,10 +70,10 @@ fn type_op_normalize_ty<'tcx>( tcx.infer_ctxt().enter_canonical_trait_query(&canonicalized, type_op_normalize) } -fn type_op_normalize_predicate<'tcx>( +fn type_op_normalize_clause<'tcx>( tcx: TyCtxt<'tcx>, - canonicalized: Canonical<'tcx, ParamEnvAnd<'tcx, Normalize>>>, -) -> Result<&'tcx Canonical<'tcx, QueryResponse<'tcx, Predicate<'tcx>>>, NoSolution> { + canonicalized: Canonical<'tcx, ParamEnvAnd<'tcx, Normalize>>>, +) -> Result<&'tcx Canonical<'tcx, QueryResponse<'tcx, Clause<'tcx>>>, NoSolution> { tcx.infer_ctxt().enter_canonical_trait_query(&canonicalized, type_op_normalize) } diff --git a/compiler/rustc_ty_utils/src/consts.rs b/compiler/rustc_ty_utils/src/consts.rs index 387adda8f579..d79ed2205704 100644 --- a/compiler/rustc_ty_utils/src/consts.rs +++ b/compiler/rustc_ty_utils/src/consts.rs @@ -241,7 +241,8 @@ fn recurse_build<'tcx>( ExprKind::Assign { .. } | ExprKind::AssignOp { .. } => { error(GenericConstantTooComplexSub::AssignNotSupported(node.span))? } - ExprKind::Closure { .. } | ExprKind::Return { .. } => { + // FIXME(explicit_tail_calls): maybe get `become` a new error + ExprKind::Closure { .. } | ExprKind::Return { .. } | ExprKind::Become { .. } => { error(GenericConstantTooComplexSub::ClosureAndReturnNotSupported(node.span))? } // let expressions imply control flow @@ -337,6 +338,7 @@ impl<'a, 'tcx> IsThirPolymorphic<'a, 'tcx> { | thir::ExprKind::Break { .. } | thir::ExprKind::Continue { .. } | thir::ExprKind::Return { .. } + | thir::ExprKind::Become { .. } | thir::ExprKind::Array { .. } | thir::ExprKind::Tuple { .. } | thir::ExprKind::Adt(_) diff --git a/compiler/rustc_ty_utils/src/ty.rs b/compiler/rustc_ty_utils/src/ty.rs index fe2d1fba7fe6..2daab520a2f7 100644 --- a/compiler/rustc_ty_utils/src/ty.rs +++ b/compiler/rustc_ty_utils/src/ty.rs @@ -4,8 +4,8 @@ use rustc_hir::def::DefKind; use rustc_index::bit_set::BitSet; use rustc_middle::query::Providers; use rustc_middle::ty::{ - self, Binder, EarlyBinder, ImplTraitInTraitData, Predicate, PredicateKind, ToPredicate, Ty, - TyCtxt, TypeSuperVisitable, TypeVisitable, TypeVisitor, + self, EarlyBinder, ImplTraitInTraitData, ToPredicate, Ty, TyCtxt, TypeSuperVisitable, + TypeVisitable, TypeVisitor, }; use rustc_session::config::TraitSolver; use rustc_span::def_id::{DefId, LocalDefId, CRATE_DEF_ID}; @@ -245,7 +245,7 @@ fn param_env(tcx: TyCtxt<'_>, def_id: DefId) -> ty::ParamEnv<'_> { }; let unnormalized_env = - ty::ParamEnv::new(tcx.mk_predicates(&predicates), traits::Reveal::UserFacing, constness); + ty::ParamEnv::new(tcx.mk_clauses(&predicates), traits::Reveal::UserFacing, constness); let body_id = local_did.unwrap_or(CRATE_DEF_ID); let cause = traits::ObligationCause::misc(tcx.def_span(def_id), body_id); @@ -258,7 +258,7 @@ fn param_env(tcx: TyCtxt<'_>, def_id: DefId) -> ty::ParamEnv<'_> { /// its corresponding opaque within the body of a default-body trait method. struct ImplTraitInTraitFinder<'a, 'tcx> { tcx: TyCtxt<'tcx>, - predicates: &'a mut Vec>, + predicates: &'a mut Vec>, fn_def_id: DefId, bound_vars: &'tcx ty::List, seen: FxHashSet, @@ -340,9 +340,8 @@ impl<'tcx> TypeVisitor> for ImplTraitInTraitFinder<'_, 'tcx> { /// that are assumed to be well-formed (because they come from the environment). /// /// Used only in chalk mode. -fn well_formed_types_in_env(tcx: TyCtxt<'_>, def_id: DefId) -> &ty::List> { +fn well_formed_types_in_env(tcx: TyCtxt<'_>, def_id: DefId) -> &ty::List> { use rustc_hir::{ForeignItemKind, ImplItemKind, ItemKind, Node, TraitItemKind}; - use rustc_middle::ty::subst::GenericArgKind; debug!("environment(def_id = {:?})", def_id); @@ -430,20 +429,19 @@ fn well_formed_types_in_env(tcx: TyCtxt<'_>, def_id: DefId) -> &ty::List { - let binder = Binder::dummy(PredicateKind::TypeWellFormedFromEnv(ty)); - Some(tcx.mk_predicate(binder)) + ty::GenericArgKind::Type(ty) => { + Some(ty::ClauseKind::TypeWellFormedFromEnv(ty).to_predicate(tcx)) } // FIXME(eddyb) no WF conditions from lifetimes? - GenericArgKind::Lifetime(_) => None, + ty::GenericArgKind::Lifetime(_) => None, // FIXME(eddyb) support const generics in Chalk - GenericArgKind::Const(_) => None, + ty::GenericArgKind::Const(_) => None, } }); - tcx.mk_predicates_from_iter(clauses.chain(input_clauses)) + tcx.mk_clauses_from_iter(clauses.chain(input_clauses)) } fn param_env_reveal_all_normalized(tcx: TyCtxt<'_>, def_id: DefId) -> ty::ParamEnv<'_> { diff --git a/library/alloc/Cargo.toml b/library/alloc/Cargo.toml index 95c07abf7310..e5f828c4c0b3 100644 --- a/library/alloc/Cargo.toml +++ b/library/alloc/Cargo.toml @@ -35,3 +35,4 @@ compiler-builtins-mem = ['compiler_builtins/mem'] compiler-builtins-c = ["compiler_builtins/c"] compiler-builtins-no-asm = ["compiler_builtins/no-asm"] compiler-builtins-mangled-names = ["compiler_builtins/mangled-names"] +compiler-builtins-weak-intrinsics = ["compiler_builtins/weak-intrinsics"] diff --git a/library/alloc/src/boxed.rs b/library/alloc/src/boxed.rs index 8ef2bac9282c..fa23367593db 100644 --- a/library/alloc/src/boxed.rs +++ b/library/alloc/src/boxed.rs @@ -1319,39 +1319,56 @@ impl Clone for Box { } #[stable(feature = "rust1", since = "1.0.0")] -impl PartialEq for Box { +impl PartialEq> for Box +where + T: ?Sized + PartialEq, + A1: Allocator, + A2: Allocator, +{ #[inline] - fn eq(&self, other: &Self) -> bool { + fn eq(&self, other: &Box) -> bool { PartialEq::eq(&**self, &**other) } + #[inline] - fn ne(&self, other: &Self) -> bool { + fn ne(&self, other: &Box) -> bool { PartialEq::ne(&**self, &**other) } } + #[stable(feature = "rust1", since = "1.0.0")] -impl PartialOrd for Box { +impl PartialOrd> for Box +where + T: ?Sized + PartialOrd, + A1: Allocator, + A2: Allocator, +{ #[inline] - fn partial_cmp(&self, other: &Self) -> Option { + fn partial_cmp(&self, other: &Box) -> Option { PartialOrd::partial_cmp(&**self, &**other) } + #[inline] - fn lt(&self, other: &Self) -> bool { + fn lt(&self, other: &Box) -> bool { PartialOrd::lt(&**self, &**other) } + #[inline] - fn le(&self, other: &Self) -> bool { + fn le(&self, other: &Box) -> bool { PartialOrd::le(&**self, &**other) } + #[inline] - fn ge(&self, other: &Self) -> bool { + fn ge(&self, other: &Box) -> bool { PartialOrd::ge(&**self, &**other) } + #[inline] - fn gt(&self, other: &Self) -> bool { + fn gt(&self, other: &Box) -> bool { PartialOrd::gt(&**self, &**other) } } + #[stable(feature = "rust1", since = "1.0.0")] impl Ord for Box { #[inline] diff --git a/library/alloc/src/vec/extract_if.rs b/library/alloc/src/vec/extract_if.rs index e8e6bd56d21b..118cfdb36b9c 100644 --- a/library/alloc/src/vec/extract_if.rs +++ b/library/alloc/src/vec/extract_if.rs @@ -37,12 +37,6 @@ pub struct ExtractIf< pub(super) old_len: usize, /// The filter test predicate. pub(super) pred: F, - /// A flag that indicates a panic has occurred in the filter test predicate. - /// This is used as a hint in the drop implementation to prevent consumption - /// of the remainder of the `ExtractIf`. Any unprocessed items will be - /// backshifted in the `vec`, but no further items will be dropped or - /// tested by the filter predicate. - pub(super) panic_flag: bool, } impl ExtractIf<'_, T, F, A> @@ -69,9 +63,7 @@ where while self.idx < self.old_len { let i = self.idx; let v = slice::from_raw_parts_mut(self.vec.as_mut_ptr(), self.old_len); - self.panic_flag = true; let drained = (self.pred)(&mut v[i]); - self.panic_flag = false; // Update the index *after* the predicate is called. If the index // is updated prior and the predicate panics, the element at this // index would be leaked. diff --git a/library/alloc/src/vec/mod.rs b/library/alloc/src/vec/mod.rs index a30c6a44e071..ef4f8be6f19d 100644 --- a/library/alloc/src/vec/mod.rs +++ b/library/alloc/src/vec/mod.rs @@ -2948,7 +2948,7 @@ impl Vec { self.set_len(0); } - ExtractIf { vec: self, idx: 0, del: 0, old_len, pred: filter, panic_flag: false } + ExtractIf { vec: self, idx: 0, del: 0, old_len, pred: filter } } } diff --git a/library/core/benches/iter.rs b/library/core/benches/iter.rs index 60ef83223d10..5ec22e5147b1 100644 --- a/library/core/benches/iter.rs +++ b/library/core/benches/iter.rs @@ -2,6 +2,7 @@ use core::borrow::Borrow; use core::iter::*; use core::mem; use core::num::Wrapping; +use core::ops::Range; use test::{black_box, Bencher}; #[bench] @@ -69,6 +70,57 @@ fn bench_max(b: &mut Bencher) { }) } +#[bench] +fn bench_range_step_by_sum_reducible(b: &mut Bencher) { + let r = 0u32..1024; + b.iter(|| { + let r = black_box(r.clone()).step_by(8); + + let mut sum: u32 = 0; + for i in r { + sum += i; + } + + sum + }) +} + +#[bench] +fn bench_range_step_by_loop_u32(b: &mut Bencher) { + let r = 0..(u16::MAX as u32); + b.iter(|| { + let r = black_box(r.clone()).step_by(64); + + let mut sum: u32 = 0; + for i in r { + let i = i ^ i.wrapping_sub(1); + sum = sum.wrapping_add(i); + } + + sum + }) +} + +#[bench] +fn bench_range_step_by_fold_usize(b: &mut Bencher) { + let r: Range = 0..(u16::MAX as usize); + b.iter(|| { + let r = black_box(r.clone()); + r.step_by(64) + .map(|x: usize| x ^ (x.wrapping_sub(1))) + .fold(0usize, |acc, i| acc.wrapping_add(i)) + }) +} + +#[bench] +fn bench_range_step_by_fold_u16(b: &mut Bencher) { + let r: Range = 0..u16::MAX; + b.iter(|| { + let r = black_box(r.clone()); + r.step_by(64).map(|x: u16| x ^ (x.wrapping_sub(1))).fold(0u16, |acc, i| acc.wrapping_add(i)) + }) +} + pub fn copy_zip(xs: &[u8], ys: &mut [u8]) { for (a, b) in ys.iter_mut().zip(xs) { *a = *b; diff --git a/library/core/src/default.rs b/library/core/src/default.rs index 09dbc95810f5..1f7be85d38ac 100644 --- a/library/core/src/default.rs +++ b/library/core/src/default.rs @@ -190,7 +190,7 @@ macro_rules! default_impl { ($t:ty, $v:expr, $doc:tt) => { #[stable(feature = "rust1", since = "1.0.0")] impl Default for $t { - #[inline] + #[inline(always)] #[doc = $doc] fn default() -> $t { $v diff --git a/library/core/src/iter/adapters/step_by.rs b/library/core/src/iter/adapters/step_by.rs index 4252c34a0e0f..7f58f7d17758 100644 --- a/library/core/src/iter/adapters/step_by.rs +++ b/library/core/src/iter/adapters/step_by.rs @@ -1,4 +1,9 @@ -use crate::{intrinsics, iter::from_fn, ops::Try}; +use crate::convert::TryFrom; +use crate::{ + intrinsics, + iter::{from_fn, TrustedLen}, + ops::{Range, Try}, +}; /// An iterator for stepping iterators by a custom amount. /// @@ -11,14 +16,22 @@ use crate::{intrinsics, iter::from_fn, ops::Try}; #[stable(feature = "iterator_step_by", since = "1.28.0")] #[derive(Clone, Debug)] pub struct StepBy { + /// This field is guaranteed to be preprocessed by the specialized `SpecRangeSetup::setup` + /// in the constructor. + /// For most iterators that processing is a no-op, but for Range<{integer}> types it is lossy + /// which means the inner iterator cannot be returned to user code. + /// Additionally this type-dependent preprocessing means specialized implementations + /// cannot be used interchangeably. iter: I, step: usize, first_take: bool, } impl StepBy { + #[inline] pub(in crate::iter) fn new(iter: I, step: usize) -> StepBy { assert!(step != 0); + let iter = >::setup(iter, step); StepBy { iter, step: step - 1, first_take: true } } } @@ -32,16 +45,174 @@ where #[inline] fn next(&mut self) -> Option { - if self.first_take { - self.first_take = false; - self.iter.next() - } else { - self.iter.nth(self.step) - } + self.spec_next() } #[inline] fn size_hint(&self) -> (usize, Option) { + self.spec_size_hint() + } + + #[inline] + fn nth(&mut self, n: usize) -> Option { + self.spec_nth(n) + } + + fn try_fold(&mut self, acc: Acc, f: F) -> R + where + F: FnMut(Acc, Self::Item) -> R, + R: Try, + { + self.spec_try_fold(acc, f) + } + + #[inline] + fn fold(self, acc: Acc, f: F) -> Acc + where + F: FnMut(Acc, Self::Item) -> Acc, + { + self.spec_fold(acc, f) + } +} + +impl StepBy +where + I: ExactSizeIterator, +{ + // The zero-based index starting from the end of the iterator of the + // last element. Used in the `DoubleEndedIterator` implementation. + fn next_back_index(&self) -> usize { + let rem = self.iter.len() % (self.step + 1); + if self.first_take { + if rem == 0 { self.step } else { rem - 1 } + } else { + rem + } + } +} + +#[stable(feature = "double_ended_step_by_iterator", since = "1.38.0")] +impl DoubleEndedIterator for StepBy +where + I: DoubleEndedIterator + ExactSizeIterator, +{ + #[inline] + fn next_back(&mut self) -> Option { + self.spec_next_back() + } + + #[inline] + fn nth_back(&mut self, n: usize) -> Option { + self.spec_nth_back(n) + } + + fn try_rfold(&mut self, init: Acc, f: F) -> R + where + F: FnMut(Acc, Self::Item) -> R, + R: Try, + { + self.spec_try_rfold(init, f) + } + + #[inline] + fn rfold(self, init: Acc, f: F) -> Acc + where + Self: Sized, + F: FnMut(Acc, Self::Item) -> Acc, + { + self.spec_rfold(init, f) + } +} + +// StepBy can only make the iterator shorter, so the len will still fit. +#[stable(feature = "iterator_step_by", since = "1.28.0")] +impl ExactSizeIterator for StepBy where I: ExactSizeIterator {} + +trait SpecRangeSetup { + fn setup(inner: T, step: usize) -> T; +} + +impl SpecRangeSetup for T { + #[inline] + default fn setup(inner: T, _step: usize) -> T { + inner + } +} + +/// Specialization trait to optimize `StepBy>` iteration. +/// +/// # Safety +/// +/// Technically this is safe to implement (look ma, no unsafe!), but in reality +/// a lot of unsafe code relies on ranges over integers being correct. +/// +/// For correctness *all* public StepBy methods must be specialized +/// because `setup` drastically alters the meaning of the struct fields so that mixing +/// different implementations would lead to incorrect results. +unsafe trait StepByImpl { + type Item; + + fn spec_next(&mut self) -> Option; + + fn spec_size_hint(&self) -> (usize, Option); + + fn spec_nth(&mut self, n: usize) -> Option; + + fn spec_try_fold(&mut self, acc: Acc, f: F) -> R + where + F: FnMut(Acc, Self::Item) -> R, + R: Try; + + fn spec_fold(self, acc: Acc, f: F) -> Acc + where + F: FnMut(Acc, Self::Item) -> Acc; +} + +/// Specialization trait for double-ended iteration. +/// +/// See also: `StepByImpl` +/// +/// # Safety +/// +/// The specializations must be implemented together with `StepByImpl` +/// where applicable. I.e. if `StepBy` does support backwards iteration +/// for a given iterator and that is specialized for forward iteration then +/// it must also be specialized for backwards iteration. +unsafe trait StepByBackImpl { + type Item; + + fn spec_next_back(&mut self) -> Option + where + I: DoubleEndedIterator + ExactSizeIterator; + + fn spec_nth_back(&mut self, n: usize) -> Option + where + I: DoubleEndedIterator + ExactSizeIterator; + + fn spec_try_rfold(&mut self, init: Acc, f: F) -> R + where + I: DoubleEndedIterator + ExactSizeIterator, + F: FnMut(Acc, Self::Item) -> R, + R: Try; + + fn spec_rfold(self, init: Acc, f: F) -> Acc + where + I: DoubleEndedIterator + ExactSizeIterator, + F: FnMut(Acc, Self::Item) -> Acc; +} + +unsafe impl StepByImpl for StepBy { + type Item = I::Item; + + #[inline] + default fn spec_next(&mut self) -> Option { + let step_size = if self.first_take { 0 } else { self.step }; + self.first_take = false; + self.iter.nth(step_size) + } + + #[inline] + default fn spec_size_hint(&self) -> (usize, Option) { #[inline] fn first_size(step: usize) -> impl Fn(usize) -> usize { move |n| if n == 0 { 0 } else { 1 + (n - 1) / (step + 1) } @@ -64,7 +235,7 @@ where } #[inline] - fn nth(&mut self, mut n: usize) -> Option { + default fn spec_nth(&mut self, mut n: usize) -> Option { if self.first_take { self.first_take = false; let first = self.iter.next(); @@ -108,7 +279,7 @@ where } } - fn try_fold(&mut self, mut acc: Acc, mut f: F) -> R + default fn spec_try_fold(&mut self, mut acc: Acc, mut f: F) -> R where F: FnMut(Acc, Self::Item) -> R, R: Try, @@ -128,7 +299,7 @@ where from_fn(nth(&mut self.iter, self.step)).try_fold(acc, f) } - fn fold(mut self, mut acc: Acc, mut f: F) -> Acc + default fn spec_fold(mut self, mut acc: Acc, mut f: F) -> Acc where F: FnMut(Acc, Self::Item) -> Acc, { @@ -148,34 +319,16 @@ where } } -impl StepBy -where - I: ExactSizeIterator, -{ - // The zero-based index starting from the end of the iterator of the - // last element. Used in the `DoubleEndedIterator` implementation. - fn next_back_index(&self) -> usize { - let rem = self.iter.len() % (self.step + 1); - if self.first_take { - if rem == 0 { self.step } else { rem - 1 } - } else { - rem - } - } -} +unsafe impl StepByBackImpl for StepBy { + type Item = I::Item; -#[stable(feature = "double_ended_step_by_iterator", since = "1.38.0")] -impl DoubleEndedIterator for StepBy -where - I: DoubleEndedIterator + ExactSizeIterator, -{ #[inline] - fn next_back(&mut self) -> Option { + default fn spec_next_back(&mut self) -> Option { self.iter.nth_back(self.next_back_index()) } #[inline] - fn nth_back(&mut self, n: usize) -> Option { + default fn spec_nth_back(&mut self, n: usize) -> Option { // `self.iter.nth_back(usize::MAX)` does the right thing here when `n` // is out of bounds because the length of `self.iter` does not exceed // `usize::MAX` (because `I: ExactSizeIterator`) and `nth_back` is @@ -184,7 +337,7 @@ where self.iter.nth_back(n) } - fn try_rfold(&mut self, init: Acc, mut f: F) -> R + default fn spec_try_rfold(&mut self, init: Acc, mut f: F) -> R where F: FnMut(Acc, Self::Item) -> R, R: Try, @@ -207,10 +360,10 @@ where } #[inline] - fn rfold(mut self, init: Acc, mut f: F) -> Acc + default fn spec_rfold(mut self, init: Acc, mut f: F) -> Acc where Self: Sized, - F: FnMut(Acc, Self::Item) -> Acc, + F: FnMut(Acc, I::Item) -> Acc, { #[inline] fn nth_back( @@ -230,6 +383,192 @@ where } } -// StepBy can only make the iterator shorter, so the len will still fit. -#[stable(feature = "iterator_step_by", since = "1.28.0")] -impl ExactSizeIterator for StepBy where I: ExactSizeIterator {} +/// For these implementations, `SpecRangeSetup` calculates the number +/// of iterations that will be needed and stores that in `iter.end`. +/// +/// The various iterator implementations then rely on that to not need +/// overflow checking, letting loops just be counted instead. +/// +/// These only work for unsigned types, and will need to be reworked +/// if you want to use it to specialize on signed types. +/// +/// Currently these are only implemented for integers up to usize due to +/// correctness issues around ExactSizeIterator impls on 16bit platforms. +/// And since ExactSizeIterator is a prerequisite for backwards iteration +/// and we must consistently specialize backwards and forwards iteration +/// that makes the situation complicated enough that it's not covered +/// for now. +macro_rules! spec_int_ranges { + ($($t:ty)*) => ($( + + const _: () = assert!(usize::BITS >= <$t>::BITS); + + impl SpecRangeSetup> for Range<$t> { + #[inline] + fn setup(mut r: Range<$t>, step: usize) -> Range<$t> { + let inner_len = r.size_hint().0; + // If step exceeds $t::MAX, then the count will be at most 1 and + // thus always fit into $t. + let yield_count = inner_len.div_ceil(step); + // Turn the range end into an iteration counter + r.end = yield_count as $t; + r + } + } + + unsafe impl StepByImpl> for StepBy> { + #[inline] + fn spec_next(&mut self) -> Option<$t> { + // if a step size larger than the type has been specified fall back to + // t::MAX, in which case remaining will be at most 1. + // The `+ 1` can't overflow since the constructor substracted 1 from the original value. + let step = <$t>::try_from(self.step + 1).unwrap_or(<$t>::MAX); + let remaining = self.iter.end; + if remaining > 0 { + let val = self.iter.start; + // this can only overflow during the last step, after which the value + // will not be used + self.iter.start = val.wrapping_add(step); + self.iter.end = remaining - 1; + Some(val) + } else { + None + } + } + + #[inline] + fn spec_size_hint(&self) -> (usize, Option) { + let remaining = self.iter.end as usize; + (remaining, Some(remaining)) + } + + // The methods below are all copied from the Iterator trait default impls. + // We have to repeat them here so that the specialization overrides the StepByImpl defaults + + #[inline] + fn spec_nth(&mut self, n: usize) -> Option { + self.advance_by(n).ok()?; + self.next() + } + + #[inline] + fn spec_try_fold(&mut self, init: Acc, mut f: F) -> R + where + F: FnMut(Acc, Self::Item) -> R, + R: Try + { + let mut accum = init; + while let Some(x) = self.next() { + accum = f(accum, x)?; + } + try { accum } + } + + #[inline] + fn spec_fold(self, init: Acc, mut f: F) -> Acc + where + F: FnMut(Acc, Self::Item) -> Acc + { + // if a step size larger than the type has been specified fall back to + // t::MAX, in which case remaining will be at most 1. + let step = <$t>::try_from(self.step + 1).unwrap_or(<$t>::MAX); + let remaining = self.iter.end; + let mut acc = init; + let mut val = self.iter.start; + for _ in 0..remaining { + acc = f(acc, val); + // this can only overflow during the last step, after which the value + // will no longer be used + val = val.wrapping_add(step); + } + acc + } + } + + /// Safety: This macro is only applied to ranges over types <= usize + /// which means the inner length is guaranteed to fit into a usize and so + /// the outer length calculation won't encounter clamped values + #[unstable(feature = "trusted_len", issue = "37572")] + unsafe impl TrustedLen for StepBy> {} + )*) +} + +macro_rules! spec_int_ranges_r { + ($($t:ty)*) => ($( + const _: () = assert!(usize::BITS >= <$t>::BITS); + + unsafe impl StepByBackImpl> for StepBy> { + + #[inline] + fn spec_next_back(&mut self) -> Option + where Range<$t>: DoubleEndedIterator + ExactSizeIterator, + { + let step = (self.step + 1) as $t; + let remaining = self.iter.end; + if remaining > 0 { + let start = self.iter.start; + self.iter.end = remaining - 1; + Some(start + step * (remaining - 1)) + } else { + None + } + } + + // The methods below are all copied from the Iterator trait default impls. + // We have to repeat them here so that the specialization overrides the StepByImplBack defaults + + #[inline] + fn spec_nth_back(&mut self, n: usize) -> Option + where Self: DoubleEndedIterator, + { + if self.advance_back_by(n).is_err() { + return None; + } + self.next_back() + } + + #[inline] + fn spec_try_rfold(&mut self, init: Acc, mut f: F) -> R + where + Self: DoubleEndedIterator, + F: FnMut(Acc, Self::Item) -> R, + R: Try + { + let mut accum = init; + while let Some(x) = self.next_back() { + accum = f(accum, x)?; + } + try { accum } + } + + #[inline] + fn spec_rfold(mut self, init: Acc, mut f: F) -> Acc + where + Self: DoubleEndedIterator, + F: FnMut(Acc, Self::Item) -> Acc + { + let mut accum = init; + while let Some(x) = self.next_back() { + accum = f(accum, x); + } + accum + } + } + )*) +} + +#[cfg(target_pointer_width = "64")] +spec_int_ranges!(u8 u16 u32 u64 usize); +// DoubleEndedIterator requires ExactSizeIterator, which isn't implemented for Range +#[cfg(target_pointer_width = "64")] +spec_int_ranges_r!(u8 u16 u32 usize); + +#[cfg(target_pointer_width = "32")] +spec_int_ranges!(u8 u16 u32 usize); +#[cfg(target_pointer_width = "32")] +spec_int_ranges_r!(u8 u16 u32 usize); + +#[cfg(target_pointer_width = "16")] +spec_int_ranges!(u8 u16 usize); +#[cfg(target_pointer_width = "16")] +spec_int_ranges_r!(u8 u16 usize); diff --git a/library/core/tests/iter/adapters/step_by.rs b/library/core/tests/iter/adapters/step_by.rs index 94f2fa8c25e2..4c5b1dd9a6bd 100644 --- a/library/core/tests/iter/adapters/step_by.rs +++ b/library/core/tests/iter/adapters/step_by.rs @@ -244,3 +244,58 @@ fn test_step_by_skip() { assert_eq!((0..=50).step_by(10).nth(3), Some(30)); assert_eq!((200..=255u8).step_by(10).nth(3), Some(230)); } + + +struct DeOpt(I); + +impl Iterator for DeOpt { + type Item = I::Item; + + fn next(&mut self) -> core::option::Option { + self.0.next() + } +} + +impl DoubleEndedIterator for DeOpt { + fn next_back(&mut self) -> core::option::Option { + self.0.next_back() + } +} + +#[test] +fn test_step_by_fold_range_specialization() { + macro_rules! t { + ($range:expr, $var: ident, $body:tt) => { + { + // run the same tests for the non-optimized version + let mut $var = DeOpt($range); + $body + } + { + let mut $var = $range; + $body + } + } + } + + t!((1usize..5).step_by(1), r, { + assert_eq!(r.next_back(), Some(4)); + assert_eq!(r.sum::(), 6); + }); + + t!((0usize..4).step_by(2), r, { + assert_eq!(r.next(), Some(0)); + assert_eq!(r.sum::(), 2); + }); + + + t!((0usize..5).step_by(2), r, { + assert_eq!(r.next(), Some(0)); + assert_eq!(r.sum::(), 6); + }); + + t!((usize::MAX - 6 .. usize::MAX).step_by(5), r, { + assert_eq!(r.next(), Some(usize::MAX - 6)); + assert_eq!(r.sum::(), usize::MAX - 1); + }); +} diff --git a/library/std/Cargo.toml b/library/std/Cargo.toml index aaaa88624f0c..151809b2df5e 100644 --- a/library/std/Cargo.toml +++ b/library/std/Cargo.toml @@ -65,6 +65,7 @@ compiler-builtins-c = ["alloc/compiler-builtins-c"] compiler-builtins-mem = ["alloc/compiler-builtins-mem"] compiler-builtins-no-asm = ["alloc/compiler-builtins-no-asm"] compiler-builtins-mangled-names = ["alloc/compiler-builtins-mangled-names"] +compiler-builtins-weak-intrinsics = ["alloc/compiler-builtins-weak-intrinsics"] llvm-libunwind = ["unwind/llvm-libunwind"] system-llvm-libunwind = ["unwind/system-llvm-libunwind"] diff --git a/library/std/src/fs.rs b/library/std/src/fs.rs index 89dfdfafdb17..c2d82169dc30 100644 --- a/library/std/src/fs.rs +++ b/library/std/src/fs.rs @@ -1755,8 +1755,14 @@ impl DirEntry { self.0.file_type().map(FileType) } - /// Returns the bare file name of this directory entry without any other - /// leading path component. + /// Returns the file name of this directory entry without any + /// leading path component(s). + /// + /// As an example, + /// the output of the function will result in "foo" for all the following paths: + /// - "./foo" + /// - "/the/foo" + /// - "../../foo" /// /// # Examples /// diff --git a/library/std/src/sys/windows/c.rs b/library/std/src/sys/windows/c.rs index 5fc6136ba1fc..b1b9e84fce9e 100644 --- a/library/std/src/sys/windows/c.rs +++ b/library/std/src/sys/windows/c.rs @@ -12,7 +12,6 @@ use crate::os::windows::io::{AsRawHandle, BorrowedHandle}; use crate::ptr; use core::ffi::NonZero_c_ulong; -#[path = "c/windows_sys.rs"] // c.rs is included from two places so we need to specify this mod windows_sys; pub use windows_sys::*; @@ -432,3 +431,47 @@ compat_fn_with_fallback! { Status as u32 } } + +// # Arm32 shim +// +// AddVectoredExceptionHandler and WSAStartup use platform-specific types. +// However, Microsoft no longer supports thumbv7a so definitions for those targets +// are not included in the win32 metadata. We work around that by defining them here. +// +// Where possible, these definitions should be kept in sync with https://docs.rs/windows-sys +cfg_if::cfg_if! { +if #[cfg(not(target_vendor = "uwp"))] { + #[link(name = "kernel32")] + extern "system" { + pub fn AddVectoredExceptionHandler( + first: u32, + handler: PVECTORED_EXCEPTION_HANDLER, + ) -> *mut c_void; + } + pub type PVECTORED_EXCEPTION_HANDLER = Option< + unsafe extern "system" fn(exceptioninfo: *mut EXCEPTION_POINTERS) -> i32, + >; + #[repr(C)] + pub struct EXCEPTION_POINTERS { + pub ExceptionRecord: *mut EXCEPTION_RECORD, + pub ContextRecord: *mut CONTEXT, + } + #[cfg(target_arch = "arm")] + pub enum CONTEXT {} +}} + +#[link(name = "ws2_32")] +extern "system" { + pub fn WSAStartup(wversionrequested: u16, lpwsadata: *mut WSADATA) -> i32; +} +#[cfg(target_arch = "arm")] +#[repr(C)] +pub struct WSADATA { + pub wVersion: u16, + pub wHighVersion: u16, + pub szDescription: [u8; 257], + pub szSystemStatus: [u8; 129], + pub iMaxSockets: u16, + pub iMaxUdpDg: u16, + pub lpVendorInfo: PSTR, +} diff --git a/library/std/src/sys/windows/c/windows_sys.lst b/library/std/src/sys/windows/c/windows_sys.lst index 2cf1ade99ce5..631aedd26b4e 100644 --- a/library/std/src/sys/windows/c/windows_sys.lst +++ b/library/std/src/sys/windows/c/windows_sys.lst @@ -2171,7 +2171,6 @@ Windows.Win32.Networking.WinSock.WSARecv Windows.Win32.Networking.WinSock.WSASend Windows.Win32.Networking.WinSock.WSASERVICE_NOT_FOUND Windows.Win32.Networking.WinSock.WSASocketW -Windows.Win32.Networking.WinSock.WSAStartup Windows.Win32.Networking.WinSock.WSASYSCALLFAILURE Windows.Win32.Networking.WinSock.WSASYSNOTREADY Windows.Win32.Networking.WinSock.WSATRY_AGAIN @@ -2419,12 +2418,10 @@ Windows.Win32.System.Console.STD_HANDLE Windows.Win32.System.Console.STD_INPUT_HANDLE Windows.Win32.System.Console.STD_OUTPUT_HANDLE Windows.Win32.System.Console.WriteConsoleW -Windows.Win32.System.Diagnostics.Debug.AddVectoredExceptionHandler Windows.Win32.System.Diagnostics.Debug.ARM64_NT_NEON128 Windows.Win32.System.Diagnostics.Debug.CONTEXT Windows.Win32.System.Diagnostics.Debug.CONTEXT Windows.Win32.System.Diagnostics.Debug.CONTEXT -Windows.Win32.System.Diagnostics.Debug.EXCEPTION_POINTERS Windows.Win32.System.Diagnostics.Debug.EXCEPTION_RECORD Windows.Win32.System.Diagnostics.Debug.FACILITY_CODE Windows.Win32.System.Diagnostics.Debug.FACILITY_NT_BIT @@ -2437,7 +2434,6 @@ Windows.Win32.System.Diagnostics.Debug.FORMAT_MESSAGE_IGNORE_INSERTS Windows.Win32.System.Diagnostics.Debug.FORMAT_MESSAGE_OPTIONS Windows.Win32.System.Diagnostics.Debug.FormatMessageW Windows.Win32.System.Diagnostics.Debug.M128A -Windows.Win32.System.Diagnostics.Debug.PVECTORED_EXCEPTION_HANDLER Windows.Win32.System.Diagnostics.Debug.XSAVE_FORMAT Windows.Win32.System.Diagnostics.Debug.XSAVE_FORMAT Windows.Win32.System.Environment.FreeEnvironmentStringsW diff --git a/library/std/src/sys/windows/c/windows_sys.rs b/library/std/src/sys/windows/c/windows_sys.rs index a4294f336fec..02377087173a 100644 --- a/library/std/src/sys/windows/c/windows_sys.rs +++ b/library/std/src/sys/windows/c/windows_sys.rs @@ -39,13 +39,6 @@ extern "system" { pub fn AcquireSRWLockShared(srwlock: *mut RTL_SRWLOCK) -> (); } #[link(name = "kernel32")] -extern "system" { - pub fn AddVectoredExceptionHandler( - first: u32, - handler: PVECTORED_EXCEPTION_HANDLER, - ) -> *mut ::core::ffi::c_void; -} -#[link(name = "kernel32")] extern "system" { pub fn CancelIo(hfile: HANDLE) -> BOOL; } @@ -711,10 +704,6 @@ extern "system" { ) -> SOCKET; } #[link(name = "ws2_32")] -extern "system" { - pub fn WSAStartup(wversionrequested: u16, lpwsadata: *mut WSADATA) -> i32; -} -#[link(name = "ws2_32")] extern "system" { pub fn accept(s: SOCKET, addr: *mut SOCKADDR, addrlen: *mut i32) -> SOCKET; } @@ -3029,17 +3018,6 @@ pub const ERROR_XML_PARSE_ERROR: WIN32_ERROR = 1465u32; pub type EXCEPTION_DISPOSITION = i32; pub const EXCEPTION_MAXIMUM_PARAMETERS: u32 = 15u32; #[repr(C)] -pub struct EXCEPTION_POINTERS { - pub ExceptionRecord: *mut EXCEPTION_RECORD, - pub ContextRecord: *mut CONTEXT, -} -impl ::core::marker::Copy for EXCEPTION_POINTERS {} -impl ::core::clone::Clone for EXCEPTION_POINTERS { - fn clone(&self) -> Self { - *self - } -} -#[repr(C)] pub struct EXCEPTION_RECORD { pub ExceptionCode: NTSTATUS, pub ExceptionFlags: u32, @@ -3748,9 +3726,6 @@ pub const PROFILE_SERVER: PROCESS_CREATION_FLAGS = 1073741824u32; pub const PROFILE_USER: PROCESS_CREATION_FLAGS = 268435456u32; pub const PROGRESS_CONTINUE: u32 = 0u32; pub type PSTR = *mut u8; -pub type PVECTORED_EXCEPTION_HANDLER = ::core::option::Option< - unsafe extern "system" fn(exceptioninfo: *mut EXCEPTION_POINTERS) -> i32, ->; pub type PWSTR = *mut u16; pub const READ_CONTROL: FILE_ACCESS_RIGHTS = 131072u32; pub const REALTIME_PRIORITY_CLASS: PROCESS_CREATION_FLAGS = 256u32; @@ -4275,23 +4250,3 @@ impl ::core::clone::Clone for XSAVE_FORMAT { *self } } -// Begin of ARM32 shim -// The raw content of this file should be processed by `generate-windows-sys` -// to be merged with the generated binding. It is not supposed to be used as -// a normal Rust module. -cfg_if::cfg_if! { -if #[cfg(target_arch = "arm")] { -#[repr(C)] -pub struct WSADATA { - pub wVersion: u16, - pub wHighVersion: u16, - pub szDescription: [u8; 257], - pub szSystemStatus: [u8; 129], - pub iMaxSockets: u16, - pub iMaxUdpDg: u16, - pub lpVendorInfo: PSTR, -} -pub enum CONTEXT {} -} -} -// End of ARM32 shim diff --git a/library/sysroot/Cargo.toml b/library/sysroot/Cargo.toml index 5356ee277cc2..6ff24a8db59c 100644 --- a/library/sysroot/Cargo.toml +++ b/library/sysroot/Cargo.toml @@ -17,6 +17,7 @@ compiler-builtins-c = ["std/compiler-builtins-c"] compiler-builtins-mem = ["std/compiler-builtins-mem"] compiler-builtins-no-asm = ["std/compiler-builtins-no-asm"] compiler-builtins-mangled-names = ["std/compiler-builtins-mangled-names"] +compiler-builtins-weak-intrinsics = ["std/compiler-builtins-weak-intrinsics"] llvm-libunwind = ["std/llvm-libunwind"] system-llvm-libunwind = ["std/system-llvm-libunwind"] panic-unwind = ["std/panic_unwind"] diff --git a/src/bootstrap/bin/main.rs b/src/bootstrap/bin/main.rs index a80379e85c19..7ce4599c4241 100644 --- a/src/bootstrap/bin/main.rs +++ b/src/bootstrap/bin/main.rs @@ -5,7 +5,9 @@ //! parent directory, and otherwise documentation can be found throughout the `build` //! directory in each respective module. -use std::env; +use std::fs::OpenOptions; +use std::io::Write; +use std::{env, fs, process}; #[cfg(all(any(unix, windows), not(target_os = "solaris")))] use bootstrap::t; @@ -20,22 +22,32 @@ fn main() { #[cfg(all(any(unix, windows), not(target_os = "solaris")))] let _build_lock_guard; #[cfg(all(any(unix, windows), not(target_os = "solaris")))] + // Display PID of process holding the lock + // PID will be stored in a lock file { let path = config.out.join("lock"); - build_lock = fd_lock::RwLock::new(t!(std::fs::File::create(&path))); + let pid = match fs::read_to_string(&path) { + Ok(contents) => contents, + Err(_) => String::new(), + }; + + build_lock = + fd_lock::RwLock::new(t!(OpenOptions::new().write(true).create(true).open(&path))); _build_lock_guard = match build_lock.try_write() { - Ok(lock) => lock, + Ok(mut lock) => { + t!(lock.write(&process::id().to_string().as_ref())); + lock + } err => { drop(err); - if let Some(pid) = get_lock_owner(&path) { - println!("warning: build directory locked by process {pid}, waiting for lock"); - } else { - println!("warning: build directory locked, waiting for lock"); - } - t!(build_lock.write()) + println!("warning: build directory locked by process {pid}, waiting for lock"); + let mut lock = t!(build_lock.write()); + t!(lock.write(&process::id().to_string().as_ref())); + lock } }; } + #[cfg(any(not(any(unix, windows)), target_os = "solaris"))] println!("warning: file locking not supported for target, not locking build directory"); @@ -108,30 +120,3 @@ fn check_version(config: &Config) -> Option { Some(msg) } - -/// Get the PID of the process which took the write lock by -/// parsing `/proc/locks`. -#[cfg(target_os = "linux")] -fn get_lock_owner(f: &std::path::Path) -> Option { - use std::fs::File; - use std::io::{BufRead, BufReader}; - use std::os::unix::fs::MetadataExt; - - let lock_inode = std::fs::metadata(f).ok()?.ino(); - let lockfile = File::open("/proc/locks").ok()?; - BufReader::new(lockfile).lines().find_map(|line| { - // pid--vvvvvv vvvvvvv--- inode - // 21: FLOCK ADVISORY WRITE 359238 08:02:3719774 0 EOF - let line = line.ok()?; - let parts = line.split_whitespace().collect::>(); - let (pid, inode) = (parts[4].parse::().ok()?, &parts[5]); - let inode = inode.rsplit_once(':')?.1.parse::().ok()?; - if inode == lock_inode { Some(pid) } else { None } - }) -} - -#[cfg(not(any(target_os = "linux", target_os = "solaris")))] -fn get_lock_owner(_: &std::path::Path) -> Option { - // FIXME: Implement on other OS's - None -} diff --git a/src/bootstrap/bootstrap.py b/src/bootstrap/bootstrap.py index 5714613cdf51..149350e62a01 100644 --- a/src/bootstrap/bootstrap.py +++ b/src/bootstrap/bootstrap.py @@ -323,6 +323,7 @@ def default_build_triple(verbose): cputype_mapper = { 'BePC': 'i686', 'aarch64': 'aarch64', + 'aarch64eb': 'aarch64', 'amd64': 'x86_64', 'arm64': 'aarch64', 'i386': 'i686', @@ -458,23 +459,51 @@ def unpack_component(download_info): verbose=download_info.verbose, ) -class RustBuild(object): - """Provide all the methods required to build Rust""" +class FakeArgs: + """Used for unit tests to avoid updating all call sites""" def __init__(self): - self.checksums_sha256 = {} - self.stage0_compiler = None - self.download_url = '' self.build = '' self.build_dir = '' self.clean = False - self.config_toml = '' - self.rust_root = '' - self.use_locked_deps = False - self.use_vendored_sources = False self.verbose = False + self.json_output = False + self.color = 'auto' + self.warnings = 'default' + +class RustBuild(object): + """Provide all the methods required to build Rust""" + def __init__(self, config_toml="", args=FakeArgs()): self.git_version = None self.nix_deps_dir = None self._should_fix_bins_and_dylibs = None + self.rust_root = os.path.abspath(os.path.join(__file__, '../../..')) + + self.config_toml = config_toml + + self.clean = args.clean + self.json_output = args.json_output + self.verbose = args.verbose + self.color = args.color + self.warnings = args.warnings + + config_verbose_count = self.get_toml('verbose', 'build') + if config_verbose_count is not None: + self.verbose = max(self.verbose, int(config_verbose_count)) + + self.use_vendored_sources = self.get_toml('vendor', 'build') == 'true' + self.use_locked_deps = self.get_toml('locked-deps', 'build') == 'true' + + build_dir = args.build_dir or self.get_toml('build-dir', 'build') or 'build' + self.build_dir = os.path.abspath(build_dir) + + with open(os.path.join(self.rust_root, "src", "stage0.json")) as f: + data = json.load(f) + self.checksums_sha256 = data["checksums_sha256"] + self.stage0_compiler = Stage0Toolchain(data["compiler"]) + self.download_url = os.getenv("RUSTUP_DIST_SERVER") or data["config"]["dist_server"] + + self.build = args.build or self.build_triple() + def download_toolchain(self): """Fetch the build system for Rust, written in Rust @@ -704,9 +733,10 @@ class RustBuild(object): """Return the path for .rustc-stamp at the given stage >>> rb = RustBuild() + >>> rb.build = "host" >>> rb.build_dir = "build" - >>> rb.rustc_stamp() == os.path.join("build", "stage0", ".rustc-stamp") - True + >>> expected = os.path.join("build", "host", "stage0", ".rustc-stamp") + >>> assert rb.rustc_stamp() == expected, rb.rustc_stamp() """ return os.path.join(self.bin_root(), '.rustc-stamp') @@ -721,15 +751,9 @@ class RustBuild(object): """Return the binary root directory for the given stage >>> rb = RustBuild() - >>> rb.build_dir = "build" - >>> rb.bin_root() == os.path.join("build", "stage0") - True - - When the 'build' property is given should be a nested directory: - >>> rb.build = "devel" - >>> rb.bin_root() == os.path.join("build", "devel", "stage0") - True + >>> expected = os.path.abspath(os.path.join("build", "devel", "stage0")) + >>> assert rb.bin_root() == expected, rb.bin_root() """ subdir = "stage0" return os.path.join(self.build_dir, self.build, subdir) @@ -761,9 +785,12 @@ class RustBuild(object): >>> rb.get_toml("key1") 'true' """ + return RustBuild.get_toml_static(self.config_toml, key, section) + @staticmethod + def get_toml_static(config_toml, key, section=None): cur_section = None - for line in self.config_toml.splitlines(): + for line in config_toml.splitlines(): section_match = re.match(r'^\s*\[(.*)\]\s*$', line) if section_match is not None: cur_section = section_match.group(1) @@ -772,7 +799,7 @@ class RustBuild(object): if match is not None: value = match.group(1) if section is None or section == cur_section: - return self.get_string(value) or value.strip() + return RustBuild.get_string(value) or value.strip() return None def cargo(self): @@ -835,13 +862,23 @@ class RustBuild(object): """ return os.path.join(self.build_dir, "bootstrap", "debug", "bootstrap") - def build_bootstrap(self, color, warnings, verbose_count): + def build_bootstrap(self): """Build bootstrap""" env = os.environ.copy() if "GITHUB_ACTIONS" in env: print("::group::Building bootstrap") else: print("Building bootstrap", file=sys.stderr) + + args = self.build_bootstrap_cmd(env) + # Run this from the source directory so cargo finds .cargo/config + run(args, env=env, verbose=self.verbose, cwd=self.rust_root) + + if "GITHUB_ACTIONS" in env: + print("::endgroup::") + + def build_bootstrap_cmd(self, env): + """For tests.""" build_dir = os.path.join(self.build_dir, "bootstrap") if self.clean and os.path.exists(build_dir): shutil.rmtree(build_dir) @@ -894,10 +931,10 @@ class RustBuild(object): if target_linker is not None: env["RUSTFLAGS"] += " -C linker=" + target_linker env["RUSTFLAGS"] += " -Wrust_2018_idioms -Wunused_lifetimes" - if warnings == "default": + if self.warnings == "default": deny_warnings = self.get_toml("deny-warnings", "rust") != "false" else: - deny_warnings = warnings == "deny" + deny_warnings = self.warnings == "deny" if deny_warnings: env["RUSTFLAGS"] += " -Dwarnings" @@ -908,7 +945,7 @@ class RustBuild(object): self.cargo())) args = [self.cargo(), "build", "--manifest-path", os.path.join(self.rust_root, "src/bootstrap/Cargo.toml")] - args.extend("--verbose" for _ in range(verbose_count)) + args.extend("--verbose" for _ in range(self.verbose)) if self.use_locked_deps: args.append("--locked") if self.use_vendored_sources: @@ -918,20 +955,16 @@ class RustBuild(object): args.append("build-metrics") if self.json_output: args.append("--message-format=json") - if color == "always": + if self.color == "always": args.append("--color=always") - elif color == "never": + elif self.color == "never": args.append("--color=never") try: args += env["CARGOFLAGS"].split() except KeyError: pass - # Run this from the source directory so cargo finds .cargo/config - run(args, env=env, verbose=self.verbose, cwd=self.rust_root) - - if "GITHUB_ACTIONS" in env: - print("::endgroup::") + return args def build_triple(self): """Build triple as in LLVM @@ -981,7 +1014,7 @@ class RustBuild(object): if os.path.exists(cargo_dir): shutil.rmtree(cargo_dir) -def parse_args(): +def parse_args(args): """Parse the command line arguments that the python script needs.""" parser = argparse.ArgumentParser(add_help=False) parser.add_argument('-h', '--help', action='store_true') @@ -994,16 +1027,11 @@ def parse_args(): parser.add_argument('--warnings', choices=['deny', 'warn', 'default'], default='default') parser.add_argument('-v', '--verbose', action='count', default=0) - return parser.parse_known_args(sys.argv)[0] + return parser.parse_known_args(args)[0] def bootstrap(args): """Configure, fetch, build and run the initial bootstrap""" - # Configure initial bootstrap - build = RustBuild() - build.rust_root = os.path.abspath(os.path.join(__file__, '../../..')) - build.verbose = args.verbose != 0 - build.clean = args.clean - build.json_output = args.json_output + rust_root = os.path.abspath(os.path.join(__file__, '../../..')) # Read from `--config`, then `RUST_BOOTSTRAP_CONFIG`, then `./config.toml`, # then `config.toml` in the root directory. @@ -1012,52 +1040,43 @@ def bootstrap(args): if using_default_path: toml_path = 'config.toml' if not os.path.exists(toml_path): - toml_path = os.path.join(build.rust_root, toml_path) + toml_path = os.path.join(rust_root, toml_path) # Give a hard error if `--config` or `RUST_BOOTSTRAP_CONFIG` are set to a missing path, # but not if `config.toml` hasn't been created. if not using_default_path or os.path.exists(toml_path): with open(toml_path) as config: - build.config_toml = config.read() + config_toml = config.read() + else: + config_toml = '' - profile = build.get_toml('profile') + profile = RustBuild.get_toml_static(config_toml, 'profile') if profile is not None: - include_file = 'config.{}.toml'.format(profile) - include_dir = os.path.join(build.rust_root, 'src', 'bootstrap', 'defaults') + # Allows creating alias for profile names, allowing + # profiles to be renamed while maintaining back compatibility + # Keep in sync with `profile_aliases` in config.rs + profile_aliases = { + "user": "dist" + } + include_file = 'config.{}.toml'.format(profile_aliases.get(profile) or profile) + include_dir = os.path.join(rust_root, 'src', 'bootstrap', 'defaults') include_path = os.path.join(include_dir, include_file) - # HACK: This works because `build.get_toml()` returns the first match it finds for a + # HACK: This works because `self.get_toml()` returns the first match it finds for a # specific key, so appending our defaults at the end allows the user to override them with open(include_path) as included_toml: - build.config_toml += os.linesep + included_toml.read() - - verbose_count = args.verbose - config_verbose_count = build.get_toml('verbose', 'build') - if config_verbose_count is not None: - verbose_count = max(args.verbose, int(config_verbose_count)) - - build.use_vendored_sources = build.get_toml('vendor', 'build') == 'true' - build.use_locked_deps = build.get_toml('locked-deps', 'build') == 'true' + config_toml += os.linesep + included_toml.read() + # Configure initial bootstrap + build = RustBuild(config_toml, args) build.check_vendored_status() - build_dir = args.build_dir or build.get_toml('build-dir', 'build') or 'build' - build.build_dir = os.path.abspath(build_dir) - - with open(os.path.join(build.rust_root, "src", "stage0.json")) as f: - data = json.load(f) - build.checksums_sha256 = data["checksums_sha256"] - build.stage0_compiler = Stage0Toolchain(data["compiler"]) - build.download_url = os.getenv("RUSTUP_DIST_SERVER") or data["config"]["dist_server"] - - build.build = args.build or build.build_triple() - if not os.path.exists(build.build_dir): os.makedirs(build.build_dir) # Fetch/build the bootstrap build.download_toolchain() sys.stdout.flush() - build.build_bootstrap(args.color, args.warnings, verbose_count) + build.build_bootstrap() sys.stdout.flush() # Run the bootstrap @@ -1077,7 +1096,7 @@ def main(): if len(sys.argv) > 1 and sys.argv[1] == 'help': sys.argv[1] = '-h' - args = parse_args() + args = parse_args(sys.argv) help_triggered = args.help or len(sys.argv) == 1 # If the user is asking for help, let them know that the whole download-and-build diff --git a/src/bootstrap/bootstrap_test.py b/src/bootstrap/bootstrap_test.py index 5ecda83ee66b..1294ca9df0d0 100644 --- a/src/bootstrap/bootstrap_test.py +++ b/src/bootstrap/bootstrap_test.py @@ -1,4 +1,6 @@ -"""Bootstrap tests""" +"""Bootstrap tests + +Run these with `x test bootstrap`, or `python -m unittest bootstrap_test.py`.""" from __future__ import absolute_import, division, print_function import os @@ -13,6 +15,22 @@ from shutil import rmtree import bootstrap import configure +def serialize_and_parse(configure_args, bootstrap_args=bootstrap.FakeArgs()): + from io import StringIO + + section_order, sections, targets = configure.parse_args(configure_args) + buffer = StringIO() + configure.write_config_toml(buffer, section_order, targets, sections) + build = bootstrap.RustBuild(config_toml=buffer.getvalue(), args=bootstrap_args) + + try: + import tomllib + # Verify this is actually valid TOML. + tomllib.loads(build.config_toml) + except ImportError: + print("warning: skipping TOML validation, need at least python 3.11", file=sys.stderr) + return build + class VerifyTestCase(unittest.TestCase): """Test Case for verify""" @@ -77,58 +95,58 @@ class ProgramOutOfDate(unittest.TestCase): class GenerateAndParseConfig(unittest.TestCase): """Test that we can serialize and deserialize a config.toml file""" - def serialize_and_parse(self, args): - from io import StringIO - - section_order, sections, targets = configure.parse_args(args) - buffer = StringIO() - configure.write_config_toml(buffer, section_order, targets, sections) - build = bootstrap.RustBuild() - build.config_toml = buffer.getvalue() - - try: - import tomllib - # Verify this is actually valid TOML. - tomllib.loads(build.config_toml) - except ImportError: - print("warning: skipping TOML validation, need at least python 3.11", file=sys.stderr) - return build - def test_no_args(self): - build = self.serialize_and_parse([]) + build = serialize_and_parse([]) self.assertEqual(build.get_toml("changelog-seen"), '2') - self.assertEqual(build.get_toml("profile"), 'user') + self.assertEqual(build.get_toml("profile"), 'dist') self.assertIsNone(build.get_toml("llvm.download-ci-llvm")) def test_set_section(self): - build = self.serialize_and_parse(["--set", "llvm.download-ci-llvm"]) + build = serialize_and_parse(["--set", "llvm.download-ci-llvm"]) self.assertEqual(build.get_toml("download-ci-llvm", section="llvm"), 'true') def test_set_target(self): - build = self.serialize_and_parse(["--set", "target.x86_64-unknown-linux-gnu.cc=gcc"]) + build = serialize_and_parse(["--set", "target.x86_64-unknown-linux-gnu.cc=gcc"]) self.assertEqual(build.get_toml("cc", section="target.x86_64-unknown-linux-gnu"), 'gcc') def test_set_top_level(self): - build = self.serialize_and_parse(["--set", "profile=compiler"]) + build = serialize_and_parse(["--set", "profile=compiler"]) self.assertEqual(build.get_toml("profile"), 'compiler') def test_set_codegen_backends(self): - build = self.serialize_and_parse(["--set", "rust.codegen-backends=cranelift"]) + build = serialize_and_parse(["--set", "rust.codegen-backends=cranelift"]) self.assertNotEqual(build.config_toml.find("codegen-backends = ['cranelift']"), -1) - build = self.serialize_and_parse(["--set", "rust.codegen-backends=cranelift,llvm"]) + build = serialize_and_parse(["--set", "rust.codegen-backends=cranelift,llvm"]) self.assertNotEqual(build.config_toml.find("codegen-backends = ['cranelift', 'llvm']"), -1) - build = self.serialize_and_parse(["--enable-full-tools"]) + build = serialize_and_parse(["--enable-full-tools"]) self.assertNotEqual(build.config_toml.find("codegen-backends = ['llvm']"), -1) -if __name__ == '__main__': - SUITE = unittest.TestSuite() - TEST_LOADER = unittest.TestLoader() - SUITE.addTest(doctest.DocTestSuite(bootstrap)) - SUITE.addTests([ - TEST_LOADER.loadTestsFromTestCase(VerifyTestCase), - TEST_LOADER.loadTestsFromTestCase(GenerateAndParseConfig), - TEST_LOADER.loadTestsFromTestCase(ProgramOutOfDate)]) - RUNNER = unittest.TextTestRunner(stream=sys.stdout, verbosity=2) - result = RUNNER.run(SUITE) - sys.exit(0 if result.wasSuccessful() else 1) +class BuildBootstrap(unittest.TestCase): + """Test that we generate the appropriate arguments when building bootstrap""" + + def build_args(self, configure_args=[], args=[], env={}): + env = env.copy() + env["PATH"] = os.environ["PATH"] + + parsed = bootstrap.parse_args(args) + build = serialize_and_parse(configure_args, parsed) + build.build_dir = os.environ["BUILD_DIR"] + build.build = os.environ["BUILD_PLATFORM"] + return build.build_bootstrap_cmd(env), env + + def test_cargoflags(self): + args, _ = self.build_args(env={"CARGOFLAGS": "--timings"}) + self.assertTrue("--timings" in args) + + def test_warnings(self): + for toml_warnings in ['false', 'true', None]: + configure_args = [] + if toml_warnings is not None: + configure_args = ["--set", "rust.deny-warnings=" + toml_warnings] + + _, env = self.build_args(configure_args, args=["--warnings=warn"]) + self.assertFalse("-Dwarnings" in env["RUSTFLAGS"]) + + _, env = self.build_args(configure_args, args=["--warnings=deny"]) + self.assertTrue("-Dwarnings" in env["RUSTFLAGS"]) diff --git a/src/bootstrap/config.rs b/src/bootstrap/config.rs index 8ee63e561ba7..b91275e73e9c 100644 --- a/src/bootstrap/config.rs +++ b/src/bootstrap/config.rs @@ -1129,6 +1129,14 @@ impl Config { }; if let Some(include) = &toml.profile { + // Allows creating alias for profile names, allowing + // profiles to be renamed while maintaining back compatibility + // Keep in sync with `profile_aliases` in bootstrap.py + let profile_aliases = HashMap::from([("user", "dist")]); + let include = match profile_aliases.get(include.as_str()) { + Some(alias) => alias, + None => include.as_str(), + }; let mut include_path = config.src.clone(); include_path.push("src"); include_path.push("bootstrap"); diff --git a/src/bootstrap/config/tests.rs b/src/bootstrap/config/tests.rs index 4de84b543ed9..3bee659abd1c 100644 --- a/src/bootstrap/config/tests.rs +++ b/src/bootstrap/config/tests.rs @@ -1,5 +1,8 @@ +use crate::config::TomlConfig; + use super::{Config, Flags}; use clap::CommandFactory; +use serde::Deserialize; use std::{env, path::Path}; fn parse(config: &str) -> Config { @@ -159,3 +162,19 @@ fn override_toml_duplicate() { |&_| toml::from_str("changelog-seen = 0").unwrap(), ); } + +#[test] +fn profile_user_dist() { + fn get_toml(file: &Path) -> TomlConfig { + let contents = if file.ends_with("config.toml") { + "profile = \"user\"".to_owned() + } else { + assert!(file.ends_with("config.dist.toml")); + std::fs::read_to_string(dbg!(file)).unwrap() + }; + toml::from_str(&contents) + .and_then(|table: toml::Value| TomlConfig::deserialize(table)) + .unwrap() + } + Config::parse_inner(&["check".to_owned()], get_toml); +} diff --git a/src/bootstrap/configure.py b/src/bootstrap/configure.py index a16f77317c82..e8eebdfb5a58 100755 --- a/src/bootstrap/configure.py +++ b/src/bootstrap/configure.py @@ -280,7 +280,7 @@ def parse_args(args): config = {} - set('build.configure-args', sys.argv[1:], config) + set('build.configure-args', args, config) apply_args(known_args, option_checking, config) return parse_example_config(known_args, config) @@ -400,7 +400,9 @@ def parse_example_config(known_args, config): targets = {} top_level_keys = [] - for line in open(rust_dir + '/config.example.toml').read().split("\n"): + with open(rust_dir + '/config.example.toml') as example_config: + example_lines = example_config.read().split("\n") + for line in example_lines: if cur_section is None: if line.count('=') == 1: top_level_key = line.split('=')[0] @@ -435,7 +437,7 @@ def parse_example_config(known_args, config): targets[target][0] = targets[target][0].replace("x86_64-unknown-linux-gnu", "'{}'".format(target) if "." in target else target) if 'profile' not in config: - set('profile', 'user', config) + set('profile', 'dist', config) configure_file(sections, top_level_keys, targets, config) return section_order, sections, targets diff --git a/src/bootstrap/defaults/config.user.toml b/src/bootstrap/defaults/config.dist.toml similarity index 100% rename from src/bootstrap/defaults/config.user.toml rename to src/bootstrap/defaults/config.dist.toml diff --git a/src/bootstrap/doc.rs b/src/bootstrap/doc.rs index 8592895423e8..1ac52dffe583 100644 --- a/src/bootstrap/doc.rs +++ b/src/bootstrap/doc.rs @@ -222,7 +222,7 @@ impl Step for TheBook { let shared_assets = builder.ensure(SharedAssets { target }); // build the redirect pages - builder.info(&format!("Documenting book redirect pages ({})", target)); + builder.msg_doc(compiler, "book redirect pages", target); for file in t!(fs::read_dir(builder.src.join(&relative_path).join("redirects"))) { let file = t!(file); let path = file.path(); @@ -306,7 +306,7 @@ impl Step for Standalone { fn run(self, builder: &Builder<'_>) { let target = self.target; let compiler = self.compiler; - builder.info(&format!("Documenting standalone ({})", target)); + builder.msg_doc(compiler, "standalone", target); let out = builder.doc_out(target); t!(fs::create_dir_all(&out)); @@ -562,7 +562,7 @@ fn doc_std( let description = format!("library{} in {} format", crate_description(&requested_crates), format.as_str()); - let _guard = builder.msg(Kind::Doc, stage, &description, compiler.host, target); + let _guard = builder.msg_doc(compiler, &description, target); let target_doc_dir_name = if format == DocumentationFormat::JSON { "json-doc" } else { "doc" }; let target_dir = @@ -804,14 +804,7 @@ macro_rules! tool_doc { SourceType::Submodule }; - builder.info( - &format!( - "Documenting stage{} {} ({})", - stage, - stringify!($tool).to_lowercase(), - target, - ), - ); + builder.msg_doc(compiler, stringify!($tool).to_lowercase(), target); // Symlink compiler docs to the output directory of rustdoc documentation. let out_dirs = [ diff --git a/src/bootstrap/lib.rs b/src/bootstrap/lib.rs index d389b568f563..c960053d7a0f 100644 --- a/src/bootstrap/lib.rs +++ b/src/bootstrap/lib.rs @@ -1009,6 +1009,15 @@ impl Build { self.msg(Kind::Check, self.config.stage, what, self.config.build, target) } + fn msg_doc( + &self, + compiler: Compiler, + what: impl Display, + target: impl Into> + Copy, + ) -> Option { + self.msg(Kind::Doc, compiler.stage, what, compiler.host, target.into()) + } + fn msg_build( &self, compiler: Compiler, diff --git a/src/bootstrap/setup.rs b/src/bootstrap/setup.rs index 7eb70de91f84..34c6ccf13657 100644 --- a/src/bootstrap/setup.rs +++ b/src/bootstrap/setup.rs @@ -20,7 +20,7 @@ pub enum Profile { Codegen, Library, Tools, - User, + Dist, None, } @@ -43,7 +43,7 @@ impl Profile { pub fn all() -> impl Iterator { use Profile::*; // N.B. these are ordered by how they are displayed, not alphabetically - [Library, Compiler, Codegen, Tools, User, None].iter().copied() + [Library, Compiler, Codegen, Tools, Dist, None].iter().copied() } pub fn purpose(&self) -> String { @@ -53,7 +53,7 @@ impl Profile { Compiler => "Contribute to the compiler itself", Codegen => "Contribute to the compiler, and also modify LLVM or codegen", Tools => "Contribute to tools which depend on the compiler, but do not modify it directly (e.g. rustdoc, clippy, miri)", - User => "Install Rust from source", + Dist => "Install Rust from source", None => "Do not modify `config.toml`" } .to_string() @@ -73,7 +73,7 @@ impl Profile { Profile::Codegen => "codegen", Profile::Library => "library", Profile::Tools => "tools", - Profile::User => "user", + Profile::Dist => "dist", Profile::None => "none", } } @@ -87,7 +87,7 @@ impl FromStr for Profile { "lib" | "library" => Ok(Profile::Library), "compiler" => Ok(Profile::Compiler), "llvm" | "codegen" => Ok(Profile::Codegen), - "maintainer" | "user" => Ok(Profile::User), + "maintainer" | "dist" | "user" => Ok(Profile::Dist), "tools" | "tool" | "rustdoc" | "clippy" | "miri" | "rustfmt" | "rls" => { Ok(Profile::Tools) } @@ -160,7 +160,7 @@ pub fn setup(config: &Config, profile: Profile) { "test src/tools/rustfmt", ], Profile::Library => &["check", "build", "test library/std", "doc"], - Profile::User => &["dist", "build"], + Profile::Dist => &["dist", "build"], }; println!(); @@ -170,7 +170,7 @@ pub fn setup(config: &Config, profile: Profile) { println!("- `x.py {}`", cmd); } - if profile != Profile::User { + if profile != Profile::Dist { println!( "For more suggestions, see https://rustc-dev-guide.rust-lang.org/building/suggested.html" ); @@ -582,7 +582,7 @@ fn create_vscode_settings_maybe(config: &Config) -> io::Result<()> { Some(false) => { // exists and is not current version or outdated, so back it up let mut backup = vscode_settings.clone(); - backup.set_extension("bak"); + backup.set_extension("json.bak"); eprintln!("warning: copying `settings.json` to `settings.json.bak`"); fs::copy(&vscode_settings, &backup)?; "Updated" diff --git a/src/bootstrap/test.rs b/src/bootstrap/test.rs index 873ed61daf33..ec447a1cd73b 100644 --- a/src/bootstrap/test.rs +++ b/src/bootstrap/test.rs @@ -1832,11 +1832,13 @@ note: if you're sure you want to do this, please open an issue as to why. In the builder, ); - builder.info(&format!( - "Check compiletest suite={} mode={} ({} -> {})", - suite, mode, &compiler.host, target - )); - let _time = util::timeit(&builder); + let _group = builder.msg( + Kind::Test, + compiler.stage, + &format!("compiletest suite={suite} mode={mode}"), + compiler.host, + target, + ); crate::render_tests::try_run_tests(builder, &mut cmd, false); if let Some(compare_mode) = compare_mode { @@ -2664,7 +2666,12 @@ impl Step for Bootstrap { /// Tests the build system itself. fn run(self, builder: &Builder<'_>) { let mut check_bootstrap = Command::new(&builder.python()); - check_bootstrap.arg("bootstrap_test.py").current_dir(builder.src.join("src/bootstrap/")); + check_bootstrap + .args(["-m", "unittest", "bootstrap_test.py"]) + .env("BUILD_DIR", &builder.out) + .env("BUILD_PLATFORM", &builder.build.build.triple) + .current_dir(builder.src.join("src/bootstrap/")) + .args(builder.config.test_args()); try_run(builder, &mut check_bootstrap).unwrap(); let host = builder.config.build; diff --git a/src/ci/docker/host-x86_64/dist-various-2/build-wasi-toolchain.sh b/src/ci/docker/host-x86_64/dist-various-2/build-wasi-toolchain.sh index 5fbce36c39d2..b867db6a1b5c 100755 --- a/src/ci/docker/host-x86_64/dist-various-2/build-wasi-toolchain.sh +++ b/src/ci/docker/host-x86_64/dist-various-2/build-wasi-toolchain.sh @@ -10,7 +10,7 @@ bin="$PWD/clang+llvm-15.0.6-x86_64-linux-gnu-ubuntu-18.04/bin" git clone https://github.com/WebAssembly/wasi-libc cd wasi-libc -git reset --hard 4362b1885fd369e042a7c0ecd8df3b6cd47fb4e8 +git reset --hard 7018e24d8fe248596819d2e884761676f3542a04 make -j$(nproc) \ CC="$bin/clang" \ NM="$bin/llvm-nm" \ diff --git a/src/ci/github-actions/ci.yml b/src/ci/github-actions/ci.yml index a9e42e4a0a0d..8907d643182d 100644 --- a/src/ci/github-actions/ci.yml +++ b/src/ci/github-actions/ci.yml @@ -147,13 +147,6 @@ x--expand-yaml-anchors--remove: run: src/ci/scripts/verify-channel.sh <<: *step - - name: configure GitHub Actions to kill the build when outdated - uses: rust-lang/simpleinfra/github-actions/cancel-outdated-builds@master - with: - github_token: "${{ secrets.github_token }}" - if: success() && !env.SKIP_JOB && github.ref != 'refs/heads/try' && github.ref != 'refs/heads/try-perf' - <<: *step - - name: collect CPU statistics run: src/ci/scripts/collect-cpu-stats.sh <<: *step @@ -305,10 +298,14 @@ defaults: # shell is PowerShell.) shell: bash +concurrency: + # For a given workflow, if we push to the same PR, cancel all previous builds on that PR. + # If the push is not attached to a PR, we will cancel all builds related to the same commit SHA. + group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }} + cancel-in-progress: true + jobs: pr: - permissions: - actions: write # for rust-lang/simpleinfra/github-actions/cancel-outdated-builds <<: *base-ci-job name: PR - ${{ matrix.name }} env: @@ -331,8 +328,6 @@ jobs: <<: *job-linux-16c auto: - permissions: - actions: write # for rust-lang/simpleinfra/github-actions/cancel-outdated-builds <<: *base-ci-job name: auto - ${{ matrix.name }} env: @@ -734,8 +729,6 @@ jobs: <<: *job-windows-8c try: - permissions: - actions: write # for rust-lang/simpleinfra/github-actions/cancel-outdated-builds <<: *base-ci-job name: try - ${{ matrix.name }} env: diff --git a/src/doc/book b/src/doc/book index 8fa6b854d515..21cf840842bd 160000 --- a/src/doc/book +++ b/src/doc/book @@ -1 +1 @@ -Subproject commit 8fa6b854d515506d825390fe0d817f5ef0c89350 +Subproject commit 21cf840842bdf768a798869f06373c96c1cc5122 diff --git a/src/doc/nomicon b/src/doc/nomicon index b5f018fb5930..c369e4b48933 160000 --- a/src/doc/nomicon +++ b/src/doc/nomicon @@ -1 +1 @@ -Subproject commit b5f018fb5930cb733b0a8aaf2eed975d4771e74d +Subproject commit c369e4b489332f8721fbae630354fa83385d457d diff --git a/src/doc/reference b/src/doc/reference index 553d99b02a53..5ca365eac678 160000 --- a/src/doc/reference +++ b/src/doc/reference @@ -1 +1 @@ -Subproject commit 553d99b02a53b4133a40d5bd2e19958c67487c00 +Subproject commit 5ca365eac678cb0d41a20b3204546d6ed70c7171 diff --git a/src/doc/rust-by-example b/src/doc/rust-by-example index 8ee9528b72b9..57636d692676 160000 --- a/src/doc/rust-by-example +++ b/src/doc/rust-by-example @@ -1 +1 @@ -Subproject commit 8ee9528b72b927cff8fd32346db8bbd1198816f0 +Subproject commit 57636d6926762861f34e030d52ca25a71e95e5bf diff --git a/src/doc/rustc-dev-guide b/src/doc/rustc-dev-guide index f1e637883faf..17fe3e948498 160000 --- a/src/doc/rustc-dev-guide +++ b/src/doc/rustc-dev-guide @@ -1 +1 @@ -Subproject commit f1e637883fafeb83bdd5906ee7f467e4d35b7337 +Subproject commit 17fe3e948498c50e208047a750f17d6a8d89669b diff --git a/src/doc/rustc/src/SUMMARY.md b/src/doc/rustc/src/SUMMARY.md index 1e17a90a8428..f8af26326a73 100644 --- a/src/doc/rustc/src/SUMMARY.md +++ b/src/doc/rustc/src/SUMMARY.md @@ -40,6 +40,7 @@ - [riscv32imac-unknown-xous-elf](platform-support/riscv32imac-unknown-xous-elf.md) - [*-pc-windows-gnullvm](platform-support/pc-windows-gnullvm.md) - [\*-nto-qnx-\*](platform-support/nto-qnx.md) + - [\*-unknown-netbsd\*](platform-support/netbsd.md) - [*-unknown-openbsd](platform-support/openbsd.md) - [\*-unknown-uefi](platform-support/unknown-uefi.md) - [wasm64-unknown-unknown](platform-support/wasm64-unknown-unknown.md) diff --git a/src/doc/rustc/src/platform-support.md b/src/doc/rustc/src/platform-support.md index 62f628f82293..6d1729e57b10 100644 --- a/src/doc/rustc/src/platform-support.md +++ b/src/doc/rustc/src/platform-support.md @@ -224,13 +224,14 @@ target | std | host | notes `aarch64-unknown-freebsd` | ✓ | ✓ | ARM64 FreeBSD `aarch64-unknown-hermit` | ✓ | | ARM64 HermitCore `aarch64-unknown-linux-gnu_ilp32` | ✓ | ✓ | ARM64 Linux (ILP32 ABI) -`aarch64-unknown-netbsd` | ✓ | ✓ | +[`aarch64-unknown-netbsd`](platform-support/netbsd.md) | ✓ | ✓ | ARM64 NetBSD [`aarch64-unknown-openbsd`](platform-support/openbsd.md) | ✓ | ✓ | ARM64 OpenBSD `aarch64-unknown-redox` | ? | | ARM64 Redox OS `aarch64-uwp-windows-msvc` | ? | | `aarch64-wrs-vxworks` | ? | | `aarch64_be-unknown-linux-gnu_ilp32` | ✓ | ✓ | ARM64 Linux (big-endian, ILP32 ABI) `aarch64_be-unknown-linux-gnu` | ✓ | ✓ | ARM64 Linux (big-endian) +[`aarch64_be-unknown-netbsd`](platform-support/netbsd.md) | ✓ | ✓ | ARM64 NetBSD (big-endian) [`arm64_32-apple-watchos`](platform-support/apple-watchos.md) | ✓ | | ARM Apple WatchOS 64-bit with 32-bit pointers [`armeb-unknown-linux-gnueabi`](platform-support/armeb-unknown-linux-gnueabi.md) | ✓ | ? | ARM BE8 the default ARM big-endian architecture since [ARMv6](https://developer.arm.com/documentation/101754/0616/armlink-Reference/armlink-Command-line-Options/--be8?lang=en). `armv4t-none-eabi` | * | | ARMv4T A32 @@ -238,7 +239,7 @@ target | std | host | notes [`armv5te-none-eabi`](platform-support/armv5te-none-eabi.md) | * | | ARMv5TE A32 `armv5te-unknown-linux-uclibceabi` | ? | | ARMv5TE Linux with uClibc `armv6-unknown-freebsd` | ✓ | ✓ | ARMv6 FreeBSD -`armv6-unknown-netbsd-eabihf` | ? | | +[`armv6-unknown-netbsd-eabihf`](platform-support/netbsd.md) | ✓ | ✓ | ARMv6 NetBSD w/hard-float [`armv6k-nintendo-3ds`](platform-support/armv6k-nintendo-3ds.md) | ? | | ARMv6K Nintendo 3DS, Horizon (Requires devkitARM toolchain) `armv7-apple-ios` | ✓ | | ARMv7 iOS, Cortex-a8 [`armv7-sony-vita-newlibeabihf`](platform-support/armv7-sony-vita-newlibeabihf.md) | ? | | ARM Cortex-A9 Sony PlayStation Vita (requires VITASDK toolchain) @@ -246,7 +247,7 @@ target | std | host | notes [`armv7-unknown-linux-uclibceabi`](platform-support/armv7-unknown-linux-uclibceabi.md) | ✓ | ✓ | ARMv7 Linux with uClibc, softfloat [`armv7-unknown-linux-uclibceabihf`](platform-support/armv7-unknown-linux-uclibceabihf.md) | ✓ | ? | ARMv7 Linux with uClibc, hardfloat `armv7-unknown-freebsd` | ✓ | ✓ | ARMv7 FreeBSD -`armv7-unknown-netbsd-eabihf` | ✓ | ✓ | +[`armv7-unknown-netbsd-eabihf`](platform-support/netbsd.md) | ✓ | ✓ | ARMv7 NetBSD w/hard-float `armv7-wrs-vxworks-eabihf` | ? | | [`armv7a-kmc-solid_asp3-eabi`](platform-support/kmc-solid.md) | ✓ | | ARM SOLID with TOPPERS/ASP3 [`armv7a-kmc-solid_asp3-eabihf`](platform-support/kmc-solid.md) | ✓ | | ARM SOLID with TOPPERS/ASP3, hardfloat @@ -262,7 +263,7 @@ target | std | host | notes `i686-apple-darwin` | ✓ | ✓ | 32-bit macOS (10.7+, Lion+) `i686-pc-windows-msvc` | * | | 32-bit Windows XP support `i686-unknown-haiku` | ✓ | ✓ | 32-bit Haiku -`i686-unknown-netbsd` | ✓ | ✓ | NetBSD/i386 with SSE2 +[`i686-unknown-netbsd`](platform-support/netbsd.md) | ✓ | ✓ | NetBSD/i386 with SSE2 [`i686-unknown-openbsd`](platform-support/openbsd.md) | ✓ | ✓ | 32-bit OpenBSD `i686-uwp-windows-gnu` | ? | | `i686-uwp-windows-msvc` | ? | | @@ -283,7 +284,7 @@ target | std | host | notes `msp430-none-elf` | * | | 16-bit MSP430 microcontrollers `powerpc-unknown-linux-gnuspe` | ✓ | | PowerPC SPE Linux `powerpc-unknown-linux-musl` | ? | | -`powerpc-unknown-netbsd` | ✓ | ✓ | +[`powerpc-unknown-netbsd`](platform-support/netbsd.md) | ✓ | ✓ | NetBSD 32-bit powerpc systems `powerpc-unknown-openbsd` | ? | | `powerpc-wrs-vxworks-spe` | ? | | `powerpc-wrs-vxworks` | ? | | @@ -307,7 +308,7 @@ target | std | host | notes [`riscv64gc-unknown-openbsd`](platform-support/openbsd.md) | ✓ | ✓ | OpenBSD/riscv64 `s390x-unknown-linux-musl` | | | S390x Linux (kernel 3.2, MUSL) `sparc-unknown-linux-gnu` | ✓ | | 32-bit SPARC Linux -`sparc64-unknown-netbsd` | ✓ | ✓ | NetBSD/sparc64 +[`sparc64-unknown-netbsd`](platform-support/netbsd.md) | ✓ | ✓ | NetBSD/sparc64 [`sparc64-unknown-openbsd`](platform-support/openbsd.md) | ✓ | ✓ | OpenBSD/sparc64 `thumbv4t-none-eabi` | * | | ARMv4T T32 [`thumbv5te-none-eabi`](platform-support/armv5te-none-eabi.md) | * | | ARMv5TE T32 diff --git a/src/doc/rustc/src/platform-support/esp-idf.md b/src/doc/rustc/src/platform-support/esp-idf.md index 4bbe35709b08..8f630fa152c4 100644 --- a/src/doc/rustc/src/platform-support/esp-idf.md +++ b/src/doc/rustc/src/platform-support/esp-idf.md @@ -13,10 +13,12 @@ Targets for the [ESP-IDF](https://github.com/espressif/esp-idf) development fram The target names follow this format: `$ARCH-esp-espidf`, where `$ARCH` specifies the target processor architecture. The following targets are currently defined: -| Target name | Target CPU(s) | Minimum ESP-IDF version | -|--------------------------------|-----------------------|-------------------------| -| `riscv32imc-esp-espidf` | [ESP32-C3](https://www.espressif.com/en/products/socs/esp32-c3) | `v4.3` | -| `riscv32imac-esp-espidf` | [ESP32-C6](https://www.espressif.com/en/products/socs/esp32-c6) | `v5.1` | +| Target name | Target CPU(s) | Minimum ESP-IDF version | +| ------------------------ | --------------------------------------------------------------- | ----------------------- | +| `riscv32imc-esp-espidf` | [ESP32-C2](https://www.espressif.com/en/products/socs/esp32-c2) | `v5.0` | +| `riscv32imc-esp-espidf` | [ESP32-C3](https://www.espressif.com/en/products/socs/esp32-c3) | `v4.3` | +| `riscv32imac-esp-espidf` | [ESP32-C6](https://www.espressif.com/en/products/socs/esp32-c6) | `v5.1` | +| `riscv32imac-esp-espidf` | [ESP32-H2](https://www.espressif.com/en/products/socs/esp32-h2) | `v5.1` | It is recommended to use the latest ESP-IDF stable release if possible. diff --git a/src/doc/rustc/src/platform-support/loongarch-linux.md b/src/doc/rustc/src/platform-support/loongarch-linux.md index 999e71f80285..17e85590f2c1 100644 --- a/src/doc/rustc/src/platform-support/loongarch-linux.md +++ b/src/doc/rustc/src/platform-support/loongarch-linux.md @@ -28,9 +28,9 @@ While the integer base ABI is implied by the machine field, the floating po ## Target maintainers -- [ZHAI Xiaojuan](https://github.com/zhaixiaojuan) `zhaixiaojuan@loongson.cn` - [WANG Rui](https://github.com/heiher) `wangrui@loongson.cn` - [ZHAI Xiang](https://github.com/xiangzhai) `zhaixiang@loongson.cn` +- [ZHAI Xiaojuan](https://github.com/zhaixiaojuan) `zhaixiaojuan@loongson.cn` - [WANG Xuerui](https://github.com/xen0n) `git@xen0n.name` ## Requirements diff --git a/src/doc/rustc/src/platform-support/netbsd.md b/src/doc/rustc/src/platform-support/netbsd.md new file mode 100644 index 000000000000..a1969524a20e --- /dev/null +++ b/src/doc/rustc/src/platform-support/netbsd.md @@ -0,0 +1,107 @@ +# \*-unknown-netbsd + +**Tier: 3** + +[NetBSD] multi-platform 4.4BSD-based UNIX-like operating system. + +[NetBSD]: https://www.NetBSD.org/ + +The target names follow this format: `$ARCH-unknown-netbsd{-$SUFFIX}`, +where `$ARCH` specifies the target processor architecture and +`-$SUFFIX` (optional) might indicate the ABI. The following targets +are currently defined running NetBSD: + +| Target name | NetBSD Platform | +|--------------------------------|-----------------| +| `amd64-unknown-netbsd` | [amd64 / x86_64 systems](https://wiki.netbsd.org/ports/amd64/) | +| `armv7-unknown-netbsd-eabihf` | [32-bit ARMv7 systems with hard-float](https://wiki.netbsd.org/ports/evbarm/) | +| `armv6-unknown-netbsd-eabihf` | [32-bit ARMv6 systems with hard-float](https://wiki.netbsd.org/ports/evbarm/) | +| `aarch64-unknown-netbsd` | [64-bit ARM systems, little-endian](https://wiki.netbsd.org/ports/evbarm/) | +| `aarch64_be-unknown-netbsd` | [64-bit ARM systems, big-endian](https://wiki.netbsd.org/ports/evbarm/) | +| `i586-unknown-netbsd` | [32-bit i386, restricted to Pentium](https://wiki.netbsd.org/ports/i386/) | +| `i686-unknown-netbsd` | [32-bit i386 with SSE](https://wiki.netbsd.org/ports/i386/) | +| `mipsel-unknown-netbsd` | [32-bit mips, requires mips32 cpu support](https://wiki.netbsd.org/ports/evbmips/) | +| `powerpc-unknown-netbsd` | [Various 32-bit PowerPC systems, e.g. MacPPC](https://wiki.netbsd.org/ports/macppc/) | +| `sparc64-unknown-netbsd` | [Sun UltraSPARC systems](https://wiki.netbsd.org/ports/sparc64/) | + +All use the "native" `stdc++` library which goes along with the natively +supplied GNU C++ compiler for the given OS version. Many of the bootstraps +are built for NetBSD 9.x, although some exceptions exist (some +are built for NetBSD 8.x but also work on newer OS versions). + + +## Designated Developers + +- [@he32](https://github.com/he32), `he@NetBSD.org` +- [NetBSD/pkgsrc-wip's rust](https://github.com/NetBSD/pkgsrc-wip/blob/master/rust/Makefile) maintainer (see MAINTAINER variable). This package is part of "pkgsrc work-in-progress" and is used for deployment and testing of new versions of rust +- [NetBSD's pkgsrc lang/rust](https://github.com/NetBSD/pkgsrc/tree/trunk/lang/rust) for the "proper" package in pkgsrc. +- [NetBSD's pkgsrc lang/rust-bin](https://github.com/NetBSD/pkgsrc/tree/trunk/lang/rust-bin) which re-uses the bootstrap kit as a binary distribution and therefore avoids the rather protracted native build time of rust itself + +Fallback to pkgsrc-users@NetBSD.org, or fault reporting via NetBSD's +bug reporting system. + +## Requirements + +The `amd64-unknown-netbsd` artifacts is being distributed by the +rust project. + +The other targets are built by the designated developers (see above), +and the targets are initially cross-compiled, but many if not most +of them are also built natively as part of testing. + + +## Building + +The default build mode for the packages is a native build. + + +## Cross-compilation + +These targets can be cross-compiled, and we do that via the pkgsrc +package(s). + +Cross-compilation typically requires the "tools" and "dest" trees +resulting from a normal cross-build of NetBSD itself, ref. our main +build script, `build.sh`. + +See e.g. [do-cross.mk +Makefile](https://github.com/NetBSD/pkgsrc/tree/trunk/lang/rust/do-cross.mk) +for the Makefile used to cross-build all the above NetBSD targets +(except for the `amd64` target). + +The major option for the rust build is whether to build rust with +the LLVM rust carries in its distribution, or use the LLVM package +installed from pkgsrc. The `PKG_OPTIONS.rust` option is +`rust-internal-llvm`, ref. [the rust package's options.mk make +fragment](https://github.com/NetBSD/pkgsrc/blob/trunk/lang/rust/options.mk). +It defaults to being set for a few of the above platforms, for +various reasons (see comments), but is otherwise unset and therefore +indicates use of the pkgsrc LLVM. + + +## Testing + +The Rust testsuite could presumably be run natively. + +For the systems where the maintainer can build natively, the rust +compiler itself is re-built natively. This involves the rust compiler +being re-built with the newly self-built rust compiler, so excercises +the result quite extensively. + +Additionally, for some systems we build `librsvg`, and for the more +capable systems we build and test `firefox` (amd64, i386, aarch64). + + +## Building Rust programs + +Rust ships pre-compiled artifacts for the `amd64-unknown-netbsd` +target. + +For the other systems mentioned above, using the `pkgsrc` route is +probably the easiest, possibly via the `rust-bin` package to save +time, see the `RUST_TYPE` variable from the `rust.mk` Makefile +fragment. + +The pkgsrc rust package has a few files to assist with building +pkgsrc packages written in rust, ref. the `rust.mk` and `cargo.mk` +Makefile fragments in the `lang/rust` package. diff --git a/src/doc/style-guide/src/statements.md b/src/doc/style-guide/src/statements.md index 62a5a032f072..9bc521e1c7ba 100644 --- a/src/doc/style-guide/src/statements.md +++ b/src/doc/style-guide/src/statements.md @@ -103,22 +103,69 @@ let Foo { #### else blocks (let-else statements) -If a let statement contains an `else` component, also known as a let-else statement, -then the `else` component should be formatted according to the same rules as the `else` block -in [control flow expressions (i.e. if-else, and if-let-else expressions)](./expressions.md#control-flow-expressions). -Apply the same formatting rules to the components preceding -the `else` block (i.e. the `let pattern: Type = initializer_expr ...` portion) -as described [above](#let-statements) +A let statement can contain an `else` component, making it a let-else statement. +In this case, always apply the same formatting rules to the components preceding +the `else` block (i.e. the `let pattern: Type = initializer_expr` portion) +as described [for other let statements](#let-statements). -Similarly to if-else expressions, if the initializer -expression is multi-lined, then the `else` keyword and opening brace of the block (i.e. `else {`) -should be put on the same line as the end of the initializer -expression with a preceding space if all the following are true: +The entire let-else statement may be formatted on a single line if all the +following are true: + +* the entire statement is *short* +* the `else` block contains only a single-line expression and no statements +* the `else` block contains no comments +* the let statement components preceding the `else` block can be formatted on a single line + +```rust +let Some(1) = opt else { return }; +``` + +Formatters may allow users to configure the value of the threshold +used to determine whether a let-else statement is *short*. + +Otherwise, the let-else statement requires some line breaks. + +If breaking a let-else statement across multiple lines, never break between the +`else` and the `{`, and always break before the `}`. + +If the let statement components preceding the `else` can be formatted on a +single line, but the let-else does not qualify to be placed entirely on a +single line, put the `else {` on the same line as the initializer expression, +with a space between them, then break the line after the `{`. Indent the +closing `}` to match the `let`, and indent the contained block one step +further. + +```rust +let Some(1) = opt else { + return; +}; + +let Some(1) = opt else { + // nope + return +}; +``` + +If the let statement components preceding the `else` can be formatted on a +single line, but the `else {` does not fit on the same line, break the line +before the `else`. + +```rust + let Some(x) = some_really_really_really_really_really_really_really_really_really_long_name + else { + return; + }; +``` + +If the initializer expression is multi-line, the `else` keyword and opening +brace of the block (i.e. `else {`) should be put on the same line as the end of +the initializer expression, with a space between them, if all the following are +true: * The initializer expression ends with one or more closing parentheses, square brackets, and/or braces * There is nothing else on that line -* That line is not indented beyond the indent of the first line containing the `let` keyword +* That line has the same indentation level as the initial `let` keyword. For example: @@ -135,7 +182,9 @@ let Some(x) = y.foo( } ``` -Otherwise, the `else` keyword and opening brace should be placed on the next line after the end of the initializer expression, and should not be indented (the `else` keyword should be aligned with the `let` keyword). +Otherwise, the `else` keyword and opening brace should be placed on the next +line after the end of the initializer expression, and the `else` keyword should +have the same indentation level as the `let` keyword. For example: @@ -155,11 +204,6 @@ fn main() { return }; - let Some(x) = some_really_really_really_really_really_really_really_really_really_long_name - else { - return; - }; - let Some(aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa) = bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb else { @@ -168,31 +212,6 @@ fn main() { } ``` -##### Single line let-else statements - -The entire let-else statement may be formatted on a single line if all the following are true: - -* the entire statement is *short* -* the `else` block contains a single-line expression and no statements -* the `else` block contains no comments -* the let statement components preceding the `else` block can be formatted on a single line - -```rust -let Some(1) = opt else { return }; - -let Some(1) = opt else { - return; -}; - -let Some(1) = opt else { - // nope - return -}; -``` - -Formatters may allow users to configure the value of the threshold -used to determine whether a let-else statement is *short*. - ### Macros in statement position A macro use in statement position should use parentheses or square brackets as diff --git a/src/etc/test-float-parse/runtests.py b/src/etc/test-float-parse/runtests.py index cf7279534dc8..cc5e31a051fc 100755 --- a/src/etc/test-float-parse/runtests.py +++ b/src/etc/test-float-parse/runtests.py @@ -127,7 +127,7 @@ def write_errors(): if not have_seen_error: have_seen_error = True msg("Something is broken:", *args) - msg("Future errors logged to errors.txt") + msg("Future errors will be logged to errors.txt") exit_status = 101 diff --git a/src/librustdoc/clean/auto_trait.rs b/src/librustdoc/clean/auto_trait.rs index 492b0b795577..92bae551644b 100644 --- a/src/librustdoc/clean/auto_trait.rs +++ b/src/librustdoc/clean/auto_trait.rs @@ -317,14 +317,14 @@ where lifetime_predicates } - fn extract_for_generics(&self, pred: ty::Predicate<'tcx>) -> FxHashSet { + fn extract_for_generics(&self, pred: ty::Clause<'tcx>) -> FxHashSet { let bound_predicate = pred.kind(); let tcx = self.cx.tcx; let regions = match bound_predicate.skip_binder() { - ty::PredicateKind::Clause(ty::ClauseKind::Trait(poly_trait_pred)) => { + ty::ClauseKind::Trait(poly_trait_pred) => { tcx.collect_referenced_late_bound_regions(&bound_predicate.rebind(poly_trait_pred)) } - ty::PredicateKind::Clause(ty::ClauseKind::Projection(poly_proj_pred)) => { + ty::ClauseKind::Projection(poly_proj_pred) => { tcx.collect_referenced_late_bound_regions(&bound_predicate.rebind(poly_proj_pred)) } _ => return FxHashSet::default(), @@ -449,9 +449,7 @@ where .filter(|p| { !orig_bounds.contains(p) || match p.kind().skip_binder() { - ty::PredicateKind::Clause(ty::ClauseKind::Trait(pred)) => { - pred.def_id() == sized_trait - } + ty::ClauseKind::Trait(pred) => pred.def_id() == sized_trait, _ => false, } }) diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index f86c32158e0b..b2f9c0bcceaa 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -326,36 +326,24 @@ fn clean_where_predicate<'tcx>( } pub(crate) fn clean_predicate<'tcx>( - predicate: ty::Predicate<'tcx>, + predicate: ty::Clause<'tcx>, cx: &mut DocContext<'tcx>, ) -> Option { let bound_predicate = predicate.kind(); match bound_predicate.skip_binder() { - ty::PredicateKind::Clause(ty::ClauseKind::Trait(pred)) => { - clean_poly_trait_predicate(bound_predicate.rebind(pred), cx) - } - ty::PredicateKind::Clause(ty::ClauseKind::RegionOutlives(pred)) => { - clean_region_outlives_predicate(pred) - } - ty::PredicateKind::Clause(ty::ClauseKind::TypeOutlives(pred)) => { + ty::ClauseKind::Trait(pred) => clean_poly_trait_predicate(bound_predicate.rebind(pred), cx), + ty::ClauseKind::RegionOutlives(pred) => clean_region_outlives_predicate(pred), + ty::ClauseKind::TypeOutlives(pred) => { clean_type_outlives_predicate(bound_predicate.rebind(pred), cx) } - ty::PredicateKind::Clause(ty::ClauseKind::Projection(pred)) => { + ty::ClauseKind::Projection(pred) => { Some(clean_projection_predicate(bound_predicate.rebind(pred), cx)) } // FIXME(generic_const_exprs): should this do something? - ty::PredicateKind::Clause(ty::ClauseKind::ConstEvaluatable(..)) => None, - ty::PredicateKind::Clause(ty::ClauseKind::WellFormed(..)) => None, - ty::PredicateKind::Clause(ty::ClauseKind::ConstArgHasType(..)) => None, - - ty::PredicateKind::Subtype(..) - | ty::PredicateKind::AliasRelate(..) - | ty::PredicateKind::Coerce(..) - | ty::PredicateKind::ObjectSafe(..) - | ty::PredicateKind::ClosureKind(..) - | ty::PredicateKind::ConstEquate(..) - | ty::PredicateKind::Ambiguous - | ty::PredicateKind::TypeWellFormedFromEnv(..) => panic!("not user writable"), + ty::ClauseKind::ConstEvaluatable(..) + | ty::ClauseKind::WellFormed(..) + | ty::ClauseKind::ConstArgHasType(..) + | ty::ClauseKind::TypeWellFormedFromEnv(..) => None, } } @@ -791,10 +779,10 @@ fn clean_ty_generics<'tcx>( }) .collect::>(); - // param index -> [(trait DefId, associated type name & generics, type, higher-ranked params)] + // param index -> [(trait DefId, associated type name & generics, term, higher-ranked params)] let mut impl_trait_proj = FxHashMap::< u32, - Vec<(DefId, PathSegment, ty::Binder<'_, Ty<'_>>, Vec)>, + Vec<(DefId, PathSegment, ty::Binder<'_, ty::Term<'_>>, Vec)>, >::default(); let where_predicates = preds @@ -805,19 +793,17 @@ fn clean_ty_generics<'tcx>( let param_idx = (|| { let bound_p = p.kind(); match bound_p.skip_binder() { - ty::PredicateKind::Clause(ty::ClauseKind::Trait(pred)) => { + ty::ClauseKind::Trait(pred) => { if let ty::Param(param) = pred.self_ty().kind() { return Some(param.index); } } - ty::PredicateKind::Clause(ty::ClauseKind::TypeOutlives( - ty::OutlivesPredicate(ty, _reg), - )) => { + ty::ClauseKind::TypeOutlives(ty::OutlivesPredicate(ty, _reg)) => { if let ty::Param(param) = ty.kind() { return Some(param.index); } } - ty::PredicateKind::Clause(ty::ClauseKind::Projection(p)) => { + ty::ClauseKind::Projection(p) => { if let ty::Param(param) = p.projection_ty.self_ty().kind() { projection = Some(bound_p.rebind(p)); return Some(param.index); @@ -852,11 +838,10 @@ fn clean_ty_generics<'tcx>( .as_ref() .and_then(|(lhs, rhs): &(Type, _)| Some((lhs.projection()?, rhs))) { - // FIXME(...): Remove this unwrap() impl_trait_proj.entry(param_idx).or_default().push(( trait_did, name, - rhs.map_bound(|rhs| rhs.ty().unwrap()), + *rhs, p.get_bound_params() .into_iter() .flatten() @@ -879,15 +864,8 @@ fn clean_ty_generics<'tcx>( let crate::core::ImplTraitParam::ParamIndex(idx) = param else { unreachable!() }; if let Some(proj) = impl_trait_proj.remove(&idx) { for (trait_did, name, rhs, bound_params) in proj { - let rhs = clean_middle_ty(rhs, cx, None, None); - simplify::merge_bounds( - cx, - &mut bounds, - bound_params, - trait_did, - name, - &Term::Type(rhs), - ); + let rhs = clean_middle_term(rhs, cx); + simplify::merge_bounds(cx, &mut bounds, bound_params, trait_did, name, &rhs); } } @@ -1360,21 +1338,51 @@ pub(crate) fn clean_middle_assoc_item<'tcx>( } } + let mut predicates = tcx.explicit_predicates_of(assoc_item.def_id).predicates; if let ty::TraitContainer = assoc_item.container { - let bounds = tcx - .explicit_item_bounds(assoc_item.def_id) - .subst_identity_iter_copied() - .map(|(c, s)| (c.as_predicate(), s)); - let predicates = tcx.explicit_predicates_of(assoc_item.def_id).predicates; - let predicates = - tcx.arena.alloc_from_iter(bounds.chain(predicates.iter().copied())); - let mut generics = clean_ty_generics( - cx, - tcx.generics_of(assoc_item.def_id), - ty::GenericPredicates { parent: None, predicates }, - ); - // Filter out the bounds that are (likely?) directly attached to the associated type, - // as opposed to being located in the where clause. + let bounds = + tcx.explicit_item_bounds(assoc_item.def_id).subst_identity_iter_copied(); + predicates = tcx.arena.alloc_from_iter(bounds.chain(predicates.iter().copied())); + } + let mut generics = clean_ty_generics( + cx, + tcx.generics_of(assoc_item.def_id), + ty::GenericPredicates { parent: None, predicates }, + ); + // Move bounds that are (likely) directly attached to the parameters of the + // (generic) associated type from the where clause to the respective parameter. + // There is no guarantee that this is what the user actually wrote but we have + // no way of knowing. + let mut where_predicates = ThinVec::new(); + for mut pred in generics.where_predicates { + if let WherePredicate::BoundPredicate { ty: Generic(arg), bounds, .. } = &mut pred + && let Some(GenericParamDef { + kind: GenericParamDefKind::Type { bounds: param_bounds, .. }, + .. + }) = generics.params.iter_mut().find(|param| ¶m.name == arg) + { + param_bounds.append(bounds); + } else if let WherePredicate::RegionPredicate { lifetime: Lifetime(arg), bounds } = &mut pred + && let Some(GenericParamDef { + kind: GenericParamDefKind::Lifetime { outlives: param_bounds }, + .. + }) = generics.params.iter_mut().find(|param| ¶m.name == arg) + { + param_bounds.extend(bounds.drain(..).map(|bound| match bound { + GenericBound::Outlives(lifetime) => lifetime, + _ => unreachable!(), + })); + } else { + where_predicates.push(pred); + } + } + generics.where_predicates = where_predicates; + + if let ty::TraitContainer = assoc_item.container { + // Move bounds that are (likely) directly attached to the associated type + // from the where-clause to the associated type. + // There is no guarantee that this is what the user actually wrote but we have + // no way of knowing. let mut bounds: Vec = Vec::new(); generics.where_predicates.retain_mut(|pred| match *pred { WherePredicate::BoundPredicate { @@ -1431,33 +1439,6 @@ pub(crate) fn clean_middle_assoc_item<'tcx>( } None => bounds.push(GenericBound::maybe_sized(cx)), } - // Move bounds that are (likely) directly attached to the parameters of the - // (generic) associated type from the where clause to the respective parameter. - // There is no guarantee that this is what the user actually wrote but we have - // no way of knowing. - let mut where_predicates = ThinVec::new(); - for mut pred in generics.where_predicates { - if let WherePredicate::BoundPredicate { ty: Generic(arg), bounds, .. } = &mut pred - && let Some(GenericParamDef { - kind: GenericParamDefKind::Type { bounds: param_bounds, .. }, - .. - }) = generics.params.iter_mut().find(|param| ¶m.name == arg) - { - param_bounds.append(bounds); - } else if let WherePredicate::RegionPredicate { lifetime: Lifetime(arg), bounds } = &mut pred - && let Some(GenericParamDef { - kind: GenericParamDefKind::Lifetime { outlives: param_bounds }, - .. - }) = generics.params.iter_mut().find(|param| ¶m.name == arg) { - param_bounds.extend(bounds.drain(..).map(|bound| match bound { - GenericBound::Outlives(lifetime) => lifetime, - _ => unreachable!(), - })); - } else { - where_predicates.push(pred); - } - } - generics.where_predicates = where_predicates; if tcx.defaultness(assoc_item.def_id).has_value() { AssocTypeItem( @@ -1469,7 +1450,6 @@ pub(crate) fn clean_middle_assoc_item<'tcx>( None, ), generics, - // FIXME: should we obtain the Type from HIR and pass it on here? item_type: None, }), bounds, @@ -1478,7 +1458,6 @@ pub(crate) fn clean_middle_assoc_item<'tcx>( TyAssocTypeItem(generics, bounds) } } else { - // FIXME: when could this happen? Associated items in inherent impls? AssocTypeItem( Box::new(Typedef { type_: clean_middle_ty( @@ -1487,12 +1466,11 @@ pub(crate) fn clean_middle_assoc_item<'tcx>( Some(assoc_item.def_id), None, ), - generics: Generics { - params: ThinVec::new(), - where_predicates: ThinVec::new(), - }, + generics, item_type: None, }), + // Associated types inside trait or inherent impls are not allowed to have + // item bounds. Thus we don't attempt to move any bounds there. Vec::new(), ) } @@ -2377,7 +2355,7 @@ fn filter_tokens_from_list( tokens } -/// When inlining items, we merge its attributes (and all the reexports attributes too) with the +/// When inlining items, we merge their attributes (and all the reexports attributes too) with the /// final reexport. For example: /// /// ```ignore (just an example) diff --git a/src/librustdoc/clean/simplify.rs b/src/librustdoc/clean/simplify.rs index a8221cc94498..65b1b72adc15 100644 --- a/src/librustdoc/clean/simplify.rs +++ b/src/librustdoc/clean/simplify.rs @@ -128,9 +128,7 @@ fn trait_is_same_or_supertrait(cx: &DocContext<'_>, child: DefId, trait_: DefId) .predicates .iter() .filter_map(|(pred, _)| { - if let ty::PredicateKind::Clause(ty::ClauseKind::Trait(pred)) = - pred.kind().skip_binder() - { + if let ty::ClauseKind::Trait(pred) = pred.kind().skip_binder() { if pred.trait_ref.self_ty() == self_ty { Some(pred.def_id()) } else { None } } else { None diff --git a/src/librustdoc/clean/types.rs b/src/librustdoc/clean/types.rs index 5f5cade67a2b..26139d527691 100644 --- a/src/librustdoc/clean/types.rs +++ b/src/librustdoc/clean/types.rs @@ -956,6 +956,8 @@ pub(crate) trait AttributesExt { .filter_map(|attr| Cfg::parse(attr.meta_item()?).ok()) .fold(Cfg::True, |cfg, new_cfg| cfg & new_cfg) } else if doc_auto_cfg_active { + // If there is no `doc(cfg())`, then we retrieve the `cfg()` attributes (because + // `doc(cfg())` overrides `cfg()`). self.iter() .filter(|attr| attr.has_name(sym::cfg)) .filter_map(|attr| single(attr.meta_item_list()?)) @@ -2387,6 +2389,7 @@ impl ImplKind { #[derive(Clone, Debug)] pub(crate) struct Import { pub(crate) kind: ImportKind, + /// The item being re-exported. pub(crate) source: ImportSource, pub(crate) should_be_displayed: bool, } diff --git a/src/librustdoc/config.rs b/src/librustdoc/config.rs index 9f08609a6d1a..217f1a6ee6b6 100644 --- a/src/librustdoc/config.rs +++ b/src/librustdoc/config.rs @@ -15,6 +15,7 @@ use rustc_session::config::{ use rustc_session::getopts; use rustc_session::lint::Level; use rustc_session::search_paths::SearchPath; +use rustc_session::EarlyErrorHandler; use rustc_span::edition::Edition; use rustc_target::spec::TargetTriple; @@ -311,32 +312,33 @@ impl Options { /// Parses the given command-line for options. If an error message or other early-return has /// been printed, returns `Err` with the exit code. pub(crate) fn from_matches( + handler: &mut EarlyErrorHandler, matches: &getopts::Matches, args: Vec, ) -> Result<(Options, RenderOptions), i32> { // Check for unstable options. - nightly_options::check_nightly_options(matches, &opts()); + nightly_options::check_nightly_options(handler, matches, &opts()); if args.is_empty() || matches.opt_present("h") || matches.opt_present("help") { crate::usage("rustdoc"); return Err(0); } else if matches.opt_present("version") { - rustc_driver::version!("rustdoc", matches); + rustc_driver::version!(&handler, "rustdoc", matches); return Err(0); } - if rustc_driver::describe_flag_categories(&matches) { + if rustc_driver::describe_flag_categories(handler, &matches) { return Err(0); } - let color = config::parse_color(matches); + let color = config::parse_color(handler, matches); let config::JsonConfig { json_rendered, json_unused_externs, .. } = - config::parse_json(matches); - let error_format = config::parse_error_format(matches, color, json_rendered); + config::parse_json(handler, matches); + let error_format = config::parse_error_format(handler, matches, color, json_rendered); let diagnostic_width = matches.opt_get("diagnostic-width").unwrap_or_default(); - let codegen_options = CodegenOptions::build(matches, error_format); - let unstable_opts = UnstableOptions::build(matches, error_format); + let codegen_options = CodegenOptions::build(handler, matches); + let unstable_opts = UnstableOptions::build(handler, matches); let diag = new_handler(error_format, None, diagnostic_width, &unstable_opts); @@ -393,8 +395,7 @@ impl Options { && !matches.opt_present("show-coverage") && !nightly_options::is_unstable_enabled(matches) { - rustc_session::early_error( - error_format, + handler.early_error( "the -Z unstable-options flag must be passed to enable --output-format for documentation generation (see https://github.com/rust-lang/rust/issues/76578)", ); } @@ -432,7 +433,7 @@ impl Options { return Err(0); } - let (lint_opts, describe_lints, lint_cap) = get_cmd_lint_options(matches, error_format); + let (lint_opts, describe_lints, lint_cap) = get_cmd_lint_options(handler, matches); let input = PathBuf::from(if describe_lints { "" // dummy, this won't be used @@ -446,12 +447,9 @@ impl Options { &matches.free[0] }); - let libs = matches - .opt_strs("L") - .iter() - .map(|s| SearchPath::from_cli_opt(s, error_format)) - .collect(); - let externs = parse_externs(matches, &unstable_opts, error_format); + let libs = + matches.opt_strs("L").iter().map(|s| SearchPath::from_cli_opt(handler, s)).collect(); + let externs = parse_externs(handler, matches, &unstable_opts); let extern_html_root_urls = match parse_extern_html_roots(matches) { Ok(ex) => ex, Err(err) => { @@ -589,7 +587,7 @@ impl Options { } } - let edition = config::parse_crate_edition(matches); + let edition = config::parse_crate_edition(handler, matches); let mut id_map = html::markdown::IdMap::new(); let Some(external_html) = ExternalHtml::load( @@ -623,7 +621,7 @@ impl Options { } } - let target = parse_target_triple(matches, error_format); + let target = parse_target_triple(handler, matches); let show_coverage = matches.opt_present("show-coverage"); diff --git a/src/librustdoc/core.rs b/src/librustdoc/core.rs index e10a62977752..9687b8b18878 100644 --- a/src/librustdoc/core.rs +++ b/src/librustdoc/core.rs @@ -13,8 +13,8 @@ use rustc_interface::interface; use rustc_middle::hir::nested_filter; use rustc_middle::ty::{ParamEnv, Ty, TyCtxt}; use rustc_session::config::{self, CrateType, ErrorOutputType, ResolveDocLinks}; -use rustc_session::lint; use rustc_session::Session; +use rustc_session::{lint, EarlyErrorHandler}; use rustc_span::symbol::sym; use rustc_span::{source_map, Span}; @@ -181,6 +181,7 @@ pub(crate) fn new_handler( /// Parse, resolve, and typecheck the given crate. pub(crate) fn create_config( + handler: &EarlyErrorHandler, RustdocOptions { input, crate_name, @@ -258,8 +259,8 @@ pub(crate) fn create_config( interface::Config { opts: sessopts, - crate_cfg: interface::parse_cfgspecs(cfgs), - crate_check_cfg: interface::parse_check_cfg(check_cfgs), + crate_cfg: interface::parse_cfgspecs(handler, cfgs), + crate_check_cfg: interface::parse_check_cfg(handler, check_cfgs), input, output_file: None, output_dir: None, diff --git a/src/librustdoc/doctest.rs b/src/librustdoc/doctest.rs index f6631b66f5b6..217257316c84 100644 --- a/src/librustdoc/doctest.rs +++ b/src/librustdoc/doctest.rs @@ -12,7 +12,7 @@ use rustc_parse::maybe_new_parser_from_source_str; use rustc_parse::parser::attr::InnerAttrPolicy; use rustc_session::config::{self, CrateType, ErrorOutputType}; use rustc_session::parse::ParseSess; -use rustc_session::{lint, Session}; +use rustc_session::{lint, EarlyErrorHandler, Session}; use rustc_span::edition::Edition; use rustc_span::source_map::SourceMap; use rustc_span::symbol::sym; @@ -85,13 +85,18 @@ pub(crate) fn run(options: RustdocOptions) -> Result<(), ErrorGuaranteed> { ..config::Options::default() }; + let early_error_handler = EarlyErrorHandler::new(ErrorOutputType::default()); + let mut cfgs = options.cfgs.clone(); cfgs.push("doc".to_owned()); cfgs.push("doctest".to_owned()); let config = interface::Config { opts: sessopts, - crate_cfg: interface::parse_cfgspecs(cfgs), - crate_check_cfg: interface::parse_check_cfg(options.check_cfgs.clone()), + crate_cfg: interface::parse_cfgspecs(&early_error_handler, cfgs), + crate_check_cfg: interface::parse_check_cfg( + &early_error_handler, + options.check_cfgs.clone(), + ), input, output_file: None, output_dir: None, diff --git a/src/librustdoc/html/format.rs b/src/librustdoc/html/format.rs index b710311c8587..b4aba2993c7f 100644 --- a/src/librustdoc/html/format.rs +++ b/src/librustdoc/html/format.rs @@ -1408,7 +1408,7 @@ impl clean::FnDecl { let amp = if f.alternate() { "&" } else { "&" }; write!(f, "(")?; - if let Some(n) = line_wrapping_indent { + if let Some(n) = line_wrapping_indent && !self.inputs.values.is_empty() { write!(f, "\n{}", Indent(n + 4))?; } for (i, input) in self.inputs.values.iter().enumerate() { diff --git a/src/librustdoc/html/static/css/rustdoc.css b/src/librustdoc/html/static/css/rustdoc.css index 21c1eb631e07..b6d90091bbae 100644 --- a/src/librustdoc/html/static/css/rustdoc.css +++ b/src/librustdoc/html/static/css/rustdoc.css @@ -891,8 +891,10 @@ so that we can apply CSS-filters to change the arrow color in themes */ color: var(--search-results-grey-color); } .search-results .result-name .typename { + display: inline-block; color: var(--search-results-grey-color); font-size: 0.875rem; + width: 6.25rem; } .popover { diff --git a/src/librustdoc/html/static/js/search.js b/src/librustdoc/html/static/js/search.js index 452348dc8650..b8cc0a6db714 100644 --- a/src/librustdoc/html/static/js/search.js +++ b/src/librustdoc/html/static/js/search.js @@ -52,9 +52,9 @@ const longItemTypes = [ "enum variant", "macro", "primitive type", - "associated type", + "assoc type", "constant", - "associated constant", + "assoc const", "union", "foreign type", "keyword", diff --git a/src/librustdoc/lib.rs b/src/librustdoc/lib.rs index a8cd0ec453ed..f28deae791a4 100644 --- a/src/librustdoc/lib.rs +++ b/src/librustdoc/lib.rs @@ -79,8 +79,7 @@ use rustc_errors::ErrorGuaranteed; use rustc_interface::interface; use rustc_middle::ty::TyCtxt; use rustc_session::config::{make_crate_type_option, ErrorOutputType, RustcOptGroup}; -use rustc_session::getopts; -use rustc_session::{early_error, early_warn}; +use rustc_session::{getopts, EarlyErrorHandler}; use crate::clean::utils::DOC_RUST_LANG_ORG_CHANNEL; @@ -155,6 +154,8 @@ pub fn main() { } } + let mut handler = EarlyErrorHandler::new(ErrorOutputType::default()); + rustc_driver::install_ice_hook( "https://github.com/rust-lang/rust/issues/new\ ?labels=C-bug%2C+I-ICE%2C+T-rustdoc&template=ice.md", @@ -170,11 +171,12 @@ pub fn main() { // NOTE: The reason this doesn't show double logging when `download-rustc = false` and // `debug_logging = true` is because all rustc logging goes to its version of tracing (the one // in the sysroot), and all of rustdoc's logging goes to its version (the one in Cargo.toml). - init_logging(); - rustc_driver::init_env_logger("RUSTDOC_LOG"); - let exit_code = rustc_driver::catch_with_exit_code(|| match get_args() { - Some(args) => main_args(&args), + init_logging(&handler); + rustc_driver::init_env_logger(&handler, "RUSTDOC_LOG"); + + let exit_code = rustc_driver::catch_with_exit_code(|| match get_args(&handler) { + Some(args) => main_args(&mut handler, &args), _ => { #[allow(deprecated)] @@ -184,22 +186,19 @@ pub fn main() { process::exit(exit_code); } -fn init_logging() { +fn init_logging(handler: &EarlyErrorHandler) { let color_logs = match std::env::var("RUSTDOC_LOG_COLOR").as_deref() { Ok("always") => true, Ok("never") => false, Ok("auto") | Err(VarError::NotPresent) => io::stdout().is_terminal(), - Ok(value) => early_error( - ErrorOutputType::default(), - format!("invalid log color value '{}': expected one of always, never, or auto", value), - ), - Err(VarError::NotUnicode(value)) => early_error( - ErrorOutputType::default(), - format!( - "invalid log color value '{}': expected one of always, never, or auto", - value.to_string_lossy() - ), - ), + Ok(value) => handler.early_error(format!( + "invalid log color value '{}': expected one of always, never, or auto", + value + )), + Err(VarError::NotUnicode(value)) => handler.early_error(format!( + "invalid log color value '{}': expected one of always, never, or auto", + value.to_string_lossy() + )), }; let filter = tracing_subscriber::EnvFilter::from_env("RUSTDOC_LOG"); let layer = tracing_tree::HierarchicalLayer::default() @@ -219,16 +218,13 @@ fn init_logging() { tracing::subscriber::set_global_default(subscriber).unwrap(); } -fn get_args() -> Option> { +fn get_args(handler: &EarlyErrorHandler) -> Option> { env::args_os() .enumerate() .map(|(i, arg)| { arg.into_string() .map_err(|arg| { - early_warn( - ErrorOutputType::default(), - format!("Argument {} is not valid Unicode: {:?}", i, arg), - ); + handler.early_warn(format!("Argument {} is not valid Unicode: {:?}", i, arg)); }) .ok() }) @@ -710,7 +706,7 @@ fn run_renderer<'tcx, T: formats::FormatRenderer<'tcx>>( } } -fn main_args(at_args: &[String]) -> MainResult { +fn main_args(handler: &mut EarlyErrorHandler, at_args: &[String]) -> MainResult { // Throw away the first argument, the name of the binary. // In case of at_args being empty, as might be the case by // passing empty argument array to execve under some platforms, @@ -721,7 +717,7 @@ fn main_args(at_args: &[String]) -> MainResult { // the compiler with @empty_file as argv[0] and no more arguments. let at_args = at_args.get(1..).unwrap_or_default(); - let args = rustc_driver::args::arg_expand_all(at_args); + let args = rustc_driver::args::arg_expand_all(handler, at_args); let mut options = getopts::Options::new(); for option in opts() { @@ -730,13 +726,13 @@ fn main_args(at_args: &[String]) -> MainResult { let matches = match options.parse(&args) { Ok(m) => m, Err(err) => { - early_error(ErrorOutputType::default(), err.to_string()); + handler.early_error(err.to_string()); } }; // Note that we discard any distinction between different non-zero exit // codes from `from_matches` here. - let (options, render_options) = match config::Options::from_matches(&matches, args) { + let (options, render_options) = match config::Options::from_matches(handler, &matches, args) { Ok(opts) => opts, Err(code) => { return if code == 0 { @@ -764,7 +760,7 @@ fn main_args(at_args: &[String]) -> MainResult { (false, true) => { let input = options.input.clone(); let edition = options.edition; - let config = core::create_config(options, &render_options); + let config = core::create_config(handler, options, &render_options); // `markdown::render` can invoke `doctest::make_test`, which // requires session globals and a thread pool, so we use @@ -797,7 +793,7 @@ fn main_args(at_args: &[String]) -> MainResult { let scrape_examples_options = options.scrape_examples_options.clone(); let bin_crate = options.bin_crate; - let config = core::create_config(options, &render_options); + let config = core::create_config(handler, options, &render_options); interface::run_compiler(config, |compiler| { let sess = compiler.session(); diff --git a/src/tools/clippy/clippy_lints/src/dereference.rs b/src/tools/clippy/clippy_lints/src/dereference.rs index ee6aef71980e..1ecaa1a123ce 100644 --- a/src/tools/clippy/clippy_lints/src/dereference.rs +++ b/src/tools/clippy/clippy_lints/src/dereference.rs @@ -27,7 +27,7 @@ use rustc_middle::mir::{Rvalue, StatementKind}; use rustc_middle::ty::adjustment::{Adjust, Adjustment, AutoBorrow, AutoBorrowMutability}; use rustc_middle::ty::{ self, Binder, BoundVariableKind, ClauseKind, EarlyBinder, FnSig, GenericArgKind, List, ParamEnv, ParamTy, - PredicateKind, ProjectionPredicate, Ty, TyCtxt, TypeVisitableExt, TypeckResults, + ProjectionPredicate, Ty, TyCtxt, TypeVisitableExt, TypeckResults, }; use rustc_session::{declare_tool_lint, impl_lint_pass}; use rustc_span::{symbol::sym, Span, Symbol}; @@ -1133,7 +1133,7 @@ fn needless_borrow_impl_arg_position<'tcx>( let projection_predicates = predicates .iter() .filter_map(|predicate| { - if let PredicateKind::Clause(ClauseKind::Projection(projection_predicate)) = predicate.kind().skip_binder() { + if let ClauseKind::Projection(projection_predicate) = predicate.kind().skip_binder() { Some(projection_predicate) } else { None @@ -1147,7 +1147,7 @@ fn needless_borrow_impl_arg_position<'tcx>( if predicates .iter() .filter_map(|predicate| { - if let PredicateKind::Clause(ClauseKind::Trait(trait_predicate)) = predicate.kind().skip_binder() + if let ClauseKind::Trait(trait_predicate) = predicate.kind().skip_binder() && trait_predicate.trait_ref.self_ty() == param_ty.to_ty(cx.tcx) { Some(trait_predicate.trait_ref.def_id) @@ -1209,7 +1209,7 @@ fn needless_borrow_impl_arg_position<'tcx>( } predicates.iter().all(|predicate| { - if let PredicateKind::Clause(ClauseKind::Trait(trait_predicate)) = predicate.kind().skip_binder() + if let ClauseKind::Trait(trait_predicate) = predicate.kind().skip_binder() && cx.tcx.is_diagnostic_item(sym::IntoIterator, trait_predicate.trait_ref.def_id) && let ty::Param(param_ty) = trait_predicate.self_ty().kind() && let GenericArgKind::Type(ty) = substs_with_referent_ty[param_ty.index as usize].unpack() diff --git a/src/tools/clippy/clippy_lints/src/derive.rs b/src/tools/clippy/clippy_lints/src/derive.rs index 8d84e756ff87..10a2f0cb1e7e 100644 --- a/src/tools/clippy/clippy_lints/src/derive.rs +++ b/src/tools/clippy/clippy_lints/src/derive.rs @@ -14,8 +14,8 @@ use rustc_lint::{LateContext, LateLintPass}; use rustc_middle::hir::nested_filter; use rustc_middle::traits::Reveal; use rustc_middle::ty::{ - self, Binder, BoundConstness, ClauseKind, GenericArgKind, GenericParamDefKind, ImplPolarity, ParamEnv, PredicateKind, - TraitPredicate, Ty, TyCtxt, + self, BoundConstness, ClauseKind, GenericArgKind, GenericParamDefKind, ImplPolarity, ParamEnv, + ToPredicate, TraitPredicate, Ty, TyCtxt, }; use rustc_session::{declare_lint_pass, declare_tool_lint}; use rustc_span::def_id::LocalDefId; @@ -503,7 +503,7 @@ fn param_env_for_derived_eq(tcx: TyCtxt<'_>, did: DefId, eq_trait_id: DefId) -> let ty_predicates = tcx.predicates_of(did).predicates; for (p, _) in ty_predicates { - if let PredicateKind::Clause(ClauseKind::Trait(p)) = p.kind().skip_binder() + if let ClauseKind::Trait(p) = p.kind().skip_binder() && p.trait_ref.def_id == eq_trait_id && let ty::Param(self_ty) = p.trait_ref.self_ty().kind() && p.constness == BoundConstness::NotConst @@ -514,13 +514,13 @@ fn param_env_for_derived_eq(tcx: TyCtxt<'_>, did: DefId, eq_trait_id: DefId) -> } ParamEnv::new( - tcx.mk_predicates_from_iter(ty_predicates.iter().map(|&(p, _)| p).chain( + tcx.mk_clauses_from_iter(ty_predicates.iter().map(|&(p, _)| p).chain( params.iter().filter(|&&(_, needs_eq)| needs_eq).map(|&(param, _)| { - tcx.mk_predicate(Binder::dummy(PredicateKind::Clause(ClauseKind::Trait(TraitPredicate { + ClauseKind::Trait(TraitPredicate { trait_ref: ty::TraitRef::new(tcx, eq_trait_id, [tcx.mk_param_from_def(param)]), constness: BoundConstness::NotConst, polarity: ImplPolarity::Positive, - })))) + }).to_predicate(tcx) }), )), Reveal::UserFacing, diff --git a/src/tools/clippy/clippy_lints/src/loops/never_loop.rs b/src/tools/clippy/clippy_lints/src/loops/never_loop.rs index 5f1fdf00be8c..10b5e1edf925 100644 --- a/src/tools/clippy/clippy_lints/src/loops/never_loop.rs +++ b/src/tools/clippy/clippy_lints/src/loops/never_loop.rs @@ -206,6 +206,12 @@ fn never_loop_expr(expr: &Expr<'_>, ignore_ids: &mut Vec, main_loop_id: H NeverLoopResult::AlwaysBreak, ) }), + ExprKind::Become(e) => { + combine_seq( + never_loop_expr(e, ignore_ids, main_loop_id), + NeverLoopResult::AlwaysBreak, + ) + } ExprKind::InlineAsm(asm) => asm .operands .iter() diff --git a/src/tools/clippy/clippy_lints/src/matches/significant_drop_in_scrutinee.rs b/src/tools/clippy/clippy_lints/src/matches/significant_drop_in_scrutinee.rs index 7945275393c0..93ef07d36aea 100644 --- a/src/tools/clippy/clippy_lints/src/matches/significant_drop_in_scrutinee.rs +++ b/src/tools/clippy/clippy_lints/src/matches/significant_drop_in_scrutinee.rs @@ -329,6 +329,7 @@ impl<'a, 'tcx> Visitor<'tcx> for SigDropHelper<'a, 'tcx> { ExprKind::Field(..) | ExprKind::Index(..) | ExprKind::Ret(..) | + ExprKind::Become(..) | ExprKind::Repeat(..) | ExprKind::Yield(..) => walk_expr(self, ex), ExprKind::AddrOf(_, _, _) | diff --git a/src/tools/clippy/clippy_lints/src/methods/needless_collect.rs b/src/tools/clippy/clippy_lints/src/methods/needless_collect.rs index cf85d3174dba..0699997d0d2b 100644 --- a/src/tools/clippy/clippy_lints/src/methods/needless_collect.rs +++ b/src/tools/clippy/clippy_lints/src/methods/needless_collect.rs @@ -16,7 +16,7 @@ use rustc_hir::{ }; use rustc_lint::LateContext; use rustc_middle::hir::nested_filter; -use rustc_middle::ty::{self, AssocKind, ClauseKind, EarlyBinder, GenericArg, GenericArgKind, PredicateKind, Ty}; +use rustc_middle::ty::{self, AssocKind, ClauseKind, EarlyBinder, GenericArg, GenericArgKind, Ty}; use rustc_span::symbol::Ident; use rustc_span::{sym, Span, Symbol}; @@ -175,7 +175,7 @@ fn check_collect_into_intoiterator<'tcx>( .caller_bounds() .into_iter() .filter_map(|p| { - if let PredicateKind::Clause(ClauseKind::Trait(t)) = p.kind().skip_binder() + if let ClauseKind::Trait(t) = p.kind().skip_binder() && cx.tcx.is_diagnostic_item(sym::IntoIterator,t.trait_ref.def_id) { Some(t.self_ty()) } else { diff --git a/src/tools/clippy/clippy_lints/src/methods/unnecessary_to_owned.rs b/src/tools/clippy/clippy_lints/src/methods/unnecessary_to_owned.rs index 06fa95cd657d..80eb00a1b42d 100644 --- a/src/tools/clippy/clippy_lints/src/methods/unnecessary_to_owned.rs +++ b/src/tools/clippy/clippy_lints/src/methods/unnecessary_to_owned.rs @@ -14,7 +14,7 @@ use rustc_lint::LateContext; use rustc_middle::mir::Mutability; use rustc_middle::ty::adjustment::{Adjust, Adjustment, OverloadedDeref}; use rustc_middle::ty::subst::{GenericArg, GenericArgKind, SubstsRef}; -use rustc_middle::ty::{self, ClauseKind, EarlyBinder, ParamTy, PredicateKind, ProjectionPredicate, TraitPredicate, Ty}; +use rustc_middle::ty::{self, ClauseKind, EarlyBinder, ParamTy, ProjectionPredicate, TraitPredicate, Ty}; use rustc_span::{sym, Symbol}; use rustc_trait_selection::traits::{query::evaluate_obligation::InferCtxtExt as _, Obligation, ObligationCause}; @@ -345,12 +345,12 @@ fn get_input_traits_and_projections<'tcx>( let mut projection_predicates = Vec::new(); for predicate in cx.tcx.param_env(callee_def_id).caller_bounds() { match predicate.kind().skip_binder() { - PredicateKind::Clause(ClauseKind::Trait(trait_predicate)) => { + ClauseKind::Trait(trait_predicate) => { if trait_predicate.trait_ref.self_ty() == input { trait_predicates.push(trait_predicate); } }, - PredicateKind::Clause(ClauseKind::Projection(projection_predicate)) => { + ClauseKind::Projection(projection_predicate) => { if projection_predicate.projection_ty.self_ty() == input { projection_predicates.push(projection_predicate); } @@ -407,7 +407,7 @@ fn can_change_type<'a>(cx: &LateContext<'a>, mut expr: &'a Expr<'a>, mut ty: Ty< let mut trait_predicates = cx.tcx.param_env(callee_def_id) .caller_bounds().iter().filter(|predicate| { - if let PredicateKind::Clause(ClauseKind::Trait(trait_predicate)) + if let ClauseKind::Trait(trait_predicate) = predicate.kind().skip_binder() && trait_predicate.trait_ref.self_ty() == *param_ty { diff --git a/src/tools/clippy/clippy_lints/src/needless_pass_by_value.rs b/src/tools/clippy/clippy_lints/src/needless_pass_by_value.rs index 3773975e9554..c0970048cdfe 100644 --- a/src/tools/clippy/clippy_lints/src/needless_pass_by_value.rs +++ b/src/tools/clippy/clippy_lints/src/needless_pass_by_value.rs @@ -126,7 +126,7 @@ impl<'tcx> LateLintPass<'tcx> for NeedlessPassByValue { .filter_map(|pred| { // Note that we do not want to deal with qualified predicates here. match pred.kind().no_bound_vars() { - Some(ty::PredicateKind::Clause(ty::ClauseKind::Trait(pred))) if pred.def_id() != sized_trait => { + Some(ty::ClauseKind::Trait(pred)) if pred.def_id() != sized_trait => { Some(pred) }, _ => None, diff --git a/src/tools/clippy/clippy_lints/src/unit_return_expecting_ord.rs b/src/tools/clippy/clippy_lints/src/unit_return_expecting_ord.rs index a375e5d5b4ca..99a1d197678b 100644 --- a/src/tools/clippy/clippy_lints/src/unit_return_expecting_ord.rs +++ b/src/tools/clippy/clippy_lints/src/unit_return_expecting_ord.rs @@ -4,7 +4,7 @@ use rustc_hir::def_id::DefId; use rustc_hir::{Closure, Expr, ExprKind, StmtKind}; use rustc_lint::{LateContext, LateLintPass}; use rustc_middle::ty; -use rustc_middle::ty::{ClauseKind, GenericPredicates, PredicateKind, ProjectionPredicate, TraitPredicate}; +use rustc_middle::ty::{ClauseKind, GenericPredicates, ProjectionPredicate, TraitPredicate}; use rustc_session::{declare_lint_pass, declare_tool_lint}; use rustc_span::{sym, BytePos, Span}; @@ -45,7 +45,7 @@ fn get_trait_predicates_for_trait_id<'tcx>( let mut preds = Vec::new(); for (pred, _) in generics.predicates { if_chain! { - if let PredicateKind::Clause(ClauseKind::Trait(poly_trait_pred)) = pred.kind().skip_binder(); + if let ClauseKind::Trait(poly_trait_pred) = pred.kind().skip_binder(); let trait_pred = cx.tcx.erase_late_bound_regions(pred.kind().rebind(poly_trait_pred)); if let Some(trait_def_id) = trait_id; if trait_def_id == trait_pred.trait_ref.def_id; @@ -63,7 +63,7 @@ fn get_projection_pred<'tcx>( trait_pred: TraitPredicate<'tcx>, ) -> Option> { generics.predicates.iter().find_map(|(proj_pred, _)| { - if let ty::PredicateKind::Clause(ClauseKind::Projection(pred)) = proj_pred.kind().skip_binder() { + if let ClauseKind::Projection(pred) = proj_pred.kind().skip_binder() { let projection_pred = cx.tcx.erase_late_bound_regions(proj_pred.kind().rebind(pred)); if projection_pred.projection_ty.substs == trait_pred.trait_ref.substs { return Some(projection_pred); diff --git a/src/tools/clippy/clippy_lints/src/utils/author.rs b/src/tools/clippy/clippy_lints/src/utils/author.rs index 3c2bf5abab2b..6b51974d739a 100644 --- a/src/tools/clippy/clippy_lints/src/utils/author.rs +++ b/src/tools/clippy/clippy_lints/src/utils/author.rs @@ -559,6 +559,11 @@ impl<'a, 'tcx> PrintVisitor<'a, 'tcx> { kind!("Ret({value})"); value.if_some(|e| self.expr(e)); }, + ExprKind::Become(value) => { + bind!(self, value); + kind!("Become({value})"); + self.expr(value); + }, ExprKind::InlineAsm(_) => { kind!("InlineAsm(_)"); out!("// unimplemented: `ExprKind::InlineAsm` is not further destructured at the moment"); diff --git a/src/tools/clippy/clippy_utils/src/eager_or_lazy.rs b/src/tools/clippy/clippy_utils/src/eager_or_lazy.rs index 941df3318ae8..659c693f87ae 100644 --- a/src/tools/clippy/clippy_utils/src/eager_or_lazy.rs +++ b/src/tools/clippy/clippy_utils/src/eager_or_lazy.rs @@ -15,7 +15,7 @@ use rustc_hir::def::{DefKind, Res}; use rustc_hir::intravisit::{walk_expr, Visitor}; use rustc_hir::{def_id::DefId, Block, Expr, ExprKind, QPath, UnOp}; use rustc_lint::LateContext; -use rustc_middle::ty::{self, PredicateKind}; +use rustc_middle::ty; use rustc_span::{sym, Symbol}; use std::cmp; use std::ops; @@ -73,7 +73,7 @@ fn fn_eagerness(cx: &LateContext<'_>, fn_id: DefId, name: Symbol, have_one_arg: .flat_map(|v| v.fields.iter()) .any(|x| matches!(cx.tcx.type_of(x.did).subst_identity().peel_refs().kind(), ty::Param(_))) && all_predicates_of(cx.tcx, fn_id).all(|(pred, _)| match pred.kind().skip_binder() { - PredicateKind::Clause(ty::ClauseKind::Trait(pred)) => cx.tcx.trait_def(pred.trait_ref.def_id).is_marker, + ty::ClauseKind::Trait(pred) => cx.tcx.trait_def(pred.trait_ref.def_id).is_marker, _ => true, }) && subs.types().all(|x| matches!(x.peel_refs().kind(), ty::Param(_))) @@ -191,6 +191,7 @@ fn expr_eagerness<'tcx>(cx: &LateContext<'tcx>, e: &'tcx Expr<'_>) -> EagernessS ExprKind::Break(..) | ExprKind::Continue(_) | ExprKind::Ret(_) + | ExprKind::Become(_) | ExprKind::InlineAsm(_) | ExprKind::Yield(..) | ExprKind::Err(_) => { diff --git a/src/tools/clippy/clippy_utils/src/hir_utils.rs b/src/tools/clippy/clippy_utils/src/hir_utils.rs index a49246a78327..3e1d73564146 100644 --- a/src/tools/clippy/clippy_utils/src/hir_utils.rs +++ b/src/tools/clippy/clippy_utils/src/hir_utils.rs @@ -845,6 +845,9 @@ impl<'a, 'tcx> SpanlessHash<'a, 'tcx> { self.hash_expr(e); } }, + ExprKind::Become(f) => { + self.hash_expr(f); + }, ExprKind::Path(ref qpath) => { self.hash_qpath(qpath); }, diff --git a/src/tools/clippy/clippy_utils/src/qualify_min_const_fn.rs b/src/tools/clippy/clippy_utils/src/qualify_min_const_fn.rs index a10eb8646af5..b7e83ce6caac 100644 --- a/src/tools/clippy/clippy_utils/src/qualify_min_const_fn.rs +++ b/src/tools/clippy/clippy_utils/src/qualify_min_const_fn.rs @@ -21,35 +21,6 @@ type McfResult = Result<(), (Span, Cow<'static, str>)>; pub fn is_min_const_fn<'tcx>(tcx: TyCtxt<'tcx>, body: &Body<'tcx>, msrv: &Msrv) -> McfResult { let def_id = body.source.def_id(); - let mut current = def_id; - loop { - let predicates = tcx.predicates_of(current); - for (predicate, _) in predicates.predicates { - match predicate.kind().skip_binder() { - ty::PredicateKind::Clause( - ty::ClauseKind::RegionOutlives(_) - | ty::ClauseKind::TypeOutlives(_) - | ty::ClauseKind::Projection(_) - | ty::ClauseKind::Trait(..) - | ty::ClauseKind::ConstArgHasType(..), - ) - | ty::PredicateKind::Clause(ty::ClauseKind::WellFormed(_)) - | ty::PredicateKind::Clause(ty::ClauseKind::ConstEvaluatable(..)) - | ty::PredicateKind::ConstEquate(..) - | ty::PredicateKind::TypeWellFormedFromEnv(..) => continue, - ty::PredicateKind::AliasRelate(..) => panic!("alias relate predicate on function: {predicate:#?}"), - ty::PredicateKind::ObjectSafe(_) => panic!("object safe predicate on function: {predicate:#?}"), - ty::PredicateKind::ClosureKind(..) => panic!("closure kind predicate on function: {predicate:#?}"), - ty::PredicateKind::Subtype(_) => panic!("subtype predicate on function: {predicate:#?}"), - ty::PredicateKind::Coerce(_) => panic!("coerce predicate on function: {predicate:#?}"), - ty::PredicateKind::Ambiguous => panic!("ambiguous predicate on function: {predicate:#?}"), - } - } - match predicates.parent { - Some(parent) => current = parent, - None => break, - } - } for local in &body.local_decls { check_ty(tcx, local.ty, local.source_info.span)?; diff --git a/src/tools/clippy/clippy_utils/src/sugg.rs b/src/tools/clippy/clippy_utils/src/sugg.rs index a87d58110b0c..b38b9553558c 100644 --- a/src/tools/clippy/clippy_utils/src/sugg.rs +++ b/src/tools/clippy/clippy_utils/src/sugg.rs @@ -147,6 +147,7 @@ impl<'a> Sugg<'a> { | hir::ExprKind::Path(..) | hir::ExprKind::Repeat(..) | hir::ExprKind::Ret(..) + | hir::ExprKind::Become(..) | hir::ExprKind::Struct(..) | hir::ExprKind::Tup(..) | hir::ExprKind::Err(_) => Sugg::NonParen(get_snippet(expr.span)), diff --git a/src/tools/clippy/clippy_utils/src/ty.rs b/src/tools/clippy/clippy_utils/src/ty.rs index 2b185943c59c..8d3aecd4785b 100644 --- a/src/tools/clippy/clippy_utils/src/ty.rs +++ b/src/tools/clippy/clippy_utils/src/ty.rs @@ -17,7 +17,7 @@ use rustc_lint::LateContext; use rustc_middle::mir::interpret::{ConstValue, Scalar}; use rustc_middle::ty::{ self, layout::ValidityRequirement, AdtDef, AliasTy, AssocKind, Binder, BoundRegion, FnSig, IntTy, List, ParamEnv, - Predicate, PredicateKind, Region, RegionKind, SubstsRef, Ty, TyCtxt, TypeSuperVisitable, TypeVisitable, + Region, RegionKind, SubstsRef, Ty, TyCtxt, TypeSuperVisitable, TypeVisitable, TypeVisitableExt, TypeVisitor, UintTy, VariantDef, VariantDiscr, }; use rustc_middle::ty::{GenericArg, GenericArgKind}; @@ -563,7 +563,7 @@ fn is_uninit_value_valid_for_ty_fallback<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'t } /// Gets an iterator over all predicates which apply to the given item. -pub fn all_predicates_of(tcx: TyCtxt<'_>, id: DefId) -> impl Iterator, Span)> { +pub fn all_predicates_of(tcx: TyCtxt<'_>, id: DefId) -> impl Iterator, Span)> { let mut next_id = Some(id); iter::from_fn(move || { next_id.take().map(|id| { @@ -665,7 +665,7 @@ pub fn ty_sig<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>) -> Option sig_from_bounds( cx, ty, - cx.tcx.item_bounds(def_id).subst_iter(cx.tcx, substs).map(|c| c.as_predicate()), + cx.tcx.item_bounds(def_id).subst_iter(cx.tcx, substs), cx.tcx.opt_parent(def_id), ), ty::FnPtr(sig) => Some(ExprFnSig::Sig(sig, None)), @@ -698,7 +698,7 @@ pub fn ty_sig<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>) -> Option( cx: &LateContext<'tcx>, ty: Ty<'tcx>, - predicates: impl IntoIterator>, + predicates: impl IntoIterator>, predicates_id: Option, ) -> Option> { let mut inputs = None; @@ -707,7 +707,7 @@ fn sig_from_bounds<'tcx>( for pred in predicates { match pred.kind().skip_binder() { - PredicateKind::Clause(ty::ClauseKind::Trait(p)) + ty::ClauseKind::Trait(p) if (lang_items.fn_trait() == Some(p.def_id()) || lang_items.fn_mut_trait() == Some(p.def_id()) || lang_items.fn_once_trait() == Some(p.def_id())) @@ -720,7 +720,7 @@ fn sig_from_bounds<'tcx>( } inputs = Some(i); }, - PredicateKind::Clause(ty::ClauseKind::Projection(p)) + ty::ClauseKind::Projection(p) if Some(p.projection_ty.def_id) == lang_items.fn_once_output() && p.projection_ty.self_ty() == ty => { if output.is_some() { @@ -937,7 +937,7 @@ pub fn adt_and_variant_of_res<'tcx>(cx: &LateContext<'tcx>, res: Res) -> Option< } /// Checks if the type is a type parameter implementing `FnOnce`, but not `FnMut`. -pub fn ty_is_fn_once_param<'tcx>(tcx: TyCtxt<'_>, ty: Ty<'tcx>, predicates: &'tcx [Predicate<'_>]) -> bool { +pub fn ty_is_fn_once_param<'tcx>(tcx: TyCtxt<'_>, ty: Ty<'tcx>, predicates: &'tcx [ty::Clause<'_>]) -> bool { let ty::Param(ty) = *ty.kind() else { return false; }; @@ -950,7 +950,7 @@ pub fn ty_is_fn_once_param<'tcx>(tcx: TyCtxt<'_>, ty: Ty<'tcx>, predicates: &'tc predicates .iter() .try_fold(false, |found, p| { - if let PredicateKind::Clause(ty::ClauseKind::Trait(p)) = p.kind().skip_binder() + if let ty::ClauseKind::Trait(p) = p.kind().skip_binder() && let ty::Param(self_ty) = p.trait_ref.self_ty().kind() && ty.index == self_ty.index { diff --git a/src/tools/clippy/clippy_utils/src/visitors.rs b/src/tools/clippy/clippy_utils/src/visitors.rs index 5dcd71cef127..8dafa723afa0 100644 --- a/src/tools/clippy/clippy_utils/src/visitors.rs +++ b/src/tools/clippy/clippy_utils/src/visitors.rs @@ -651,6 +651,7 @@ pub fn for_each_unconsumed_temporary<'tcx, B>( // Either drops temporaries, jumps out of the current expression, or has no sub expression. ExprKind::DropTemps(_) | ExprKind::Ret(_) + | ExprKind::Become(_) | ExprKind::Break(..) | ExprKind::Yield(..) | ExprKind::Block(..) diff --git a/src/tools/clippy/src/driver.rs b/src/tools/clippy/src/driver.rs index 3c5b6e12b968..f3cc94aeff01 100644 --- a/src/tools/clippy/src/driver.rs +++ b/src/tools/clippy/src/driver.rs @@ -16,6 +16,8 @@ extern crate rustc_session; extern crate rustc_span; use rustc_interface::interface; +use rustc_session::EarlyErrorHandler; +use rustc_session::config::ErrorOutputType; use rustc_session::parse::ParseSess; use rustc_span::symbol::Symbol; @@ -187,7 +189,9 @@ const BUG_REPORT_URL: &str = "https://github.com/rust-lang/rust-clippy/issues/ne #[allow(clippy::too_many_lines)] pub fn main() { - rustc_driver::init_rustc_env_logger(); + let handler = EarlyErrorHandler::new(ErrorOutputType::default()); + + rustc_driver::init_rustc_env_logger(&handler); rustc_driver::install_ice_hook(BUG_REPORT_URL, |handler| { // FIXME: this macro calls unwrap internally but is called in a panicking context! It's not diff --git a/src/tools/clippy/tests/ui/crashes/ice-6250.stderr b/src/tools/clippy/tests/ui/crashes/ice-6250.stderr index 4506d1550bd4..db34e6bfa7b2 100644 --- a/src/tools/clippy/tests/ui/crashes/ice-6250.stderr +++ b/src/tools/clippy/tests/ui/crashes/ice-6250.stderr @@ -12,11 +12,6 @@ LL | for reference in vec![1, 2, 3] { ... LL | Some(reference) = cache.data.get(key) { | ^^^^^^^^^ expected integer, found `&i32` - | -help: consider dereferencing the borrow - | -LL | Some(*reference) = cache.data.get(key) { - | + error[E0308]: mismatched types --> $DIR/ice-6250.rs:12:9 diff --git a/src/tools/compiletest/src/common.rs b/src/tools/compiletest/src/common.rs index 1b46c42fa4cf..85a8fbcffbe2 100644 --- a/src/tools/compiletest/src/common.rs +++ b/src/tools/compiletest/src/common.rs @@ -453,7 +453,7 @@ impl TargetCfgs { let mut all_families = HashSet::new(); let mut all_pointer_widths = HashSet::new(); - for (target, cfg) in targets.into_iter() { + for (target, cfg) in targets.iter() { all_archs.insert(cfg.arch.clone()); all_oses.insert(cfg.os.clone()); all_oses_and_envs.insert(cfg.os_and_env()); @@ -464,11 +464,11 @@ impl TargetCfgs { } all_pointer_widths.insert(format!("{}bit", cfg.pointer_width)); - all_targets.insert(target.into()); + all_targets.insert(target.clone()); } Self { - current: Self::get_current_target_config(config), + current: Self::get_current_target_config(config, &targets), all_targets, all_archs, all_oses, @@ -480,16 +480,20 @@ impl TargetCfgs { } } - fn get_current_target_config(config: &Config) -> TargetCfg { - let mut arch = None; - let mut os = None; - let mut env = None; - let mut abi = None; - let mut families = Vec::new(); - let mut pointer_width = None; - let mut endian = None; - let mut panic = None; + fn get_current_target_config( + config: &Config, + targets: &HashMap, + ) -> TargetCfg { + let mut cfg = targets[&config.target].clone(); + // To get the target information for the current target, we take the target spec obtained + // from `--print=all-target-specs-json`, and then we enrich it with the information + // gathered from `--print=cfg --target=$target`. + // + // This is done because some parts of the target spec can be overridden with `-C` flags, + // which are respected for `--print=cfg` but not for `--print=all-target-specs-json`. The + // code below extracts them from `--print=cfg`: make sure to only override fields that can + // actually be changed with `-C` flags. for config in rustc_output(config, &["--print=cfg", "--target", &config.target]).trim().lines() { @@ -507,60 +511,16 @@ impl TargetCfgs { }) .unwrap_or_else(|| (config, None)); - match name { - "target_arch" => { - arch = Some(value.expect("target_arch should be a key-value pair").to_string()); - } - "target_os" => { - os = Some(value.expect("target_os sould be a key-value pair").to_string()); - } - "target_env" => { - env = Some(value.expect("target_env should be a key-value pair").to_string()); - } - "target_abi" => { - abi = Some(value.expect("target_abi should be a key-value pair").to_string()); - } - "target_family" => { - families - .push(value.expect("target_family should be a key-value pair").to_string()); - } - "target_pointer_width" => { - pointer_width = Some( - value - .expect("target_pointer_width should be a key-value pair") - .parse::() - .expect("target_pointer_width should be a valid u32"), - ); - } - "target_endian" => { - endian = Some(match value.expect("target_endian should be a key-value pair") { - "big" => Endian::Big, - "little" => Endian::Little, - _ => panic!("target_endian should be either 'big' or 'little'"), - }); - } - "panic" => { - panic = Some(match value.expect("panic should be a key-value pair") { - "abort" => PanicStrategy::Abort, - "unwind" => PanicStrategy::Unwind, - _ => panic!("panic should be either 'abort' or 'unwind'"), - }); - } - _ => (), + match (name, value) { + // Can be overridden with `-C panic=$strategy`. + ("panic", Some("abort")) => cfg.panic = PanicStrategy::Abort, + ("panic", Some("unwind")) => cfg.panic = PanicStrategy::Unwind, + ("panic", other) => panic!("unexpected value for panic cfg: {other:?}"), + _ => {} } } - TargetCfg { - arch: arch.expect("target configuration should specify target_arch"), - os: os.expect("target configuration should specify target_os"), - env: env.expect("target configuration should specify target_env"), - abi: abi.expect("target configuration should specify target_abi"), - families, - pointer_width: pointer_width - .expect("target configuration should specify target_pointer_width"), - endian: endian.expect("target configuration should specify target_endian"), - panic: panic.expect("target configuration should specify panic"), - } + cfg } } @@ -582,6 +542,8 @@ pub struct TargetCfg { endian: Endian, #[serde(rename = "panic-strategy", default)] pub(crate) panic: PanicStrategy, + #[serde(default)] + pub(crate) dynamic_linking: bool, } impl TargetCfg { diff --git a/src/tools/compiletest/src/header/needs.rs b/src/tools/compiletest/src/header/needs.rs index 18b3b913a682..0e306696a90c 100644 --- a/src/tools/compiletest/src/header/needs.rs +++ b/src/tools/compiletest/src/header/needs.rs @@ -130,6 +130,11 @@ pub(super) fn handle_needs( condition: config.git_hash, ignore_reason: "ignored when git hashes have been omitted for building", }, + Need { + name: "needs-dynamic-linking", + condition: config.target_cfg().dynamic_linking, + ignore_reason: "ignored on targets without dynamic linking", + }, ]; let (name, comment) = match ln.split_once([':', ' ']) { diff --git a/src/tools/compiletest/src/runtest.rs b/src/tools/compiletest/src/runtest.rs index 25b16e38e534..5c8ee7895d3b 100644 --- a/src/tools/compiletest/src/runtest.rs +++ b/src/tools/compiletest/src/runtest.rs @@ -1810,8 +1810,8 @@ impl<'test> TestCx<'test> { || self.config.target.contains("wasm32") || self.config.target.contains("nvptx") || self.is_vxworks_pure_static() - || self.config.target.contains("sgx") || self.config.target.contains("bpf") + || !self.config.target_cfg().dynamic_linking { // We primarily compile all auxiliary libraries as dynamic libraries // to avoid code size bloat and large binaries as much as possible diff --git a/src/tools/error_index_generator/main.rs b/src/tools/error_index_generator/main.rs index f984275b164c..62a58576da55 100644 --- a/src/tools/error_index_generator/main.rs +++ b/src/tools/error_index_generator/main.rs @@ -1,6 +1,7 @@ #![feature(rustc_private)] extern crate rustc_driver; +extern crate rustc_session; use std::env; use std::error::Error; @@ -170,7 +171,9 @@ fn parse_args() -> (OutputFormat, PathBuf) { } fn main() { - rustc_driver::init_env_logger("RUST_LOG"); + let handler = + rustc_session::EarlyErrorHandler::new(rustc_session::config::ErrorOutputType::default()); + rustc_driver::init_env_logger(&handler, "RUST_LOG"); let (format, dst) = parse_args(); let result = main_with_result(format, &dst); if let Err(e) = result { diff --git a/src/tools/generate-windows-sys/src/arm_shim.rs b/src/tools/generate-windows-sys/src/arm_shim.rs deleted file mode 100644 index 17c2ccb223cc..000000000000 --- a/src/tools/generate-windows-sys/src/arm_shim.rs +++ /dev/null @@ -1,20 +0,0 @@ -// Begin of ARM32 shim -// The raw content of this file should be processed by `generate-windows-sys` -// to be merged with the generated binding. It is not supposed to be used as -// a normal Rust module. -cfg_if::cfg_if! { -if #[cfg(target_arch = "arm")] { -#[repr(C)] -pub struct WSADATA { - pub wVersion: u16, - pub wHighVersion: u16, - pub szDescription: [u8; 257], - pub szSystemStatus: [u8; 129], - pub iMaxSockets: u16, - pub iMaxUdpDg: u16, - pub lpVendorInfo: PSTR, -} -pub enum CONTEXT {} -} -} -// End of ARM32 shim diff --git a/src/tools/generate-windows-sys/src/main.rs b/src/tools/generate-windows-sys/src/main.rs index 65e480715ee2..91d981462e81 100644 --- a/src/tools/generate-windows-sys/src/main.rs +++ b/src/tools/generate-windows-sys/src/main.rs @@ -11,9 +11,6 @@ const PRELUDE: &str = r#"// This file is autogenerated. // ignore-tidy-filelength "#; -/// This is a shim for the ARM (32-bit) architecture, which is no longer supported by windows-rs. -const ARM_SHIM: &str = include_str!("arm_shim.rs"); - fn main() -> io::Result<()> { let mut path: PathBuf = std::env::args_os().nth(1).expect("a path to the rust repository is required").into(); @@ -35,7 +32,6 @@ fn main() -> io::Result<()> { let mut f = std::fs::File::create(&path)?; f.write_all(PRELUDE.as_bytes())?; f.write_all(bindings.as_bytes())?; - f.write_all(ARM_SHIM.as_bytes())?; Ok(()) } diff --git a/src/tools/miri/src/bin/miri.rs b/src/tools/miri/src/bin/miri.rs index 083dd4800d93..219617b1d685 100644 --- a/src/tools/miri/src/bin/miri.rs +++ b/src/tools/miri/src/bin/miri.rs @@ -31,9 +31,9 @@ use rustc_middle::{ query::{ExternProviders, LocalCrate}, ty::TyCtxt, }; -use rustc_session::config::OptLevel; - -use rustc_session::{config::CrateType, search_paths::PathKind, CtfeBacktrace}; +use rustc_session::{EarlyErrorHandler, CtfeBacktrace}; +use rustc_session::config::{OptLevel, CrateType, ErrorOutputType}; +use rustc_session::search_paths::PathKind; use miri::{BacktraceStyle, BorrowTrackerMethod, ProvenanceMode, RetagFields}; @@ -59,6 +59,7 @@ impl rustc_driver::Callbacks for MiriCompilerCalls { fn after_analysis<'tcx>( &mut self, + handler: &EarlyErrorHandler, _: &rustc_interface::interface::Compiler, queries: &'tcx rustc_interface::Queries<'tcx>, ) -> Compilation { @@ -66,8 +67,8 @@ impl rustc_driver::Callbacks for MiriCompilerCalls { if tcx.sess.compile_status().is_err() { tcx.sess.fatal("miri cannot be run on programs that fail compilation"); } - - init_late_loggers(tcx); +; + init_late_loggers(handler, tcx); if !tcx.sess.crate_types().contains(&CrateType::Executable) { tcx.sess.fatal("miri only makes sense on bin crates"); } @@ -181,7 +182,7 @@ macro_rules! show_error { ($($tt:tt)*) => { show_error(&format_args!($($tt)*)) }; } -fn init_early_loggers() { +fn init_early_loggers(handler: &EarlyErrorHandler) { // Note that our `extern crate log` is *not* the same as rustc's; as a result, we have to // initialize them both, and we always initialize `miri`'s first. let env = env_logger::Env::new().filter("MIRI_LOG").write_style("MIRI_LOG_STYLE"); @@ -195,11 +196,11 @@ fn init_early_loggers() { // later with our custom settings, and *not* log anything for what happens before // `miri` gets started. if env::var_os("RUSTC_LOG").is_some() { - rustc_driver::init_rustc_env_logger(); + rustc_driver::init_rustc_env_logger(handler); } } -fn init_late_loggers(tcx: TyCtxt<'_>) { +fn init_late_loggers(handler: &EarlyErrorHandler, tcx: TyCtxt<'_>) { // We initialize loggers right before we start evaluation. We overwrite the `RUSTC_LOG` // env var if it is not set, control it based on `MIRI_LOG`. // (FIXME: use `var_os`, but then we need to manually concatenate instead of `format!`.) @@ -218,7 +219,7 @@ fn init_late_loggers(tcx: TyCtxt<'_>) { } else { env::set_var("RUSTC_LOG", &var); } - rustc_driver::init_rustc_env_logger(); + rustc_driver::init_rustc_env_logger(handler); } } @@ -284,6 +285,8 @@ fn parse_comma_list(input: &str) -> Result, T::Err> { } fn main() { + let handler = EarlyErrorHandler::new(ErrorOutputType::default()); + // Snapshot a copy of the environment before `rustc` starts messing with it. // (`install_ice_hook` might change `RUST_BACKTRACE`.) let env_snapshot = env::vars_os().collect::>(); @@ -292,7 +295,7 @@ fn main() { if let Some(crate_kind) = env::var_os("MIRI_BE_RUSTC") { // Earliest rustc setup. rustc_driver::install_ice_hook(rustc_driver::DEFAULT_BUG_REPORT_URL, |_| ()); - rustc_driver::init_rustc_env_logger(); + rustc_driver::init_rustc_env_logger(&handler); let target_crate = if crate_kind == "target" { true @@ -314,7 +317,7 @@ fn main() { rustc_driver::install_ice_hook("https://github.com/rust-lang/miri/issues/new", |_| ()); // Init loggers the Miri way. - init_early_loggers(); + init_early_loggers(&handler); // Parse our arguments and split them across `rustc` and `miri`. let mut miri_config = miri::MiriConfig::default(); diff --git a/src/tools/rust-installer/Cargo.toml b/src/tools/rust-installer/Cargo.toml index 85e979f07bff..471f2b5ac73e 100644 --- a/src/tools/rust-installer/Cargo.toml +++ b/src/tools/rust-installer/Cargo.toml @@ -2,7 +2,7 @@ authors = ["The Rust Project Developers"] name = "installer" version = "0.0.0" -edition = "2018" +edition = "2021" [[bin]] doc = false @@ -20,4 +20,4 @@ num_cpus = "1" [dependencies.clap] features = ["derive"] -version = "3.1" +version = "4.2" diff --git a/src/tools/rust-installer/src/combiner.rs b/src/tools/rust-installer/src/combiner.rs index abcf59cfe36c..19466f63fedf 100644 --- a/src/tools/rust-installer/src/combiner.rs +++ b/src/tools/rust-installer/src/combiner.rs @@ -13,47 +13,47 @@ actor! { #[derive(Debug)] pub struct Combiner { /// The name of the product, for display. - #[clap(value_name = "NAME")] + #[arg(value_name = "NAME")] product_name: String = "Product", /// The name of the package tarball. - #[clap(value_name = "NAME")] + #[arg(value_name = "NAME")] package_name: String = "package", /// The directory under lib/ where the manifest lives. - #[clap(value_name = "DIR")] + #[arg(value_name = "DIR")] rel_manifest_dir: String = "packagelib", /// The string to print after successful installation. - #[clap(value_name = "MESSAGE")] + #[arg(value_name = "MESSAGE")] success_message: String = "Installed.", /// Places to look for legacy manifests to uninstall. - #[clap(value_name = "DIRS")] + #[arg(value_name = "DIRS")] legacy_manifest_dirs: String = "", /// Installers to combine. - #[clap(value_name = "FILE,FILE")] + #[arg(value_name = "FILE,FILE")] input_tarballs: String = "", /// Directory containing files that should not be installed. - #[clap(value_name = "DIR")] + #[arg(value_name = "DIR")] non_installed_overlay: String = "", /// The directory to do temporary work. - #[clap(value_name = "DIR")] + #[arg(value_name = "DIR")] work_dir: String = "./workdir", /// The location to put the final image and tarball. - #[clap(value_name = "DIR")] + #[arg(value_name = "DIR")] output_dir: String = "./dist", /// The profile used to compress the tarball. - #[clap(value_name = "FORMAT", default_value_t)] + #[arg(value_name = "FORMAT", default_value_t)] compression_profile: CompressionProfile, /// The formats used to compress the tarball - #[clap(value_name = "FORMAT", default_value_t)] + #[arg(value_name = "FORMAT", default_value_t)] compression_formats: CompressionFormats, } } @@ -94,7 +94,7 @@ impl Combiner { let pkg_name = input_tarball.trim_end_matches(&format!(".tar.{}", compression.extension())); let pkg_name = Path::new(pkg_name).file_name().unwrap(); - let pkg_dir = Path::new(&self.work_dir).join(&pkg_name); + let pkg_dir = Path::new(&self.work_dir).join(pkg_name); // Verify the version number. let mut version = String::new(); @@ -114,9 +114,9 @@ impl Combiner { // All we need to do is copy the component directory. We could // move it, but rustbuild wants to reuse the unpacked package // dir for OS-specific installers on macOS and Windows. - let component_dir = package_dir.join(&component); + let component_dir = package_dir.join(component); create_dir(&component_dir)?; - copy_recursive(&pkg_dir.join(&component), &component_dir)?; + copy_recursive(&pkg_dir.join(component), &component_dir)?; // Merge the component name. writeln!(&components, "{}", component).context("failed to write new components")?; @@ -158,7 +158,7 @@ impl Combiner { .input(self.package_name) .output(path_to_str(&output)?.into()) .compression_profile(self.compression_profile) - .compression_formats(self.compression_formats.clone()); + .compression_formats(self.compression_formats); tarballer.run()?; Ok(()) diff --git a/src/tools/rust-installer/src/compression.rs b/src/tools/rust-installer/src/compression.rs index 7c9c946e0b54..902b2ec69078 100644 --- a/src/tools/rust-installer/src/compression.rs +++ b/src/tools/rust-installer/src/compression.rs @@ -166,7 +166,7 @@ impl Default for CompressionFormats { impl CompressionFormats { pub(crate) fn iter(&self) -> impl Iterator + '_ { - self.0.iter().map(|i| *i) + self.0.iter().copied() } } diff --git a/src/tools/rust-installer/src/generator.rs b/src/tools/rust-installer/src/generator.rs index ddd1052599d5..45f8c49d03ea 100644 --- a/src/tools/rust-installer/src/generator.rs +++ b/src/tools/rust-installer/src/generator.rs @@ -11,55 +11,55 @@ actor! { #[derive(Debug)] pub struct Generator { /// The name of the product, for display - #[clap(value_name = "NAME")] + #[arg(value_name = "NAME")] product_name: String = "Product", /// The name of the component, distinct from other installed components - #[clap(value_name = "NAME")] + #[arg(value_name = "NAME")] component_name: String = "component", /// The name of the package, tarball - #[clap(value_name = "NAME")] + #[arg(value_name = "NAME")] package_name: String = "package", /// The directory under lib/ where the manifest lives - #[clap(value_name = "DIR")] + #[arg(value_name = "DIR")] rel_manifest_dir: String = "packagelib", /// The string to print after successful installation - #[clap(value_name = "MESSAGE")] + #[arg(value_name = "MESSAGE")] success_message: String = "Installed.", /// Places to look for legacy manifests to uninstall - #[clap(value_name = "DIRS")] + #[arg(value_name = "DIRS")] legacy_manifest_dirs: String = "", /// Directory containing files that should not be installed - #[clap(value_name = "DIR")] + #[arg(value_name = "DIR")] non_installed_overlay: String = "", /// Path prefixes of directories that should be installed/uninstalled in bulk - #[clap(value_name = "DIRS")] + #[arg(value_name = "DIRS")] bulk_dirs: String = "", /// The directory containing the installation medium - #[clap(value_name = "DIR")] + #[arg(value_name = "DIR")] image_dir: String = "./install_image", /// The directory to do temporary work - #[clap(value_name = "DIR")] + #[arg(value_name = "DIR")] work_dir: String = "./workdir", /// The location to put the final image and tarball - #[clap(value_name = "DIR")] + #[arg(value_name = "DIR")] output_dir: String = "./dist", /// The profile used to compress the tarball. - #[clap(value_name = "FORMAT", default_value_t)] + #[arg(value_name = "FORMAT", default_value_t)] compression_profile: CompressionProfile, /// The formats used to compress the tarball - #[clap(value_name = "FORMAT", default_value_t)] + #[arg(value_name = "FORMAT", default_value_t)] compression_formats: CompressionFormats, } } @@ -118,7 +118,7 @@ impl Generator { .input(self.package_name) .output(path_to_str(&output)?.into()) .compression_profile(self.compression_profile) - .compression_formats(self.compression_formats.clone()); + .compression_formats(self.compression_formats); tarballer.run()?; Ok(()) diff --git a/src/tools/rust-installer/src/scripter.rs b/src/tools/rust-installer/src/scripter.rs index 06affc029fd1..8180f925cb0d 100644 --- a/src/tools/rust-installer/src/scripter.rs +++ b/src/tools/rust-installer/src/scripter.rs @@ -2,29 +2,29 @@ use crate::util::*; use anyhow::{Context, Result}; use std::io::Write; -const TEMPLATE: &'static str = include_str!("../install-template.sh"); +const TEMPLATE: &str = include_str!("../install-template.sh"); actor! { #[derive(Debug)] pub struct Scripter { /// The name of the product, for display - #[clap(value_name = "NAME")] + #[arg(value_name = "NAME")] product_name: String = "Product", /// The directory under lib/ where the manifest lives - #[clap(value_name = "DIR")] + #[arg(value_name = "DIR")] rel_manifest_dir: String = "manifestlib", /// The string to print after successful installation - #[clap(value_name = "MESSAGE")] + #[arg(value_name = "MESSAGE")] success_message: String = "Installed.", /// Places to look for legacy manifests to uninstall - #[clap(value_name = "DIRS")] + #[arg(value_name = "DIRS")] legacy_manifest_dirs: String = "", /// The name of the output script - #[clap(value_name = "FILE")] + #[arg(value_name = "FILE")] output_script: String = "install.sh", } } diff --git a/src/tools/rust-installer/src/tarballer.rs b/src/tools/rust-installer/src/tarballer.rs index 7353a49fe035..c60d5f648ffc 100644 --- a/src/tools/rust-installer/src/tarballer.rs +++ b/src/tools/rust-installer/src/tarballer.rs @@ -14,23 +14,23 @@ actor! { #[derive(Debug)] pub struct Tarballer { /// The input folder to be compressed. - #[clap(value_name = "NAME")] + #[arg(value_name = "NAME")] input: String = "package", /// The prefix of the tarballs. - #[clap(value_name = "PATH")] + #[arg(value_name = "PATH")] output: String = "./dist", /// The folder in which the input is to be found. - #[clap(value_name = "DIR")] + #[arg(value_name = "DIR")] work_dir: String = "./workdir", /// The profile used to compress the tarball. - #[clap(value_name = "FORMAT", default_value_t)] + #[arg(value_name = "FORMAT", default_value_t)] compression_profile: CompressionProfile, /// The formats used to compress the tarball. - #[clap(value_name = "FORMAT", default_value_t)] + #[arg(value_name = "FORMAT", default_value_t)] compression_formats: CompressionFormats, } } @@ -98,7 +98,7 @@ fn append_path(builder: &mut Builder, src: &Path, path: &String) -> if cfg!(windows) { // Windows doesn't really have a mode, so `tar` never marks files executable. // Use an extension whitelist to update files that usually should be so. - const EXECUTABLES: [&'static str; 4] = ["exe", "dll", "py", "sh"]; + const EXECUTABLES: [&str; 4] = ["exe", "dll", "py", "sh"]; if let Some(ext) = src.extension().and_then(|s| s.to_str()) { if EXECUTABLES.contains(&ext) { let mode = header.mode()?; @@ -134,7 +134,7 @@ where for entry in WalkDir::new(root.join(name)) { let entry = entry?; let path = entry.path().strip_prefix(root)?; - let path = path_to_str(&path)?; + let path = path_to_str(path)?; if entry.file_type().is_dir() { dirs.push(path.to_owned()); diff --git a/src/tools/rust-installer/src/util.rs b/src/tools/rust-installer/src/util.rs index 6cac314b68d0..4eb2e75fd7e1 100644 --- a/src/tools/rust-installer/src/util.rs +++ b/src/tools/rust-installer/src/util.rs @@ -117,7 +117,7 @@ where } else { copy(entry.path(), dst)?; } - callback(&path, file_type)?; + callback(path, file_type)?; } Ok(()) } @@ -135,7 +135,7 @@ macro_rules! actor { $( #[ $attr ] )+ #[derive(clap::Args)] pub struct $name { - $( $( #[ $field_attr ] )+ #[clap(long, $(default_value = $default)*)] $field : $type, )* + $( $( #[ $field_attr ] )+ #[arg(long, $(default_value = $default)*)] $field : $type, )* } impl Default for $name { diff --git a/src/tools/tidy/src/features.rs b/src/tools/tidy/src/features.rs index 2fd4c797b43f..7ad8f5c5c05f 100644 --- a/src/tools/tidy/src/features.rs +++ b/src/tools/tidy/src/features.rs @@ -160,10 +160,10 @@ pub fn check( for &(name, _) in gate_untested.iter() { println!("Expected a gate test for the feature '{name}'."); println!( - "Hint: create a failing test file named 'feature-gate-{}.rs'\ - \n in the 'ui' test suite, with its failures due to\ - \n missing usage of `#![feature({})]`.", - name, name + "Hint: create a failing test file named 'tests/ui/feature-gates/feature-gate-{}.rs',\ + \n with its failures due to missing usage of `#![feature({})]`.", + name.replace("_", "-"), + name ); println!( "Hint: If you already have such a test and don't want to rename it,\ diff --git a/src/tools/tidy/src/ui_tests.rs b/src/tools/tidy/src/ui_tests.rs index 55bf38110a6d..3ed587caadc6 100644 --- a/src/tools/tidy/src/ui_tests.rs +++ b/src/tools/tidy/src/ui_tests.rs @@ -11,7 +11,7 @@ use std::path::{Path, PathBuf}; const ENTRY_LIMIT: usize = 900; // FIXME: The following limits should be reduced eventually. const ISSUES_ENTRY_LIMIT: usize = 1896; -const ROOT_ENTRY_LIMIT: usize = 870; +const ROOT_ENTRY_LIMIT: usize = 871; const EXPECTED_TEST_FILE_EXTENSIONS: &[&str] = &[ "rs", // test source files diff --git a/tests/codegen/issues/issue-111603.rs b/tests/codegen/issues/issue-111603.rs index 90b3c314d2f4..06429ed3fa9b 100644 --- a/tests/codegen/issues/issue-111603.rs +++ b/tests/codegen/issues/issue-111603.rs @@ -5,6 +5,18 @@ use std::sync::Arc; +// CHECK-LABEL: @new_from_array +#[no_mangle] +pub fn new_from_array(x: u64) -> Arc<[u64]> { + // Ensure that we only generate one alloca for the array. + + // CHECK: alloca + // CHECK-SAME: [1000 x i64] + // CHECK-NOT: alloca + let array = [x; 1000]; + Arc::new(array) +} + // CHECK-LABEL: @new_uninit #[no_mangle] pub fn new_uninit(x: u64) -> Arc<[u64; 1000]> { diff --git a/tests/mir-opt/array_index_is_temporary.main.SimplifyCfg-elaborate-drops.after.panic-unwind.mir b/tests/mir-opt/array_index_is_temporary.main.SimplifyCfg-elaborate-drops.after.panic-unwind.mir index 2f6c92d9e859..4b05610f7310 100644 --- a/tests/mir-opt/array_index_is_temporary.main.SimplifyCfg-elaborate-drops.after.panic-unwind.mir +++ b/tests/mir-opt/array_index_is_temporary.main.SimplifyCfg-elaborate-drops.after.panic-unwind.mir @@ -36,7 +36,7 @@ fn main() -> () { StorageLive(_5); StorageLive(_6); _6 = _3; - _5 = foo(move _6) -> bb1; + _5 = foo(move _6) -> [return: bb1, unwind continue]; } bb1: { @@ -45,7 +45,7 @@ fn main() -> () { _7 = _2; _8 = Len(_1); _9 = Lt(_7, _8); - assert(move _9, "index out of bounds: the length is {} but the index is {}", move _8, _7) -> bb2; + assert(move _9, "index out of bounds: the length is {} but the index is {}", move _8, _7) -> [success: bb2, unwind continue]; } bb2: { diff --git a/tests/mir-opt/basic_assignment.main.ElaborateDrops.diff b/tests/mir-opt/basic_assignment.main.ElaborateDrops.diff index 41732211628e..9c7b3c5197b6 100644 --- a/tests/mir-opt/basic_assignment.main.ElaborateDrops.diff +++ b/tests/mir-opt/basic_assignment.main.ElaborateDrops.diff @@ -58,7 +58,7 @@ bb4: { StorageDead(_5); -- drop(_4) -> bb5; +- drop(_4) -> [return: bb5, unwind continue]; + goto -> bb5; } diff --git a/tests/mir-opt/box_expr.main.ElaborateDrops.before.panic-unwind.mir b/tests/mir-opt/box_expr.main.ElaborateDrops.before.panic-unwind.mir index cf63c4f19dac..a72d22a9c9ff 100644 --- a/tests/mir-opt/box_expr.main.ElaborateDrops.before.panic-unwind.mir +++ b/tests/mir-opt/box_expr.main.ElaborateDrops.before.panic-unwind.mir @@ -19,7 +19,7 @@ fn main() -> () { StorageLive(_1); _2 = SizeOf(S); _3 = AlignOf(S); - _4 = alloc::alloc::exchange_malloc(move _2, move _3) -> bb1; + _4 = alloc::alloc::exchange_malloc(move _2, move _3) -> [return: bb1, unwind continue]; } bb1: { @@ -30,7 +30,7 @@ fn main() -> () { bb2: { _1 = move _5; - drop(_5) -> bb3; + drop(_5) -> [return: bb3, unwind continue]; } bb3: { @@ -45,7 +45,7 @@ fn main() -> () { StorageDead(_7); StorageDead(_6); _0 = const (); - drop(_1) -> bb5; + drop(_1) -> [return: bb5, unwind continue]; } bb5: { diff --git a/tests/mir-opt/building/async_await.a-{closure#0}.generator_resume.0.mir b/tests/mir-opt/building/async_await.a-{closure#0}.generator_resume.0.mir index 7e8206b02fcb..074ebddf78bb 100644 --- a/tests/mir-opt/building/async_await.a-{closure#0}.generator_resume.0.mir +++ b/tests/mir-opt/building/async_await.a-{closure#0}.generator_resume.0.mir @@ -30,7 +30,7 @@ fn a::{closure#0}(_1: Pin<&mut [async fn body@$DIR/async_await.rs:11:14: 11:16]> } bb2: { - assert(const false, "`async fn` resumed after completion") -> bb2; + assert(const false, "`async fn` resumed after completion") -> [success: bb2, unwind continue]; } bb3: { diff --git a/tests/mir-opt/building/async_await.b-{closure#0}.generator_resume.0.mir b/tests/mir-opt/building/async_await.b-{closure#0}.generator_resume.0.mir index ed1388718519..f774f32eb23e 100644 --- a/tests/mir-opt/building/async_await.b-{closure#0}.generator_resume.0.mir +++ b/tests/mir-opt/building/async_await.b-{closure#0}.generator_resume.0.mir @@ -310,7 +310,7 @@ fn b::{closure#0}(_1: Pin<&mut [async fn body@$DIR/async_await.rs:14:18: 17:2]>, } bb28: { - assert(const false, "`async fn` resumed after completion") -> bb28; + assert(const false, "`async fn` resumed after completion") -> [success: bb28, unwind continue]; } bb29: { diff --git a/tests/mir-opt/building/custom/terminators.direct_call.built.after.mir b/tests/mir-opt/building/custom/terminators.direct_call.built.after.mir index 534d7615180a..07044ceaef44 100644 --- a/tests/mir-opt/building/custom/terminators.direct_call.built.after.mir +++ b/tests/mir-opt/building/custom/terminators.direct_call.built.after.mir @@ -4,7 +4,7 @@ fn direct_call(_1: i32) -> i32 { let mut _0: i32; bb0: { - _0 = ident::(_1) -> bb1; + _0 = ident::(_1) -> [return: bb1, unwind continue]; } bb1: { diff --git a/tests/mir-opt/building/custom/terminators.drop_first.built.after.mir b/tests/mir-opt/building/custom/terminators.drop_first.built.after.mir index aba724a4b0d3..6524f754d9c4 100644 --- a/tests/mir-opt/building/custom/terminators.drop_first.built.after.mir +++ b/tests/mir-opt/building/custom/terminators.drop_first.built.after.mir @@ -4,7 +4,7 @@ fn drop_first(_1: WriteOnDrop<'_>, _2: WriteOnDrop<'_>) -> () { let mut _0: (); bb0: { - drop(_1) -> bb1; + drop(_1) -> [return: bb1, unwind continue]; } bb1: { diff --git a/tests/mir-opt/building/custom/terminators.drop_second.built.after.mir b/tests/mir-opt/building/custom/terminators.drop_second.built.after.mir index 32d770bb0c13..ed3728121bd6 100644 --- a/tests/mir-opt/building/custom/terminators.drop_second.built.after.mir +++ b/tests/mir-opt/building/custom/terminators.drop_second.built.after.mir @@ -4,7 +4,7 @@ fn drop_second(_1: WriteOnDrop<'_>, _2: WriteOnDrop<'_>) -> () { let mut _0: (); bb0: { - drop(_2) -> bb1; + drop(_2) -> [return: bb1, unwind continue]; } bb1: { diff --git a/tests/mir-opt/building/custom/terminators.indirect_call.built.after.mir b/tests/mir-opt/building/custom/terminators.indirect_call.built.after.mir index 56371c786660..3b849354dcd8 100644 --- a/tests/mir-opt/building/custom/terminators.indirect_call.built.after.mir +++ b/tests/mir-opt/building/custom/terminators.indirect_call.built.after.mir @@ -4,7 +4,7 @@ fn indirect_call(_1: i32, _2: fn(i32) -> i32) -> i32 { let mut _0: i32; bb0: { - _0 = _2(_1) -> bb1; + _0 = _2(_1) -> [return: bb1, unwind continue]; } bb1: { diff --git a/tests/mir-opt/combine_array_len.norm2.InstSimplify.panic-unwind.diff b/tests/mir-opt/combine_array_len.norm2.InstSimplify.panic-unwind.diff index ab7a34f840d5..4833c1089e3c 100644 --- a/tests/mir-opt/combine_array_len.norm2.InstSimplify.panic-unwind.diff +++ b/tests/mir-opt/combine_array_len.norm2.InstSimplify.panic-unwind.diff @@ -32,7 +32,7 @@ - _4 = Len(_1); + _4 = const 2_usize; _5 = Lt(_3, _4); - assert(move _5, "index out of bounds: the length is {} but the index is {}", move _4, _3) -> bb1; + assert(move _5, "index out of bounds: the length is {} but the index is {}", move _4, _3) -> [success: bb1, unwind continue]; } bb1: { @@ -44,7 +44,7 @@ - _8 = Len(_1); + _8 = const 2_usize; _9 = Lt(_7, _8); - assert(move _9, "index out of bounds: the length is {} but the index is {}", move _8, _7) -> bb2; + assert(move _9, "index out of bounds: the length is {} but the index is {}", move _8, _7) -> [success: bb2, unwind continue]; } bb2: { diff --git a/tests/mir-opt/combine_clone_of_primitives.{impl#0}-clone.InstSimplify.panic-unwind.diff b/tests/mir-opt/combine_clone_of_primitives.{impl#0}-clone.InstSimplify.panic-unwind.diff index ee0f9fbf8289..1a4372afe697 100644 --- a/tests/mir-opt/combine_clone_of_primitives.{impl#0}-clone.InstSimplify.panic-unwind.diff +++ b/tests/mir-opt/combine_clone_of_primitives.{impl#0}-clone.InstSimplify.panic-unwind.diff @@ -21,7 +21,7 @@ _4 = &((*_1).0: T); - _3 = &(*_4); + _3 = _4; - _2 = ::clone(move _3) -> bb1; + _2 = ::clone(move _3) -> [return: bb1, unwind continue]; } bb1: { diff --git a/tests/mir-opt/const_prop/aggregate.main.ConstProp.panic-unwind.diff b/tests/mir-opt/const_prop/aggregate.main.ConstProp.panic-unwind.diff index 73b5baafb332..e4650046bdf1 100644 --- a/tests/mir-opt/const_prop/aggregate.main.ConstProp.panic-unwind.diff +++ b/tests/mir-opt/const_prop/aggregate.main.ConstProp.panic-unwind.diff @@ -27,7 +27,7 @@ StorageLive(_5); - _5 = _1; + _5 = const 1_u8; - _4 = foo(move _5) -> bb1; + _4 = foo(move _5) -> [return: bb1, unwind continue]; } bb1: { diff --git a/tests/mir-opt/const_prop/aggregate.main.PreCodegen.after.panic-unwind.mir b/tests/mir-opt/const_prop/aggregate.main.PreCodegen.after.panic-unwind.mir index 93d461a38c4a..9590c7f90aa3 100644 --- a/tests/mir-opt/const_prop/aggregate.main.PreCodegen.after.panic-unwind.mir +++ b/tests/mir-opt/const_prop/aggregate.main.PreCodegen.after.panic-unwind.mir @@ -23,7 +23,7 @@ fn main() -> () { StorageLive(_4); StorageLive(_5); _5 = const 1_u8; - _4 = foo(move _5) -> bb1; + _4 = foo(move _5) -> [return: bb1, unwind continue]; } bb1: { diff --git a/tests/mir-opt/const_prop/array_index.main.ConstProp.32bit.panic-unwind.diff b/tests/mir-opt/const_prop/array_index.main.ConstProp.32bit.panic-unwind.diff index 9ac2fac6c004..ec11395c3762 100644 --- a/tests/mir-opt/const_prop/array_index.main.ConstProp.32bit.panic-unwind.diff +++ b/tests/mir-opt/const_prop/array_index.main.ConstProp.32bit.panic-unwind.diff @@ -20,10 +20,10 @@ _3 = const 2_usize; - _4 = Len(_2); - _5 = Lt(_3, _4); -- assert(move _5, "index out of bounds: the length is {} but the index is {}", move _4, _3) -> bb1; +- assert(move _5, "index out of bounds: the length is {} but the index is {}", move _4, _3) -> [success: bb1, unwind continue]; + _4 = const 4_usize; + _5 = const true; -+ assert(const true, "index out of bounds: the length is {} but the index is {}", move _4, _3) -> bb1; ++ assert(const true, "index out of bounds: the length is {} but the index is {}", move _4, _3) -> [success: bb1, unwind continue]; } bb1: { diff --git a/tests/mir-opt/const_prop/array_index.main.ConstProp.64bit.panic-unwind.diff b/tests/mir-opt/const_prop/array_index.main.ConstProp.64bit.panic-unwind.diff index 9ac2fac6c004..ec11395c3762 100644 --- a/tests/mir-opt/const_prop/array_index.main.ConstProp.64bit.panic-unwind.diff +++ b/tests/mir-opt/const_prop/array_index.main.ConstProp.64bit.panic-unwind.diff @@ -20,10 +20,10 @@ _3 = const 2_usize; - _4 = Len(_2); - _5 = Lt(_3, _4); -- assert(move _5, "index out of bounds: the length is {} but the index is {}", move _4, _3) -> bb1; +- assert(move _5, "index out of bounds: the length is {} but the index is {}", move _4, _3) -> [success: bb1, unwind continue]; + _4 = const 4_usize; + _5 = const true; -+ assert(const true, "index out of bounds: the length is {} but the index is {}", move _4, _3) -> bb1; ++ assert(const true, "index out of bounds: the length is {} but the index is {}", move _4, _3) -> [success: bb1, unwind continue]; } bb1: { diff --git a/tests/mir-opt/const_prop/bad_op_div_by_zero.main.ConstProp.panic-unwind.diff b/tests/mir-opt/const_prop/bad_op_div_by_zero.main.ConstProp.panic-unwind.diff index 2aff357cc3e6..a5b51681ec97 100644 --- a/tests/mir-opt/const_prop/bad_op_div_by_zero.main.ConstProp.panic-unwind.diff +++ b/tests/mir-opt/const_prop/bad_op_div_by_zero.main.ConstProp.panic-unwind.diff @@ -24,21 +24,21 @@ StorageLive(_3); - _3 = _1; - _4 = Eq(_3, const 0_i32); -- assert(!move _4, "attempt to divide `{}` by zero", const 1_i32) -> bb1; +- assert(!move _4, "attempt to divide `{}` by zero", const 1_i32) -> [success: bb1, unwind continue]; + _3 = const 0_i32; + _4 = const true; -+ assert(!const true, "attempt to divide `{}` by zero", const 1_i32) -> bb1; ++ assert(!const true, "attempt to divide `{}` by zero", const 1_i32) -> [success: bb1, unwind continue]; } bb1: { - _5 = Eq(_3, const -1_i32); - _6 = Eq(const 1_i32, const i32::MIN); - _7 = BitAnd(move _5, move _6); -- assert(!move _7, "attempt to compute `{} / {}`, which would overflow", const 1_i32, _3) -> bb2; +- assert(!move _7, "attempt to compute `{} / {}`, which would overflow", const 1_i32, _3) -> [success: bb2, unwind continue]; + _5 = const false; + _6 = const false; + _7 = const false; -+ assert(!const false, "attempt to compute `{} / {}`, which would overflow", const 1_i32, _3) -> bb2; ++ assert(!const false, "attempt to compute `{} / {}`, which would overflow", const 1_i32, _3) -> [success: bb2, unwind continue]; } bb2: { diff --git a/tests/mir-opt/const_prop/bad_op_mod_by_zero.main.ConstProp.panic-unwind.diff b/tests/mir-opt/const_prop/bad_op_mod_by_zero.main.ConstProp.panic-unwind.diff index db93de9630b5..4afddf3c92d7 100644 --- a/tests/mir-opt/const_prop/bad_op_mod_by_zero.main.ConstProp.panic-unwind.diff +++ b/tests/mir-opt/const_prop/bad_op_mod_by_zero.main.ConstProp.panic-unwind.diff @@ -24,21 +24,21 @@ StorageLive(_3); - _3 = _1; - _4 = Eq(_3, const 0_i32); -- assert(!move _4, "attempt to calculate the remainder of `{}` with a divisor of zero", const 1_i32) -> bb1; +- assert(!move _4, "attempt to calculate the remainder of `{}` with a divisor of zero", const 1_i32) -> [success: bb1, unwind continue]; + _3 = const 0_i32; + _4 = const true; -+ assert(!const true, "attempt to calculate the remainder of `{}` with a divisor of zero", const 1_i32) -> bb1; ++ assert(!const true, "attempt to calculate the remainder of `{}` with a divisor of zero", const 1_i32) -> [success: bb1, unwind continue]; } bb1: { - _5 = Eq(_3, const -1_i32); - _6 = Eq(const 1_i32, const i32::MIN); - _7 = BitAnd(move _5, move _6); -- assert(!move _7, "attempt to compute the remainder of `{} % {}`, which would overflow", const 1_i32, _3) -> bb2; +- assert(!move _7, "attempt to compute the remainder of `{} % {}`, which would overflow", const 1_i32, _3) -> [success: bb2, unwind continue]; + _5 = const false; + _6 = const false; + _7 = const false; -+ assert(!const false, "attempt to compute the remainder of `{} % {}`, which would overflow", const 1_i32, _3) -> bb2; ++ assert(!const false, "attempt to compute the remainder of `{} % {}`, which would overflow", const 1_i32, _3) -> [success: bb2, unwind continue]; } bb2: { diff --git a/tests/mir-opt/const_prop/bad_op_unsafe_oob_for_slices.main.ConstProp.32bit.panic-unwind.diff b/tests/mir-opt/const_prop/bad_op_unsafe_oob_for_slices.main.ConstProp.32bit.panic-unwind.diff index f39468d9684b..2c0e4844ecc3 100644 --- a/tests/mir-opt/const_prop/bad_op_unsafe_oob_for_slices.main.ConstProp.32bit.panic-unwind.diff +++ b/tests/mir-opt/const_prop/bad_op_unsafe_oob_for_slices.main.ConstProp.32bit.panic-unwind.diff @@ -36,9 +36,9 @@ _6 = const 3_usize; _7 = const 3_usize; - _8 = Lt(_6, _7); -- assert(move _8, "index out of bounds: the length is {} but the index is {}", move _7, _6) -> bb1; +- assert(move _8, "index out of bounds: the length is {} but the index is {}", move _7, _6) -> [success: bb1, unwind continue]; + _8 = const false; -+ assert(const false, "index out of bounds: the length is {} but the index is {}", move _7, _6) -> bb1; ++ assert(const false, "index out of bounds: the length is {} but the index is {}", move _7, _6) -> [success: bb1, unwind continue]; } bb1: { diff --git a/tests/mir-opt/const_prop/bad_op_unsafe_oob_for_slices.main.ConstProp.64bit.panic-unwind.diff b/tests/mir-opt/const_prop/bad_op_unsafe_oob_for_slices.main.ConstProp.64bit.panic-unwind.diff index f39468d9684b..2c0e4844ecc3 100644 --- a/tests/mir-opt/const_prop/bad_op_unsafe_oob_for_slices.main.ConstProp.64bit.panic-unwind.diff +++ b/tests/mir-opt/const_prop/bad_op_unsafe_oob_for_slices.main.ConstProp.64bit.panic-unwind.diff @@ -36,9 +36,9 @@ _6 = const 3_usize; _7 = const 3_usize; - _8 = Lt(_6, _7); -- assert(move _8, "index out of bounds: the length is {} but the index is {}", move _7, _6) -> bb1; +- assert(move _8, "index out of bounds: the length is {} but the index is {}", move _7, _6) -> [success: bb1, unwind continue]; + _8 = const false; -+ assert(const false, "index out of bounds: the length is {} but the index is {}", move _7, _6) -> bb1; ++ assert(const false, "index out of bounds: the length is {} but the index is {}", move _7, _6) -> [success: bb1, unwind continue]; } bb1: { diff --git a/tests/mir-opt/const_prop/boxes.main.ConstProp.panic-unwind.diff b/tests/mir-opt/const_prop/boxes.main.ConstProp.panic-unwind.diff index 8e3c2f6c8448..6214766c7ee5 100644 --- a/tests/mir-opt/const_prop/boxes.main.ConstProp.panic-unwind.diff +++ b/tests/mir-opt/const_prop/boxes.main.ConstProp.panic-unwind.diff @@ -26,7 +26,7 @@ - _5 = AlignOf(i32); + _4 = const 4_usize; + _5 = const 4_usize; - _6 = alloc::alloc::exchange_malloc(move _4, move _5) -> bb1; + _6 = alloc::alloc::exchange_malloc(move _4, move _5) -> [return: bb1, unwind continue]; } bb1: { diff --git a/tests/mir-opt/const_prop/checked_add.main.ConstProp.panic-unwind.diff b/tests/mir-opt/const_prop/checked_add.main.ConstProp.panic-unwind.diff index 175e2b51a37c..125407bf285a 100644 --- a/tests/mir-opt/const_prop/checked_add.main.ConstProp.panic-unwind.diff +++ b/tests/mir-opt/const_prop/checked_add.main.ConstProp.panic-unwind.diff @@ -12,9 +12,9 @@ bb0: { StorageLive(_1); - _2 = CheckedAdd(const 1_u32, const 1_u32); -- assert(!move (_2.1: bool), "attempt to compute `{} + {}`, which would overflow", const 1_u32, const 1_u32) -> bb1; +- assert(!move (_2.1: bool), "attempt to compute `{} + {}`, which would overflow", const 1_u32, const 1_u32) -> [success: bb1, unwind continue]; + _2 = const (2_u32, false); -+ assert(!const false, "attempt to compute `{} + {}`, which would overflow", const 1_u32, const 1_u32) -> bb1; ++ assert(!const false, "attempt to compute `{} + {}`, which would overflow", const 1_u32, const 1_u32) -> [success: bb1, unwind continue]; } bb1: { diff --git a/tests/mir-opt/const_prop/const_prop_fails_gracefully.main.ConstProp.panic-unwind.diff b/tests/mir-opt/const_prop/const_prop_fails_gracefully.main.ConstProp.panic-unwind.diff index 01ec24916c89..850b743feb1c 100644 --- a/tests/mir-opt/const_prop/const_prop_fails_gracefully.main.ConstProp.panic-unwind.diff +++ b/tests/mir-opt/const_prop/const_prop_fails_gracefully.main.ConstProp.panic-unwind.diff @@ -24,7 +24,7 @@ StorageLive(_4); StorageLive(_5); _5 = _1; - _4 = read(move _5) -> bb1; + _4 = read(move _5) -> [return: bb1, unwind continue]; } bb1: { diff --git a/tests/mir-opt/const_prop/control_flow_simplification.hello.ConstProp.panic-unwind.diff b/tests/mir-opt/const_prop/control_flow_simplification.hello.ConstProp.panic-unwind.diff index 4593ffaac2bd..7496d2543097 100644 --- a/tests/mir-opt/const_prop/control_flow_simplification.hello.ConstProp.panic-unwind.diff +++ b/tests/mir-opt/const_prop/control_flow_simplification.hello.ConstProp.panic-unwind.diff @@ -14,7 +14,7 @@ } bb1: { - _2 = begin_panic::<&str>(const "explicit panic"); + _2 = begin_panic::<&str>(const "explicit panic") -> unwind continue; } bb2: { diff --git a/tests/mir-opt/const_prop/indirect.main.ConstProp.panic-unwind.diff b/tests/mir-opt/const_prop/indirect.main.ConstProp.panic-unwind.diff index affef00bb732..ccfa35f001b5 100644 --- a/tests/mir-opt/const_prop/indirect.main.ConstProp.panic-unwind.diff +++ b/tests/mir-opt/const_prop/indirect.main.ConstProp.panic-unwind.diff @@ -15,10 +15,10 @@ StorageLive(_2); - _2 = const 2_u32 as u8 (IntToInt); - _3 = CheckedAdd(_2, const 1_u8); -- assert(!move (_3.1: bool), "attempt to compute `{} + {}`, which would overflow", move _2, const 1_u8) -> bb1; +- assert(!move (_3.1: bool), "attempt to compute `{} + {}`, which would overflow", move _2, const 1_u8) -> [success: bb1, unwind continue]; + _2 = const 2_u8; + _3 = const (3_u8, false); -+ assert(!const false, "attempt to compute `{} + {}`, which would overflow", move _2, const 1_u8) -> bb1; ++ assert(!const false, "attempt to compute `{} + {}`, which would overflow", move _2, const 1_u8) -> [success: bb1, unwind continue]; } bb1: { diff --git a/tests/mir-opt/const_prop/inherit_overflow.main.ConstProp.panic-unwind.diff b/tests/mir-opt/const_prop/inherit_overflow.main.ConstProp.panic-unwind.diff index 9dae4b404aad..4f8e0f0f599b 100644 --- a/tests/mir-opt/const_prop/inherit_overflow.main.ConstProp.panic-unwind.diff +++ b/tests/mir-opt/const_prop/inherit_overflow.main.ConstProp.panic-unwind.diff @@ -21,9 +21,9 @@ StorageLive(_3); _3 = const 1_u8; - _4 = CheckedAdd(_2, _3); -- assert(!move (_4.1: bool), "attempt to compute `{} + {}`, which would overflow", _2, _3) -> bb1; +- assert(!move (_4.1: bool), "attempt to compute `{} + {}`, which would overflow", _2, _3) -> [success: bb1, unwind continue]; + _4 = const (0_u8, true); -+ assert(!const true, "attempt to compute `{} + {}`, which would overflow", _2, _3) -> bb1; ++ assert(!const true, "attempt to compute `{} + {}`, which would overflow", _2, _3) -> [success: bb1, unwind continue]; } bb1: { diff --git a/tests/mir-opt/const_prop/issue_66971.main.ConstProp.panic-unwind.diff b/tests/mir-opt/const_prop/issue_66971.main.ConstProp.panic-unwind.diff index e83c18735b61..5e3443228cd2 100644 --- a/tests/mir-opt/const_prop/issue_66971.main.ConstProp.panic-unwind.diff +++ b/tests/mir-opt/const_prop/issue_66971.main.ConstProp.panic-unwind.diff @@ -9,7 +9,7 @@ bb0: { StorageLive(_2); _2 = (const (), const 0_u8, const 0_u8); - _1 = encode(move _2) -> bb1; + _1 = encode(move _2) -> [return: bb1, unwind continue]; } bb1: { diff --git a/tests/mir-opt/const_prop/issue_67019.main.ConstProp.panic-unwind.diff b/tests/mir-opt/const_prop/issue_67019.main.ConstProp.panic-unwind.diff index cbbc2582973a..95776030162e 100644 --- a/tests/mir-opt/const_prop/issue_67019.main.ConstProp.panic-unwind.diff +++ b/tests/mir-opt/const_prop/issue_67019.main.ConstProp.panic-unwind.diff @@ -14,7 +14,7 @@ + _3 = const (1_u8, 2_u8); _2 = (move _3,); StorageDead(_3); - _1 = test(move _2) -> bb1; + _1 = test(move _2) -> [return: bb1, unwind continue]; } bb1: { diff --git a/tests/mir-opt/const_prop/large_array_index.main.ConstProp.32bit.panic-unwind.diff b/tests/mir-opt/const_prop/large_array_index.main.ConstProp.32bit.panic-unwind.diff index be245b424c14..658607116c87 100644 --- a/tests/mir-opt/const_prop/large_array_index.main.ConstProp.32bit.panic-unwind.diff +++ b/tests/mir-opt/const_prop/large_array_index.main.ConstProp.32bit.panic-unwind.diff @@ -20,10 +20,10 @@ _3 = const 2_usize; - _4 = Len(_2); - _5 = Lt(_3, _4); -- assert(move _5, "index out of bounds: the length is {} but the index is {}", move _4, _3) -> bb1; +- assert(move _5, "index out of bounds: the length is {} but the index is {}", move _4, _3) -> [success: bb1, unwind continue]; + _4 = const 5000_usize; + _5 = const true; -+ assert(const true, "index out of bounds: the length is {} but the index is {}", move _4, _3) -> bb1; ++ assert(const true, "index out of bounds: the length is {} but the index is {}", move _4, _3) -> [success: bb1, unwind continue]; } bb1: { diff --git a/tests/mir-opt/const_prop/large_array_index.main.ConstProp.64bit.panic-unwind.diff b/tests/mir-opt/const_prop/large_array_index.main.ConstProp.64bit.panic-unwind.diff index be245b424c14..658607116c87 100644 --- a/tests/mir-opt/const_prop/large_array_index.main.ConstProp.64bit.panic-unwind.diff +++ b/tests/mir-opt/const_prop/large_array_index.main.ConstProp.64bit.panic-unwind.diff @@ -20,10 +20,10 @@ _3 = const 2_usize; - _4 = Len(_2); - _5 = Lt(_3, _4); -- assert(move _5, "index out of bounds: the length is {} but the index is {}", move _4, _3) -> bb1; +- assert(move _5, "index out of bounds: the length is {} but the index is {}", move _4, _3) -> [success: bb1, unwind continue]; + _4 = const 5000_usize; + _5 = const true; -+ assert(const true, "index out of bounds: the length is {} but the index is {}", move _4, _3) -> bb1; ++ assert(const true, "index out of bounds: the length is {} but the index is {}", move _4, _3) -> [success: bb1, unwind continue]; } bb1: { diff --git a/tests/mir-opt/const_prop/mutable_variable_aggregate_partial_read.main.ConstProp.panic-unwind.diff b/tests/mir-opt/const_prop/mutable_variable_aggregate_partial_read.main.ConstProp.panic-unwind.diff index 50006f5f5b5a..7ba2b483dc3f 100644 --- a/tests/mir-opt/const_prop/mutable_variable_aggregate_partial_read.main.ConstProp.panic-unwind.diff +++ b/tests/mir-opt/const_prop/mutable_variable_aggregate_partial_read.main.ConstProp.panic-unwind.diff @@ -14,7 +14,7 @@ bb0: { StorageLive(_1); - _1 = foo() -> bb1; + _1 = foo() -> [return: bb1, unwind continue]; } bb1: { diff --git a/tests/mir-opt/const_prop/mutable_variable_unprop_assign.main.ConstProp.panic-unwind.diff b/tests/mir-opt/const_prop/mutable_variable_unprop_assign.main.ConstProp.panic-unwind.diff index 69a0c3e2429e..15ef0fa4dfff 100644 --- a/tests/mir-opt/const_prop/mutable_variable_unprop_assign.main.ConstProp.panic-unwind.diff +++ b/tests/mir-opt/const_prop/mutable_variable_unprop_assign.main.ConstProp.panic-unwind.diff @@ -23,7 +23,7 @@ bb0: { StorageLive(_1); - _1 = foo() -> bb1; + _1 = foo() -> [return: bb1, unwind continue]; } bb1: { diff --git a/tests/mir-opt/const_prop/offset_of.concrete.ConstProp.panic-unwind.diff b/tests/mir-opt/const_prop/offset_of.concrete.ConstProp.panic-unwind.diff index 29cad611b540..bbb807d8fcdc 100644 --- a/tests/mir-opt/const_prop/offset_of.concrete.ConstProp.panic-unwind.diff +++ b/tests/mir-opt/const_prop/offset_of.concrete.ConstProp.panic-unwind.diff @@ -29,7 +29,7 @@ StorageLive(_2); - _2 = OffsetOf(Alpha, [0]); + _2 = const 4_usize; - _1 = must_use::(move _2) -> bb1; + _1 = must_use::(move _2) -> [return: bb1, unwind continue]; } bb1: { @@ -38,7 +38,7 @@ StorageLive(_4); - _4 = OffsetOf(Alpha, [1]); + _4 = const 0_usize; - _3 = must_use::(move _4) -> bb2; + _3 = must_use::(move _4) -> [return: bb2, unwind continue]; } bb2: { @@ -47,7 +47,7 @@ StorageLive(_6); - _6 = OffsetOf(Alpha, [2, 0]); + _6 = const 2_usize; - _5 = must_use::(move _6) -> bb3; + _5 = must_use::(move _6) -> [return: bb3, unwind continue]; } bb3: { @@ -56,7 +56,7 @@ StorageLive(_8); - _8 = OffsetOf(Alpha, [2, 1]); + _8 = const 3_usize; - _7 = must_use::(move _8) -> bb4; + _7 = must_use::(move _8) -> [return: bb4, unwind continue]; } bb4: { diff --git a/tests/mir-opt/const_prop/offset_of.generic.ConstProp.panic-unwind.diff b/tests/mir-opt/const_prop/offset_of.generic.ConstProp.panic-unwind.diff index 2a58a1a5ceb4..fd5206e460c6 100644 --- a/tests/mir-opt/const_prop/offset_of.generic.ConstProp.panic-unwind.diff +++ b/tests/mir-opt/const_prop/offset_of.generic.ConstProp.panic-unwind.diff @@ -28,7 +28,7 @@ StorageLive(_1); StorageLive(_2); _2 = OffsetOf(Gamma, [0]); - _1 = must_use::(move _2) -> bb1; + _1 = must_use::(move _2) -> [return: bb1, unwind continue]; } bb1: { @@ -36,7 +36,7 @@ StorageLive(_3); StorageLive(_4); _4 = OffsetOf(Gamma, [1]); - _3 = must_use::(move _4) -> bb2; + _3 = must_use::(move _4) -> [return: bb2, unwind continue]; } bb2: { @@ -44,7 +44,7 @@ StorageLive(_5); StorageLive(_6); _6 = OffsetOf(Delta, [1]); - _5 = must_use::(move _6) -> bb3; + _5 = must_use::(move _6) -> [return: bb3, unwind continue]; } bb3: { @@ -52,7 +52,7 @@ StorageLive(_7); StorageLive(_8); _8 = OffsetOf(Delta, [2]); - _7 = must_use::(move _8) -> bb4; + _7 = must_use::(move _8) -> [return: bb4, unwind continue]; } bb4: { diff --git a/tests/mir-opt/const_prop/repeat.main.ConstProp.32bit.panic-unwind.diff b/tests/mir-opt/const_prop/repeat.main.ConstProp.32bit.panic-unwind.diff index f94708605eef..571f279a8c14 100644 --- a/tests/mir-opt/const_prop/repeat.main.ConstProp.32bit.panic-unwind.diff +++ b/tests/mir-opt/const_prop/repeat.main.ConstProp.32bit.panic-unwind.diff @@ -22,10 +22,10 @@ _4 = const 2_usize; - _5 = Len(_3); - _6 = Lt(_4, _5); -- assert(move _6, "index out of bounds: the length is {} but the index is {}", move _5, _4) -> bb1; +- assert(move _6, "index out of bounds: the length is {} but the index is {}", move _5, _4) -> [success: bb1, unwind continue]; + _5 = const 8_usize; + _6 = const true; -+ assert(const true, "index out of bounds: the length is {} but the index is {}", move _5, _4) -> bb1; ++ assert(const true, "index out of bounds: the length is {} but the index is {}", move _5, _4) -> [success: bb1, unwind continue]; } bb1: { diff --git a/tests/mir-opt/const_prop/repeat.main.ConstProp.64bit.panic-unwind.diff b/tests/mir-opt/const_prop/repeat.main.ConstProp.64bit.panic-unwind.diff index f94708605eef..571f279a8c14 100644 --- a/tests/mir-opt/const_prop/repeat.main.ConstProp.64bit.panic-unwind.diff +++ b/tests/mir-opt/const_prop/repeat.main.ConstProp.64bit.panic-unwind.diff @@ -22,10 +22,10 @@ _4 = const 2_usize; - _5 = Len(_3); - _6 = Lt(_4, _5); -- assert(move _6, "index out of bounds: the length is {} but the index is {}", move _5, _4) -> bb1; +- assert(move _6, "index out of bounds: the length is {} but the index is {}", move _5, _4) -> [success: bb1, unwind continue]; + _5 = const 8_usize; + _6 = const true; -+ assert(const true, "index out of bounds: the length is {} but the index is {}", move _5, _4) -> bb1; ++ assert(const true, "index out of bounds: the length is {} but the index is {}", move _5, _4) -> [success: bb1, unwind continue]; } bb1: { diff --git a/tests/mir-opt/const_prop/return_place.add.ConstProp.panic-unwind.diff b/tests/mir-opt/const_prop/return_place.add.ConstProp.panic-unwind.diff index f89e9dd5b635..79f85fcef110 100644 --- a/tests/mir-opt/const_prop/return_place.add.ConstProp.panic-unwind.diff +++ b/tests/mir-opt/const_prop/return_place.add.ConstProp.panic-unwind.diff @@ -7,9 +7,9 @@ bb0: { - _1 = CheckedAdd(const 2_u32, const 2_u32); -- assert(!move (_1.1: bool), "attempt to compute `{} + {}`, which would overflow", const 2_u32, const 2_u32) -> bb1; +- assert(!move (_1.1: bool), "attempt to compute `{} + {}`, which would overflow", const 2_u32, const 2_u32) -> [success: bb1, unwind continue]; + _1 = const (4_u32, false); -+ assert(!const false, "attempt to compute `{} + {}`, which would overflow", const 2_u32, const 2_u32) -> bb1; ++ assert(!const false, "attempt to compute `{} + {}`, which would overflow", const 2_u32, const 2_u32) -> [success: bb1, unwind continue]; } bb1: { diff --git a/tests/mir-opt/const_prop/return_place.add.PreCodegen.before.panic-unwind.mir b/tests/mir-opt/const_prop/return_place.add.PreCodegen.before.panic-unwind.mir index 148f16c7ee2d..9a0646974636 100644 --- a/tests/mir-opt/const_prop/return_place.add.PreCodegen.before.panic-unwind.mir +++ b/tests/mir-opt/const_prop/return_place.add.PreCodegen.before.panic-unwind.mir @@ -6,7 +6,7 @@ fn add() -> u32 { bb0: { _1 = const (4_u32, false); - assert(!const false, "attempt to compute `{} + {}`, which would overflow", const 2_u32, const 2_u32) -> bb1; + assert(!const false, "attempt to compute `{} + {}`, which would overflow", const 2_u32, const 2_u32) -> [success: bb1, unwind continue]; } bb1: { diff --git a/tests/mir-opt/const_prop/scalar_literal_propagation.main.ConstProp.panic-unwind.diff b/tests/mir-opt/const_prop/scalar_literal_propagation.main.ConstProp.panic-unwind.diff index d7d6e8e435e2..a7d7a7224cea 100644 --- a/tests/mir-opt/const_prop/scalar_literal_propagation.main.ConstProp.panic-unwind.diff +++ b/tests/mir-opt/const_prop/scalar_literal_propagation.main.ConstProp.panic-unwind.diff @@ -17,7 +17,7 @@ StorageLive(_3); - _3 = _1; + _3 = const 1_u32; - _2 = consume(move _3) -> bb1; + _2 = consume(move _3) -> [return: bb1, unwind continue]; } bb1: { diff --git a/tests/mir-opt/const_prop/slice_len.main.ConstProp.32bit.panic-unwind.diff b/tests/mir-opt/const_prop/slice_len.main.ConstProp.32bit.panic-unwind.diff index b07ec0ad5025..c0f290a9ab49 100644 --- a/tests/mir-opt/const_prop/slice_len.main.ConstProp.32bit.panic-unwind.diff +++ b/tests/mir-opt/const_prop/slice_len.main.ConstProp.32bit.panic-unwind.diff @@ -27,10 +27,10 @@ _6 = const 1_usize; - _7 = Len((*_2)); - _8 = Lt(_6, _7); -- assert(move _8, "index out of bounds: the length is {} but the index is {}", move _7, _6) -> bb1; +- assert(move _8, "index out of bounds: the length is {} but the index is {}", move _7, _6) -> [success: bb1, unwind continue]; + _7 = const 3_usize; + _8 = const true; -+ assert(const true, "index out of bounds: the length is {} but the index is {}", move _7, _6) -> bb1; ++ assert(const true, "index out of bounds: the length is {} but the index is {}", move _7, _6) -> [success: bb1, unwind continue]; } bb1: { diff --git a/tests/mir-opt/const_prop/slice_len.main.ConstProp.64bit.panic-unwind.diff b/tests/mir-opt/const_prop/slice_len.main.ConstProp.64bit.panic-unwind.diff index b07ec0ad5025..c0f290a9ab49 100644 --- a/tests/mir-opt/const_prop/slice_len.main.ConstProp.64bit.panic-unwind.diff +++ b/tests/mir-opt/const_prop/slice_len.main.ConstProp.64bit.panic-unwind.diff @@ -27,10 +27,10 @@ _6 = const 1_usize; - _7 = Len((*_2)); - _8 = Lt(_6, _7); -- assert(move _8, "index out of bounds: the length is {} but the index is {}", move _7, _6) -> bb1; +- assert(move _8, "index out of bounds: the length is {} but the index is {}", move _7, _6) -> [success: bb1, unwind continue]; + _7 = const 3_usize; + _8 = const true; -+ assert(const true, "index out of bounds: the length is {} but the index is {}", move _7, _6) -> bb1; ++ assert(const true, "index out of bounds: the length is {} but the index is {}", move _7, _6) -> [success: bb1, unwind continue]; } bb1: { diff --git a/tests/mir-opt/const_prop/switch_int.main.ConstProp.panic-unwind.diff b/tests/mir-opt/const_prop/switch_int.main.ConstProp.panic-unwind.diff index 02dca4d3dea5..1ce28e979a5b 100644 --- a/tests/mir-opt/const_prop/switch_int.main.ConstProp.panic-unwind.diff +++ b/tests/mir-opt/const_prop/switch_int.main.ConstProp.panic-unwind.diff @@ -13,11 +13,11 @@ } bb1: { - _0 = foo(const -1_i32) -> bb3; + _0 = foo(const -1_i32) -> [return: bb3, unwind continue]; } bb2: { - _0 = foo(const 0_i32) -> bb3; + _0 = foo(const 0_i32) -> [return: bb3, unwind continue]; } bb3: { diff --git a/tests/mir-opt/const_prop/switch_int.main.SimplifyConstCondition-after-const-prop.panic-unwind.diff b/tests/mir-opt/const_prop/switch_int.main.SimplifyConstCondition-after-const-prop.panic-unwind.diff index 72ce94e14295..e598a0d3df00 100644 --- a/tests/mir-opt/const_prop/switch_int.main.SimplifyConstCondition-after-const-prop.panic-unwind.diff +++ b/tests/mir-opt/const_prop/switch_int.main.SimplifyConstCondition-after-const-prop.panic-unwind.diff @@ -13,11 +13,11 @@ } bb1: { - _0 = foo(const -1_i32) -> bb3; + _0 = foo(const -1_i32) -> [return: bb3, unwind continue]; } bb2: { - _0 = foo(const 0_i32) -> bb3; + _0 = foo(const 0_i32) -> [return: bb3, unwind continue]; } bb3: { diff --git a/tests/mir-opt/const_prop/tuple_literal_propagation.main.ConstProp.panic-unwind.diff b/tests/mir-opt/const_prop/tuple_literal_propagation.main.ConstProp.panic-unwind.diff index d44c69ca4403..6255f9ec5962 100644 --- a/tests/mir-opt/const_prop/tuple_literal_propagation.main.ConstProp.panic-unwind.diff +++ b/tests/mir-opt/const_prop/tuple_literal_propagation.main.ConstProp.panic-unwind.diff @@ -18,7 +18,7 @@ StorageLive(_3); - _3 = _1; + _3 = const (1_u32, 2_u32); - _2 = consume(move _3) -> bb1; + _2 = consume(move _3) -> [return: bb1, unwind continue]; } bb1: { diff --git a/tests/mir-opt/copy-prop/borrowed_local.f.CopyProp.panic-unwind.diff b/tests/mir-opt/copy-prop/borrowed_local.f.CopyProp.panic-unwind.diff index 074f82702418..b702e3b7d1ed 100644 --- a/tests/mir-opt/copy-prop/borrowed_local.f.CopyProp.panic-unwind.diff +++ b/tests/mir-opt/copy-prop/borrowed_local.f.CopyProp.panic-unwind.diff @@ -13,11 +13,11 @@ _2 = &_1; _3 = _1; _4 = &_3; - _0 = cmp_ref(_2, _4) -> bb1; + _0 = cmp_ref(_2, _4) -> [return: bb1, unwind continue]; } bb1: { - _0 = opaque::(_3) -> bb2; + _0 = opaque::(_3) -> [return: bb2, unwind continue]; } bb2: { diff --git a/tests/mir-opt/copy-prop/branch.foo.CopyProp.panic-unwind.diff b/tests/mir-opt/copy-prop/branch.foo.CopyProp.panic-unwind.diff index 0dcc5cef7340..2f92d8818cff 100644 --- a/tests/mir-opt/copy-prop/branch.foo.CopyProp.panic-unwind.diff +++ b/tests/mir-opt/copy-prop/branch.foo.CopyProp.panic-unwind.diff @@ -16,13 +16,13 @@ bb0: { StorageLive(_1); - _1 = val() -> bb1; + _1 = val() -> [return: bb1, unwind continue]; } bb1: { StorageLive(_2); StorageLive(_3); - _3 = cond() -> bb2; + _3 = cond() -> [return: bb2, unwind continue]; } bb2: { @@ -36,7 +36,7 @@ bb4: { StorageLive(_4); - _4 = val() -> bb5; + _4 = val() -> [return: bb5, unwind continue]; } bb5: { diff --git a/tests/mir-opt/copy-prop/copy_propagation_arg.bar.CopyProp.panic-unwind.diff b/tests/mir-opt/copy-prop/copy_propagation_arg.bar.CopyProp.panic-unwind.diff index 95c1c12ee692..ef9c343a264d 100644 --- a/tests/mir-opt/copy-prop/copy_propagation_arg.bar.CopyProp.panic-unwind.diff +++ b/tests/mir-opt/copy-prop/copy_propagation_arg.bar.CopyProp.panic-unwind.diff @@ -11,7 +11,7 @@ StorageLive(_2); StorageLive(_3); _3 = _1; - _2 = dummy(move _3) -> bb1; + _2 = dummy(move _3) -> [return: bb1, unwind continue]; } bb1: { diff --git a/tests/mir-opt/copy-prop/copy_propagation_arg.foo.CopyProp.panic-unwind.diff b/tests/mir-opt/copy-prop/copy_propagation_arg.foo.CopyProp.panic-unwind.diff index e16d6220ef2c..769089e16f34 100644 --- a/tests/mir-opt/copy-prop/copy_propagation_arg.foo.CopyProp.panic-unwind.diff +++ b/tests/mir-opt/copy-prop/copy_propagation_arg.foo.CopyProp.panic-unwind.diff @@ -11,7 +11,7 @@ StorageLive(_2); StorageLive(_3); _3 = _1; - _2 = dummy(move _3) -> bb1; + _2 = dummy(move _3) -> [return: bb1, unwind continue]; } bb1: { diff --git a/tests/mir-opt/copy-prop/custom_move_arg.f.CopyProp.panic-unwind.diff b/tests/mir-opt/copy-prop/custom_move_arg.f.CopyProp.panic-unwind.diff index 2d7e34f2d6e3..eb40183c1c95 100644 --- a/tests/mir-opt/copy-prop/custom_move_arg.f.CopyProp.panic-unwind.diff +++ b/tests/mir-opt/copy-prop/custom_move_arg.f.CopyProp.panic-unwind.diff @@ -8,14 +8,14 @@ bb0: { - _2 = _1; -- _0 = opaque::(move _1) -> bb1; -+ _0 = opaque::(_1) -> bb1; +- _0 = opaque::(move _1) -> [return: bb1, unwind continue]; ++ _0 = opaque::(_1) -> [return: bb1, unwind continue]; } bb1: { - _3 = move _2; -- _0 = opaque::(_3) -> bb2; -+ _0 = opaque::(_1) -> bb2; +- _0 = opaque::(_3) -> [return: bb2, unwind continue]; ++ _0 = opaque::(_1) -> [return: bb2, unwind continue]; } bb2: { diff --git a/tests/mir-opt/copy-prop/cycle.main.CopyProp.panic-unwind.diff b/tests/mir-opt/copy-prop/cycle.main.CopyProp.panic-unwind.diff index bf9e941c7b65..e343b78924ab 100644 --- a/tests/mir-opt/copy-prop/cycle.main.CopyProp.panic-unwind.diff +++ b/tests/mir-opt/copy-prop/cycle.main.CopyProp.panic-unwind.diff @@ -22,7 +22,7 @@ bb0: { StorageLive(_1); - _1 = val() -> bb1; + _1 = val() -> [return: bb1, unwind continue]; } bb1: { @@ -38,7 +38,7 @@ StorageLive(_5); StorageLive(_6); _6 = _1; - _5 = std::mem::drop::(move _6) -> bb2; + _5 = std::mem::drop::(move _6) -> [return: bb2, unwind continue]; } bb2: { diff --git a/tests/mir-opt/copy-prop/dead_stores_79191.f.CopyProp.after.panic-unwind.mir b/tests/mir-opt/copy-prop/dead_stores_79191.f.CopyProp.after.panic-unwind.mir index 617e57d884bf..f8c285ff3843 100644 --- a/tests/mir-opt/copy-prop/dead_stores_79191.f.CopyProp.after.panic-unwind.mir +++ b/tests/mir-opt/copy-prop/dead_stores_79191.f.CopyProp.after.panic-unwind.mir @@ -16,7 +16,7 @@ fn f(_1: usize) -> usize { _1 = _2; StorageLive(_4); _4 = _1; - _0 = id::(move _4) -> bb1; + _0 = id::(move _4) -> [return: bb1, unwind continue]; } bb1: { diff --git a/tests/mir-opt/copy-prop/dead_stores_better.f.CopyProp.after.panic-unwind.mir b/tests/mir-opt/copy-prop/dead_stores_better.f.CopyProp.after.panic-unwind.mir index 617e57d884bf..f8c285ff3843 100644 --- a/tests/mir-opt/copy-prop/dead_stores_better.f.CopyProp.after.panic-unwind.mir +++ b/tests/mir-opt/copy-prop/dead_stores_better.f.CopyProp.after.panic-unwind.mir @@ -16,7 +16,7 @@ fn f(_1: usize) -> usize { _1 = _2; StorageLive(_4); _4 = _1; - _0 = id::(move _4) -> bb1; + _0 = id::(move _4) -> [return: bb1, unwind continue]; } bb1: { diff --git a/tests/mir-opt/copy-prop/issue_107511.main.CopyProp.panic-unwind.diff b/tests/mir-opt/copy-prop/issue_107511.main.CopyProp.panic-unwind.diff index 69f399bf1fa1..c2d892be35dc 100644 --- a/tests/mir-opt/copy-prop/issue_107511.main.CopyProp.panic-unwind.diff +++ b/tests/mir-opt/copy-prop/issue_107511.main.CopyProp.panic-unwind.diff @@ -49,14 +49,14 @@ _7 = &_2; _6 = move _7 as &[i32] (Pointer(Unsize)); StorageDead(_7); - _5 = core::slice::::len(move _6) -> bb1; + _5 = core::slice::::len(move _6) -> [return: bb1, unwind continue]; } bb1: { StorageDead(_6); _4 = std::ops::Range:: { start: const 0_usize, end: move _5 }; StorageDead(_5); - _3 = as IntoIterator>::into_iter(move _4) -> bb2; + _3 = as IntoIterator>::into_iter(move _4) -> [return: bb2, unwind continue]; } bb2: { @@ -73,7 +73,7 @@ StorageLive(_13); _13 = &mut _8; _12 = &mut (*_13); - _11 = as Iterator>::next(move _12) -> bb4; + _11 = as Iterator>::next(move _12) -> [return: bb4, unwind continue]; } bb4: { @@ -90,9 +90,9 @@ - _18 = _16; _19 = Len(_2); - _20 = Lt(_18, _19); -- assert(move _20, "index out of bounds: the length is {} but the index is {}", move _19, _18) -> bb8; +- assert(move _20, "index out of bounds: the length is {} but the index is {}", move _19, _18) -> [success: bb8, unwind continue]; + _20 = Lt(_16, _19); -+ assert(move _20, "index out of bounds: the length is {} but the index is {}", move _19, _16) -> bb8; ++ assert(move _20, "index out of bounds: the length is {} but the index is {}", move _19, _16) -> [success: bb8, unwind continue]; } bb6: { diff --git a/tests/mir-opt/copy-prop/move_arg.f.CopyProp.panic-unwind.diff b/tests/mir-opt/copy-prop/move_arg.f.CopyProp.panic-unwind.diff index cbbf6686b049..0c6a3c6d5c95 100644 --- a/tests/mir-opt/copy-prop/move_arg.f.CopyProp.panic-unwind.diff +++ b/tests/mir-opt/copy-prop/move_arg.f.CopyProp.panic-unwind.diff @@ -21,8 +21,8 @@ - _4 = _1; - StorageLive(_5); - _5 = _2; -- _3 = g::(move _4, move _5) -> bb1; -+ _3 = g::(_1, _1) -> bb1; +- _3 = g::(move _4, move _5) -> [return: bb1, unwind continue]; ++ _3 = g::(_1, _1) -> [return: bb1, unwind continue]; } bb1: { diff --git a/tests/mir-opt/copy-prop/move_projection.f.CopyProp.panic-unwind.diff b/tests/mir-opt/copy-prop/move_projection.f.CopyProp.panic-unwind.diff index 3ebee0ed80d4..ad3889639e0c 100644 --- a/tests/mir-opt/copy-prop/move_projection.f.CopyProp.panic-unwind.diff +++ b/tests/mir-opt/copy-prop/move_projection.f.CopyProp.panic-unwind.diff @@ -9,13 +9,13 @@ bb0: { - _2 = _1; - _3 = move (_2.0: u8); -- _0 = opaque::(move _1) -> bb1; +- _0 = opaque::(move _1) -> [return: bb1, unwind continue]; + _3 = (_1.0: u8); -+ _0 = opaque::(_1) -> bb1; ++ _0 = opaque::(_1) -> [return: bb1, unwind continue]; } bb1: { - _0 = opaque::(move _3) -> bb2; + _0 = opaque::(move _3) -> [return: bb2, unwind continue]; } bb2: { diff --git a/tests/mir-opt/copy-prop/reborrow.demiraw.CopyProp.panic-unwind.diff b/tests/mir-opt/copy-prop/reborrow.demiraw.CopyProp.panic-unwind.diff index 0f14b53e9ade..66a0f49cfb9d 100644 --- a/tests/mir-opt/copy-prop/reborrow.demiraw.CopyProp.panic-unwind.diff +++ b/tests/mir-opt/copy-prop/reborrow.demiraw.CopyProp.panic-unwind.diff @@ -36,8 +36,8 @@ StorageLive(_6); - StorageLive(_7); - _7 = _5; -- _6 = opaque::<*mut u8>(move _7) -> bb1; -+ _6 = opaque::<*mut u8>(_2) -> bb1; +- _6 = opaque::<*mut u8>(move _7) -> [return: bb1, unwind continue]; ++ _6 = opaque::<*mut u8>(_2) -> [return: bb1, unwind continue]; } bb1: { diff --git a/tests/mir-opt/copy-prop/reborrow.miraw.CopyProp.panic-unwind.diff b/tests/mir-opt/copy-prop/reborrow.miraw.CopyProp.panic-unwind.diff index ba6e09fa95c6..f5a512b89955 100644 --- a/tests/mir-opt/copy-prop/reborrow.miraw.CopyProp.panic-unwind.diff +++ b/tests/mir-opt/copy-prop/reborrow.miraw.CopyProp.panic-unwind.diff @@ -32,8 +32,8 @@ StorageLive(_5); - StorageLive(_6); - _6 = _4; -- _5 = opaque::<*mut u8>(move _6) -> bb1; -+ _5 = opaque::<*mut u8>(_2) -> bb1; +- _5 = opaque::<*mut u8>(move _6) -> [return: bb1, unwind continue]; ++ _5 = opaque::<*mut u8>(_2) -> [return: bb1, unwind continue]; } bb1: { diff --git a/tests/mir-opt/copy-prop/reborrow.remut.CopyProp.panic-unwind.diff b/tests/mir-opt/copy-prop/reborrow.remut.CopyProp.panic-unwind.diff index 4379aa06385e..67763fdce667 100644 --- a/tests/mir-opt/copy-prop/reborrow.remut.CopyProp.panic-unwind.diff +++ b/tests/mir-opt/copy-prop/reborrow.remut.CopyProp.panic-unwind.diff @@ -30,8 +30,8 @@ StorageLive(_5); - StorageLive(_6); - _6 = move _4; -- _5 = opaque::<&mut u8>(move _6) -> bb1; -+ _5 = opaque::<&mut u8>(move _2) -> bb1; +- _5 = opaque::<&mut u8>(move _6) -> [return: bb1, unwind continue]; ++ _5 = opaque::<&mut u8>(move _2) -> [return: bb1, unwind continue]; } bb1: { diff --git a/tests/mir-opt/copy-prop/reborrow.reraw.CopyProp.panic-unwind.diff b/tests/mir-opt/copy-prop/reborrow.reraw.CopyProp.panic-unwind.diff index 53332f8161ea..becc42563210 100644 --- a/tests/mir-opt/copy-prop/reborrow.reraw.CopyProp.panic-unwind.diff +++ b/tests/mir-opt/copy-prop/reborrow.reraw.CopyProp.panic-unwind.diff @@ -30,8 +30,8 @@ StorageLive(_5); - StorageLive(_6); - _6 = move _4; -- _5 = opaque::<&mut u8>(move _6) -> bb1; -+ _5 = opaque::<&mut u8>(move _2) -> bb1; +- _5 = opaque::<&mut u8>(move _6) -> [return: bb1, unwind continue]; ++ _5 = opaque::<&mut u8>(move _2) -> [return: bb1, unwind continue]; } bb1: { diff --git a/tests/mir-opt/dataflow-const-prop/checked.main.DataflowConstProp.panic-unwind.diff b/tests/mir-opt/dataflow-const-prop/checked.main.DataflowConstProp.panic-unwind.diff index 784841eacbfa..0d8a9aca3d8c 100644 --- a/tests/mir-opt/dataflow-const-prop/checked.main.DataflowConstProp.panic-unwind.diff +++ b/tests/mir-opt/dataflow-const-prop/checked.main.DataflowConstProp.panic-unwind.diff @@ -41,10 +41,10 @@ StorageLive(_5); - _5 = _2; - _6 = CheckedAdd(_4, _5); -- assert(!move (_6.1: bool), "attempt to compute `{} + {}`, which would overflow", move _4, move _5) -> bb1; +- assert(!move (_6.1: bool), "attempt to compute `{} + {}`, which would overflow", move _4, move _5) -> [success: bb1, unwind continue]; + _5 = const 2_i32; + _6 = CheckedAdd(const 1_i32, const 2_i32); -+ assert(!const false, "attempt to compute `{} + {}`, which would overflow", const 1_i32, const 2_i32) -> bb1; ++ assert(!const false, "attempt to compute `{} + {}`, which would overflow", const 1_i32, const 2_i32) -> [success: bb1, unwind continue]; } bb1: { @@ -58,10 +58,10 @@ StorageLive(_9); - _9 = _7; - _10 = CheckedAdd(_9, const 1_i32); -- assert(!move (_10.1: bool), "attempt to compute `{} + {}`, which would overflow", move _9, const 1_i32) -> bb2; +- assert(!move (_10.1: bool), "attempt to compute `{} + {}`, which would overflow", move _9, const 1_i32) -> [success: bb2, unwind continue]; + _9 = const i32::MAX; + _10 = CheckedAdd(const i32::MAX, const 1_i32); -+ assert(!const true, "attempt to compute `{} + {}`, which would overflow", const i32::MAX, const 1_i32) -> bb2; ++ assert(!const true, "attempt to compute `{} + {}`, which would overflow", const i32::MAX, const 1_i32) -> [success: bb2, unwind continue]; } bb2: { diff --git a/tests/mir-opt/dataflow-const-prop/inherit_overflow.main.DataflowConstProp.panic-unwind.diff b/tests/mir-opt/dataflow-const-prop/inherit_overflow.main.DataflowConstProp.panic-unwind.diff index d79a2da1ddb7..c1d281ab788f 100644 --- a/tests/mir-opt/dataflow-const-prop/inherit_overflow.main.DataflowConstProp.panic-unwind.diff +++ b/tests/mir-opt/dataflow-const-prop/inherit_overflow.main.DataflowConstProp.panic-unwind.diff @@ -21,9 +21,9 @@ StorageLive(_3); _3 = const 1_u8; - _4 = CheckedAdd(_2, _3); -- assert(!move (_4.1: bool), "attempt to compute `{} + {}`, which would overflow", _2, _3) -> bb1; +- assert(!move (_4.1: bool), "attempt to compute `{} + {}`, which would overflow", _2, _3) -> [success: bb1, unwind continue]; + _4 = CheckedAdd(const u8::MAX, const 1_u8); -+ assert(!const true, "attempt to compute `{} + {}`, which would overflow", const u8::MAX, const 1_u8) -> bb1; ++ assert(!const true, "attempt to compute `{} + {}`, which would overflow", const u8::MAX, const 1_u8) -> [success: bb1, unwind continue]; } bb1: { diff --git a/tests/mir-opt/dataflow-const-prop/ref_without_sb.main.DataflowConstProp.panic-unwind.diff b/tests/mir-opt/dataflow-const-prop/ref_without_sb.main.DataflowConstProp.panic-unwind.diff index 83d2f78323e7..4e1d26acfa3f 100644 --- a/tests/mir-opt/dataflow-const-prop/ref_without_sb.main.DataflowConstProp.panic-unwind.diff +++ b/tests/mir-opt/dataflow-const-prop/ref_without_sb.main.DataflowConstProp.panic-unwind.diff @@ -24,7 +24,7 @@ StorageLive(_4); _4 = &_1; _3 = &(*_4); - _2 = escape::(move _3) -> bb1; + _2 = escape::(move _3) -> [return: bb1, unwind continue]; } bb1: { @@ -33,7 +33,7 @@ StorageDead(_2); _1 = const 1_i32; StorageLive(_5); - _5 = some_function() -> bb2; + _5 = some_function() -> [return: bb2, unwind continue]; } bb2: { diff --git a/tests/mir-opt/dataflow-const-prop/sibling_ptr.main.DataflowConstProp.panic-unwind.diff b/tests/mir-opt/dataflow-const-prop/sibling_ptr.main.DataflowConstProp.panic-unwind.diff index 927ca0124bbc..ebeb8619d730 100644 --- a/tests/mir-opt/dataflow-const-prop/sibling_ptr.main.DataflowConstProp.panic-unwind.diff +++ b/tests/mir-opt/dataflow-const-prop/sibling_ptr.main.DataflowConstProp.panic-unwind.diff @@ -30,7 +30,7 @@ StorageLive(_4); StorageLive(_5); _5 = _3; - _4 = ptr::mut_ptr::::add(move _5, const 1_usize) -> bb1; + _4 = ptr::mut_ptr::::add(move _5, const 1_usize) -> [return: bb1, unwind continue]; } bb1: { diff --git a/tests/mir-opt/dataflow-const-prop/terminator.main.DataflowConstProp.panic-unwind.diff b/tests/mir-opt/dataflow-const-prop/terminator.main.DataflowConstProp.panic-unwind.diff index f9723a049830..395620fec524 100644 --- a/tests/mir-opt/dataflow-const-prop/terminator.main.DataflowConstProp.panic-unwind.diff +++ b/tests/mir-opt/dataflow-const-prop/terminator.main.DataflowConstProp.panic-unwind.diff @@ -22,8 +22,8 @@ + _4 = const 1_i32; + _3 = const 2_i32; StorageDead(_4); -- _2 = foo(move _3) -> bb1; -+ _2 = foo(const 2_i32) -> bb1; +- _2 = foo(move _3) -> [return: bb1, unwind continue]; ++ _2 = foo(const 2_i32) -> [return: bb1, unwind continue]; } bb1: { diff --git a/tests/mir-opt/dead-store-elimination/cycle.cycle.DeadStoreElimination.panic-unwind.diff b/tests/mir-opt/dead-store-elimination/cycle.cycle.DeadStoreElimination.panic-unwind.diff index 80a4dd371839..4b922e05e105 100644 --- a/tests/mir-opt/dead-store-elimination/cycle.cycle.DeadStoreElimination.panic-unwind.diff +++ b/tests/mir-opt/dead-store-elimination/cycle.cycle.DeadStoreElimination.panic-unwind.diff @@ -28,9 +28,9 @@ bb1: { - StorageLive(_5); -- _5 = cond() -> bb2; +- _5 = cond() -> [return: bb2, unwind continue]; + StorageLive(_4); -+ _4 = cond() -> bb2; ++ _4 = cond() -> [return: bb2, unwind continue]; } bb2: { diff --git a/tests/mir-opt/deduplicate_blocks.is_line_doc_comment_2.DeduplicateBlocks.panic-unwind.diff b/tests/mir-opt/deduplicate_blocks.is_line_doc_comment_2.DeduplicateBlocks.panic-unwind.diff index 66396d28e704..3d9aa829052d 100644 --- a/tests/mir-opt/deduplicate_blocks.is_line_doc_comment_2.DeduplicateBlocks.panic-unwind.diff +++ b/tests/mir-opt/deduplicate_blocks.is_line_doc_comment_2.DeduplicateBlocks.panic-unwind.diff @@ -17,7 +17,7 @@ StorageLive(_2); StorageLive(_3); _3 = &(*_1); - _2 = core::str::::as_bytes(move _3) -> bb1; + _2 = core::str::::as_bytes(move _3) -> [return: bb1, unwind continue]; } bb1: { diff --git a/tests/mir-opt/derefer_complex_case.main.Derefer.panic-unwind.diff b/tests/mir-opt/derefer_complex_case.main.Derefer.panic-unwind.diff index 62085341d378..da4cc188cfa6 100644 --- a/tests/mir-opt/derefer_complex_case.main.Derefer.panic-unwind.diff +++ b/tests/mir-opt/derefer_complex_case.main.Derefer.panic-unwind.diff @@ -30,7 +30,7 @@ StorageLive(_2); _14 = const _; _2 = &(*_14); - _1 = <&[i32; 2] as IntoIterator>::into_iter(move _2) -> bb1; + _1 = <&[i32; 2] as IntoIterator>::into_iter(move _2) -> [return: bb1, unwind continue]; } bb1: { @@ -47,7 +47,7 @@ StorageLive(_9); _9 = &mut _4; _8 = &mut (*_9); - _7 = as Iterator>::next(move _8) -> bb3; + _7 = as Iterator>::next(move _8) -> [return: bb3, unwind continue]; } bb3: { @@ -63,7 +63,7 @@ + _12 = (*_15); StorageLive(_13); _13 = _12; - _6 = std::mem::drop::(move _13) -> bb7; + _6 = std::mem::drop::(move _13) -> [return: bb7, unwind continue]; } bb5: { diff --git a/tests/mir-opt/derefer_inline_test.main.Derefer.panic-unwind.diff b/tests/mir-opt/derefer_inline_test.main.Derefer.panic-unwind.diff index 50683837097a..2ada087b4bd6 100644 --- a/tests/mir-opt/derefer_inline_test.main.Derefer.panic-unwind.diff +++ b/tests/mir-opt/derefer_inline_test.main.Derefer.panic-unwind.diff @@ -9,7 +9,7 @@ bb0: { StorageLive(_1); StorageLive(_2); - _2 = f() -> bb1; + _2 = f() -> [return: bb1, unwind continue]; } bb1: { @@ -18,7 +18,7 @@ bb2: { StorageDead(_2); - drop(_1) -> bb3; + drop(_1) -> [return: bb3, unwind continue]; } bb3: { diff --git a/tests/mir-opt/derefer_terminator_test.main.Derefer.panic-unwind.diff b/tests/mir-opt/derefer_terminator_test.main.Derefer.panic-unwind.diff index 59168eda2f3e..19b26c901cbf 100644 --- a/tests/mir-opt/derefer_terminator_test.main.Derefer.panic-unwind.diff +++ b/tests/mir-opt/derefer_terminator_test.main.Derefer.panic-unwind.diff @@ -30,12 +30,12 @@ bb0: { StorageLive(_1); - _1 = foo() -> bb1; + _1 = foo() -> [return: bb1, unwind continue]; } bb1: { StorageLive(_2); - _2 = foo() -> bb2; + _2 = foo() -> [return: bb2, unwind continue]; } bb2: { diff --git a/tests/mir-opt/dest-prop/branch.foo.DestinationPropagation.panic-unwind.diff b/tests/mir-opt/dest-prop/branch.foo.DestinationPropagation.panic-unwind.diff index e0734f47de2a..759c1cabf45e 100644 --- a/tests/mir-opt/dest-prop/branch.foo.DestinationPropagation.panic-unwind.diff +++ b/tests/mir-opt/dest-prop/branch.foo.DestinationPropagation.panic-unwind.diff @@ -18,16 +18,16 @@ bb0: { - StorageLive(_1); -- _1 = val() -> bb1; +- _1 = val() -> [return: bb1, unwind continue]; + nop; -+ _0 = val() -> bb1; ++ _0 = val() -> [return: bb1, unwind continue]; } bb1: { - StorageLive(_2); + nop; StorageLive(_3); - _3 = cond() -> bb2; + _3 = cond() -> [return: bb2, unwind continue]; } bb2: { @@ -42,7 +42,7 @@ bb4: { StorageLive(_4); - _4 = val() -> bb5; + _4 = val() -> [return: bb5, unwind continue]; } bb5: { diff --git a/tests/mir-opt/dest-prop/copy_propagation_arg.bar.DestinationPropagation.panic-unwind.diff b/tests/mir-opt/dest-prop/copy_propagation_arg.bar.DestinationPropagation.panic-unwind.diff index b181066df047..8b2835c8ced2 100644 --- a/tests/mir-opt/dest-prop/copy_propagation_arg.bar.DestinationPropagation.panic-unwind.diff +++ b/tests/mir-opt/dest-prop/copy_propagation_arg.bar.DestinationPropagation.panic-unwind.diff @@ -11,10 +11,10 @@ StorageLive(_2); - StorageLive(_3); - _3 = _1; -- _2 = dummy(move _3) -> bb1; +- _2 = dummy(move _3) -> [return: bb1, unwind continue]; + nop; + nop; -+ _2 = dummy(move _1) -> bb1; ++ _2 = dummy(move _1) -> [return: bb1, unwind continue]; } bb1: { diff --git a/tests/mir-opt/dest-prop/copy_propagation_arg.foo.DestinationPropagation.panic-unwind.diff b/tests/mir-opt/dest-prop/copy_propagation_arg.foo.DestinationPropagation.panic-unwind.diff index f19728669368..b4c8a89278b9 100644 --- a/tests/mir-opt/dest-prop/copy_propagation_arg.foo.DestinationPropagation.panic-unwind.diff +++ b/tests/mir-opt/dest-prop/copy_propagation_arg.foo.DestinationPropagation.panic-unwind.diff @@ -12,8 +12,8 @@ + nop; StorageLive(_3); _3 = _1; -- _2 = dummy(move _3) -> bb1; -+ _1 = dummy(move _3) -> bb1; +- _2 = dummy(move _3) -> [return: bb1, unwind continue]; ++ _1 = dummy(move _3) -> [return: bb1, unwind continue]; } bb1: { diff --git a/tests/mir-opt/dest-prop/cycle.main.DestinationPropagation.panic-unwind.diff b/tests/mir-opt/dest-prop/cycle.main.DestinationPropagation.panic-unwind.diff index 0dc7de31cc47..6f6e01d37b1a 100644 --- a/tests/mir-opt/dest-prop/cycle.main.DestinationPropagation.panic-unwind.diff +++ b/tests/mir-opt/dest-prop/cycle.main.DestinationPropagation.panic-unwind.diff @@ -24,9 +24,9 @@ bb0: { - StorageLive(_1); -- _1 = val() -> bb1; +- _1 = val() -> [return: bb1, unwind continue]; + nop; -+ _6 = val() -> bb1; ++ _6 = val() -> [return: bb1, unwind continue]; } bb1: { @@ -51,7 +51,7 @@ - _6 = _1; + nop; + nop; - _5 = std::mem::drop::(move _6) -> bb2; + _5 = std::mem::drop::(move _6) -> [return: bb2, unwind continue]; } bb2: { diff --git a/tests/mir-opt/dest-prop/dead_stores_79191.f.DestinationPropagation.after.panic-unwind.mir b/tests/mir-opt/dest-prop/dead_stores_79191.f.DestinationPropagation.after.panic-unwind.mir index bf515d328aef..9147de2ec473 100644 --- a/tests/mir-opt/dest-prop/dead_stores_79191.f.DestinationPropagation.after.panic-unwind.mir +++ b/tests/mir-opt/dest-prop/dead_stores_79191.f.DestinationPropagation.after.panic-unwind.mir @@ -20,7 +20,7 @@ fn f(_1: usize) -> usize { nop; nop; nop; - _0 = id::(move _1) -> bb1; + _0 = id::(move _1) -> [return: bb1, unwind continue]; } bb1: { diff --git a/tests/mir-opt/dest-prop/dead_stores_better.f.DestinationPropagation.after.panic-unwind.mir b/tests/mir-opt/dest-prop/dead_stores_better.f.DestinationPropagation.after.panic-unwind.mir index 038bd4b6da9d..185feb4b4181 100644 --- a/tests/mir-opt/dest-prop/dead_stores_better.f.DestinationPropagation.after.panic-unwind.mir +++ b/tests/mir-opt/dest-prop/dead_stores_better.f.DestinationPropagation.after.panic-unwind.mir @@ -19,7 +19,7 @@ fn f(_1: usize) -> usize { nop; nop; nop; - _0 = id::(move _1) -> bb1; + _0 = id::(move _1) -> [return: bb1, unwind continue]; } bb1: { diff --git a/tests/mir-opt/dest-prop/simple.nrvo.DestinationPropagation.panic-unwind.diff b/tests/mir-opt/dest-prop/simple.nrvo.DestinationPropagation.panic-unwind.diff index 4e32823c1ee9..9c3cbef38d69 100644 --- a/tests/mir-opt/dest-prop/simple.nrvo.DestinationPropagation.panic-unwind.diff +++ b/tests/mir-opt/dest-prop/simple.nrvo.DestinationPropagation.panic-unwind.diff @@ -25,8 +25,8 @@ StorageLive(_6); _6 = &mut _2; _5 = &mut (*_6); -- _3 = move _4(move _5) -> bb1; -+ _3 = move _1(move _5) -> bb1; +- _3 = move _4(move _5) -> [return: bb1, unwind continue]; ++ _3 = move _1(move _5) -> [return: bb1, unwind continue]; } bb1: { diff --git a/tests/mir-opt/dest-prop/union.main.DestinationPropagation.panic-unwind.diff b/tests/mir-opt/dest-prop/union.main.DestinationPropagation.panic-unwind.diff index 8d1297d02996..d2eef90582d5 100644 --- a/tests/mir-opt/dest-prop/union.main.DestinationPropagation.panic-unwind.diff +++ b/tests/mir-opt/dest-prop/union.main.DestinationPropagation.panic-unwind.diff @@ -18,7 +18,7 @@ bb0: { StorageLive(_1); StorageLive(_2); - _2 = val() -> bb1; + _2 = val() -> [return: bb1, unwind continue]; } bb1: { diff --git a/tests/mir-opt/dest-prop/unreachable.f.DestinationPropagation.panic-unwind.diff b/tests/mir-opt/dest-prop/unreachable.f.DestinationPropagation.panic-unwind.diff index e46a318f51ab..7f730a77b06a 100644 --- a/tests/mir-opt/dest-prop/unreachable.f.DestinationPropagation.panic-unwind.diff +++ b/tests/mir-opt/dest-prop/unreachable.f.DestinationPropagation.panic-unwind.diff @@ -34,7 +34,7 @@ - _5 = _1; - StorageLive(_6); - _6 = _2; -- _4 = g::(move _5, move _6) -> bb2; +- _4 = g::(move _5, move _6) -> [return: bb2, unwind continue]; - } - - bb2: { @@ -53,9 +53,9 @@ + nop; StorageLive(_9); - _9 = _2; -- _7 = g::(move _8, move _9) -> bb4; +- _7 = g::(move _8, move _9) -> [return: bb4, unwind continue]; + _9 = _1; -+ _7 = g::(move _1, move _9) -> bb2; ++ _7 = g::(move _1, move _9) -> [return: bb2, unwind continue]; } - bb4: { diff --git a/tests/mir-opt/fn_ptr_shim.core.ops-function-Fn-call.AddMovesForPackedDrops.before.mir b/tests/mir-opt/fn_ptr_shim.core.ops-function-Fn-call.AddMovesForPackedDrops.before.mir index 4fe11435fab9..5fddfd494ead 100644 --- a/tests/mir-opt/fn_ptr_shim.core.ops-function-Fn-call.AddMovesForPackedDrops.before.mir +++ b/tests/mir-opt/fn_ptr_shim.core.ops-function-Fn-call.AddMovesForPackedDrops.before.mir @@ -1,10 +1,10 @@ // MIR for `std::ops::Fn::call` before AddMovesForPackedDrops -fn std::ops::Fn::call(_1: *const fn(), _2: ()) -> >::Output { +fn std::ops::Fn::call(_1: &fn(), _2: ()) -> >::Output { let mut _0: >::Output; bb0: { - _0 = move (*_1)() -> bb1; + _0 = move (*_1)() -> [return: bb1, unwind continue]; } bb1: { diff --git a/tests/mir-opt/funky_arms.float_to_exponential_common.ConstProp.panic-unwind.diff b/tests/mir-opt/funky_arms.float_to_exponential_common.ConstProp.panic-unwind.diff index 513ff03c4261..8a3dcfab44bd 100644 --- a/tests/mir-opt/funky_arms.float_to_exponential_common.ConstProp.panic-unwind.diff +++ b/tests/mir-opt/funky_arms.float_to_exponential_common.ConstProp.panic-unwind.diff @@ -38,7 +38,7 @@ StorageLive(_4); StorageLive(_5); _5 = &(*_1); - _4 = Formatter::<'_>::sign_plus(move _5) -> bb1; + _4 = Formatter::<'_>::sign_plus(move _5) -> [return: bb1, unwind continue]; } bb1: { @@ -63,7 +63,7 @@ StorageLive(_7); StorageLive(_8); _8 = &(*_1); - _7 = Formatter::<'_>::precision(move _8) -> bb5; + _7 = Formatter::<'_>::precision(move _8) -> [return: bb5, unwind continue]; } bb5: { @@ -81,7 +81,7 @@ _15 = _10 as u32 (IntToInt); _14 = Add(move _15, const 1_u32); StorageDead(_15); - _0 = float_to_exponential_common_exact::(_1, _2, move _13, move _14, _3) -> bb7; + _0 = float_to_exponential_common_exact::(_1, _2, move _13, move _14, _3) -> [return: bb7, unwind continue]; } bb7: { @@ -93,7 +93,7 @@ bb8: { StorageLive(_20); _20 = _6; - _0 = float_to_exponential_common_shortest::(_1, _2, move _20, _3) -> bb9; + _0 = float_to_exponential_common_shortest::(_1, _2, move _20, _3) -> [return: bb9, unwind continue]; } bb9: { diff --git a/tests/mir-opt/inline/asm_unwind.main.Inline.panic-unwind.diff b/tests/mir-opt/inline/asm_unwind.main.Inline.panic-unwind.diff index af67723d9371..684211b53b33 100644 --- a/tests/mir-opt/inline/asm_unwind.main.Inline.panic-unwind.diff +++ b/tests/mir-opt/inline/asm_unwind.main.Inline.panic-unwind.diff @@ -15,7 +15,7 @@ bb0: { StorageLive(_1); -- _1 = foo() -> bb1; +- _1 = foo() -> [return: bb1, unwind continue]; + StorageLive(_2); + asm!("", options(MAY_UNWIND)) -> [return: bb2, unwind: bb3]; } @@ -28,7 +28,7 @@ + } + + bb2: { -+ drop(_2) -> bb1; ++ drop(_2) -> [return: bb1, unwind continue]; + } + + bb3 (cleanup): { diff --git a/tests/mir-opt/inline/caller_with_trivial_bound.foo.Inline.panic-unwind.diff b/tests/mir-opt/inline/caller_with_trivial_bound.foo.Inline.panic-unwind.diff index 67f16833435d..d4427b2a8076 100644 --- a/tests/mir-opt/inline/caller_with_trivial_bound.foo.Inline.panic-unwind.diff +++ b/tests/mir-opt/inline/caller_with_trivial_bound.foo.Inline.panic-unwind.diff @@ -10,7 +10,7 @@ bb0: { StorageLive(_1); - _1 = bar::() -> bb1; + _1 = bar::() -> [return: bb1, unwind continue]; } bb1: { diff --git a/tests/mir-opt/inline/cycle.g.Inline.panic-unwind.diff b/tests/mir-opt/inline/cycle.g.Inline.panic-unwind.diff index 2bdb942379ca..3ce8d9acf368 100644 --- a/tests/mir-opt/inline/cycle.g.Inline.panic-unwind.diff +++ b/tests/mir-opt/inline/cycle.g.Inline.panic-unwind.diff @@ -16,7 +16,7 @@ bb0: { StorageLive(_1); -- _1 = f::(main) -> bb1; +- _1 = f::(main) -> [return: bb1, unwind continue]; + StorageLive(_2); + _2 = main; + StorageLive(_4); @@ -46,7 +46,7 @@ + bb4: { + StorageDead(_5); + StorageDead(_3); -+ drop(_2) -> bb1; ++ drop(_2) -> [return: bb1, unwind continue]; } } diff --git a/tests/mir-opt/inline/cycle.main.Inline.panic-unwind.diff b/tests/mir-opt/inline/cycle.main.Inline.panic-unwind.diff index c4f97d75308f..198a23226184 100644 --- a/tests/mir-opt/inline/cycle.main.Inline.panic-unwind.diff +++ b/tests/mir-opt/inline/cycle.main.Inline.panic-unwind.diff @@ -24,7 +24,7 @@ bb0: { StorageLive(_1); -- _1 = f::(g) -> bb1; +- _1 = f::(g) -> [return: bb1, unwind continue]; + StorageLive(_2); + _2 = g; + StorageLive(_4); @@ -56,7 +56,7 @@ + StorageDead(_6); + StorageDead(_5); + StorageDead(_3); -+ drop(_2) -> bb1; ++ drop(_2) -> [return: bb1, unwind continue]; } } diff --git a/tests/mir-opt/inline/dyn_trait.get_query.Inline.panic-unwind.diff b/tests/mir-opt/inline/dyn_trait.get_query.Inline.panic-unwind.diff index ca772cf43839..941ba24605cd 100644 --- a/tests/mir-opt/inline/dyn_trait.get_query.Inline.panic-unwind.diff +++ b/tests/mir-opt/inline/dyn_trait.get_query.Inline.panic-unwind.diff @@ -22,17 +22,17 @@ StorageLive(_2); StorageLive(_3); _3 = &(*_1); - _2 = ::cache::(move _3) -> bb1; + _2 = ::cache::(move _3) -> [return: bb1, unwind continue]; } bb1: { StorageDead(_3); StorageLive(_4); _4 = &(*_2); -- _0 = try_execute_query::<::C>(move _4) -> bb2; +- _0 = try_execute_query::<::C>(move _4) -> [return: bb2, unwind continue]; + StorageLive(_5); + _5 = _4 as &dyn Cache::V> (Pointer(Unsize)); -+ _0 = ::V> as Cache>::store_nocache(_5) -> bb2; ++ _0 = ::V> as Cache>::store_nocache(_5) -> [return: bb2, unwind continue]; } bb2: { diff --git a/tests/mir-opt/inline/dyn_trait.mk_cycle.Inline.panic-unwind.diff b/tests/mir-opt/inline/dyn_trait.mk_cycle.Inline.panic-unwind.diff index 12b539fc250c..7b1cf895a873 100644 --- a/tests/mir-opt/inline/dyn_trait.mk_cycle.Inline.panic-unwind.diff +++ b/tests/mir-opt/inline/dyn_trait.mk_cycle.Inline.panic-unwind.diff @@ -9,7 +9,7 @@ bb0: { StorageLive(_2); _2 = &(*_1); - _0 = as Cache>::store_nocache(move _2) -> bb1; + _0 = as Cache>::store_nocache(move _2) -> [return: bb1, unwind continue]; } bb1: { diff --git a/tests/mir-opt/inline/dyn_trait.try_execute_query.Inline.panic-unwind.diff b/tests/mir-opt/inline/dyn_trait.try_execute_query.Inline.panic-unwind.diff index 9bcd73e1c8ba..5e30da400d29 100644 --- a/tests/mir-opt/inline/dyn_trait.try_execute_query.Inline.panic-unwind.diff +++ b/tests/mir-opt/inline/dyn_trait.try_execute_query.Inline.panic-unwind.diff @@ -16,8 +16,8 @@ _3 = &(*_1); _2 = move _3 as &dyn Cache::V> (Pointer(Unsize)); StorageDead(_3); -- _0 = mk_cycle::<::V>(move _2) -> bb1; -+ _0 = ::V> as Cache>::store_nocache(_2) -> bb1; +- _0 = mk_cycle::<::V>(move _2) -> [return: bb1, unwind continue]; ++ _0 = ::V> as Cache>::store_nocache(_2) -> [return: bb1, unwind continue]; } bb1: { diff --git a/tests/mir-opt/inline/exponential_runtime.main.Inline.panic-unwind.diff b/tests/mir-opt/inline/exponential_runtime.main.Inline.panic-unwind.diff index b87e164e471a..0a4ce40c529d 100644 --- a/tests/mir-opt/inline/exponential_runtime.main.Inline.panic-unwind.diff +++ b/tests/mir-opt/inline/exponential_runtime.main.Inline.panic-unwind.diff @@ -37,7 +37,7 @@ bb0: { StorageLive(_1); -- _1 = <() as G>::call() -> bb1; +- _1 = <() as G>::call() -> [return: bb1, unwind continue]; + StorageLive(_2); + StorageLive(_3); + StorageLive(_4); @@ -56,7 +56,7 @@ + StorageLive(_17); + StorageLive(_18); + StorageLive(_19); -+ _17 = <() as A>::call() -> bb12; ++ _17 = <() as A>::call() -> [return: bb12, unwind continue]; } bb1: { @@ -72,63 +72,63 @@ + StorageDead(_7); + StorageDead(_6); + StorageDead(_5); -+ _3 = <() as F>::call() -> bb3; ++ _3 = <() as F>::call() -> [return: bb3, unwind continue]; + } + + bb3: { -+ _4 = <() as F>::call() -> bb1; ++ _4 = <() as F>::call() -> [return: bb1, unwind continue]; + } + + bb4: { + StorageDead(_10); + StorageDead(_9); + StorageDead(_8); -+ _6 = <() as E>::call() -> bb5; ++ _6 = <() as E>::call() -> [return: bb5, unwind continue]; + } + + bb5: { -+ _7 = <() as E>::call() -> bb2; ++ _7 = <() as E>::call() -> [return: bb2, unwind continue]; + } + + bb6: { + StorageDead(_13); + StorageDead(_12); + StorageDead(_11); -+ _9 = <() as D>::call() -> bb7; ++ _9 = <() as D>::call() -> [return: bb7, unwind continue]; + } + + bb7: { -+ _10 = <() as D>::call() -> bb4; ++ _10 = <() as D>::call() -> [return: bb4, unwind continue]; + } + + bb8: { + StorageDead(_16); + StorageDead(_15); + StorageDead(_14); -+ _12 = <() as C>::call() -> bb9; ++ _12 = <() as C>::call() -> [return: bb9, unwind continue]; + } + + bb9: { -+ _13 = <() as C>::call() -> bb6; ++ _13 = <() as C>::call() -> [return: bb6, unwind continue]; + } + + bb10: { + StorageDead(_19); + StorageDead(_18); + StorageDead(_17); -+ _15 = <() as B>::call() -> bb11; ++ _15 = <() as B>::call() -> [return: bb11, unwind continue]; + } + + bb11: { -+ _16 = <() as B>::call() -> bb8; ++ _16 = <() as B>::call() -> [return: bb8, unwind continue]; + } + + bb12: { -+ _18 = <() as A>::call() -> bb13; ++ _18 = <() as A>::call() -> [return: bb13, unwind continue]; + } + + bb13: { -+ _19 = <() as A>::call() -> bb10; ++ _19 = <() as A>::call() -> [return: bb10, unwind continue]; } } diff --git a/tests/mir-opt/inline/inline_compatibility.inlined_no_sanitize.Inline.panic-unwind.diff b/tests/mir-opt/inline/inline_compatibility.inlined_no_sanitize.Inline.panic-unwind.diff index 10e0f0efcbcf..eba5ad9cf269 100644 --- a/tests/mir-opt/inline/inline_compatibility.inlined_no_sanitize.Inline.panic-unwind.diff +++ b/tests/mir-opt/inline/inline_compatibility.inlined_no_sanitize.Inline.panic-unwind.diff @@ -9,7 +9,7 @@ bb0: { StorageLive(_1); -- _1 = no_sanitize() -> bb1; +- _1 = no_sanitize() -> [return: bb1, unwind continue]; - } - - bb1: { diff --git a/tests/mir-opt/inline/inline_compatibility.inlined_target_feature.Inline.panic-unwind.diff b/tests/mir-opt/inline/inline_compatibility.inlined_target_feature.Inline.panic-unwind.diff index b854e93d9b79..24457819b2c1 100644 --- a/tests/mir-opt/inline/inline_compatibility.inlined_target_feature.Inline.panic-unwind.diff +++ b/tests/mir-opt/inline/inline_compatibility.inlined_target_feature.Inline.panic-unwind.diff @@ -9,7 +9,7 @@ bb0: { StorageLive(_1); -- _1 = target_feature() -> bb1; +- _1 = target_feature() -> [return: bb1, unwind continue]; - } - - bb1: { diff --git a/tests/mir-opt/inline/inline_compatibility.not_inlined_c_variadic.Inline.panic-unwind.diff b/tests/mir-opt/inline/inline_compatibility.not_inlined_c_variadic.Inline.panic-unwind.diff index d9e7177e6278..364acab6d936 100644 --- a/tests/mir-opt/inline/inline_compatibility.not_inlined_c_variadic.Inline.panic-unwind.diff +++ b/tests/mir-opt/inline/inline_compatibility.not_inlined_c_variadic.Inline.panic-unwind.diff @@ -10,7 +10,7 @@ bb0: { StorageLive(_1); - _1 = sum(const 4_u32, const 4_u32, const 30_u32, const 200_u32, const 1000_u32) -> bb1; + _1 = sum(const 4_u32, const 4_u32, const 30_u32, const 200_u32, const 1000_u32) -> [return: bb1, unwind continue]; } bb1: { diff --git a/tests/mir-opt/inline/inline_compatibility.not_inlined_no_sanitize.Inline.panic-unwind.diff b/tests/mir-opt/inline/inline_compatibility.not_inlined_no_sanitize.Inline.panic-unwind.diff index 7d9b1d847b02..965b7ddca320 100644 --- a/tests/mir-opt/inline/inline_compatibility.not_inlined_no_sanitize.Inline.panic-unwind.diff +++ b/tests/mir-opt/inline/inline_compatibility.not_inlined_no_sanitize.Inline.panic-unwind.diff @@ -7,7 +7,7 @@ bb0: { StorageLive(_1); - _1 = no_sanitize() -> bb1; + _1 = no_sanitize() -> [return: bb1, unwind continue]; } bb1: { diff --git a/tests/mir-opt/inline/inline_compatibility.not_inlined_target_feature.Inline.panic-unwind.diff b/tests/mir-opt/inline/inline_compatibility.not_inlined_target_feature.Inline.panic-unwind.diff index 5bee58652838..bcdbd6e33140 100644 --- a/tests/mir-opt/inline/inline_compatibility.not_inlined_target_feature.Inline.panic-unwind.diff +++ b/tests/mir-opt/inline/inline_compatibility.not_inlined_target_feature.Inline.panic-unwind.diff @@ -7,7 +7,7 @@ bb0: { StorageLive(_1); - _1 = target_feature() -> bb1; + _1 = target_feature() -> [return: bb1, unwind continue]; } bb1: { diff --git a/tests/mir-opt/inline/inline_cycle.one.Inline.panic-unwind.diff b/tests/mir-opt/inline/inline_cycle.one.Inline.panic-unwind.diff index 66d25162cb1b..75ac40bea61f 100644 --- a/tests/mir-opt/inline/inline_cycle.one.Inline.panic-unwind.diff +++ b/tests/mir-opt/inline/inline_cycle.one.Inline.panic-unwind.diff @@ -13,7 +13,7 @@ bb0: { StorageLive(_1); - _1 = ::call() -> bb1; + _1 = ::call() -> [return: bb1, unwind continue]; } bb1: { diff --git a/tests/mir-opt/inline/inline_cycle.two.Inline.panic-unwind.diff b/tests/mir-opt/inline/inline_cycle.two.Inline.panic-unwind.diff index d3bd412d9532..a08662959dd8 100644 --- a/tests/mir-opt/inline/inline_cycle.two.Inline.panic-unwind.diff +++ b/tests/mir-opt/inline/inline_cycle.two.Inline.panic-unwind.diff @@ -23,14 +23,14 @@ bb0: { StorageLive(_1); -- _1 = call::(f) -> bb1; +- _1 = call::(f) -> [return: bb1, unwind continue]; + StorageLive(_2); + _2 = f; + StorageLive(_3); + StorageLive(_4); + _4 = const (); + StorageLive(_5); -+ _5 = f() -> bb1; ++ _5 = f() -> [return: bb1, unwind continue]; } bb1: { diff --git a/tests/mir-opt/inline/inline_cycle_generic.main.Inline.panic-unwind.diff b/tests/mir-opt/inline/inline_cycle_generic.main.Inline.panic-unwind.diff index 2a4002f0499c..8314526ee043 100644 --- a/tests/mir-opt/inline/inline_cycle_generic.main.Inline.panic-unwind.diff +++ b/tests/mir-opt/inline/inline_cycle_generic.main.Inline.panic-unwind.diff @@ -13,8 +13,8 @@ bb0: { StorageLive(_1); -- _1 = ::call() -> bb1; -+ _1 = as Call>::call() -> bb1; +- _1 = ::call() -> [return: bb1, unwind continue]; ++ _1 = as Call>::call() -> [return: bb1, unwind continue]; } bb1: { diff --git a/tests/mir-opt/inline/inline_diverging.f.Inline.panic-unwind.diff b/tests/mir-opt/inline/inline_diverging.f.Inline.panic-unwind.diff index 76bb3356f50f..b79918992534 100644 --- a/tests/mir-opt/inline/inline_diverging.f.Inline.panic-unwind.diff +++ b/tests/mir-opt/inline/inline_diverging.f.Inline.panic-unwind.diff @@ -10,7 +10,7 @@ bb0: { StorageLive(_2); -- _2 = sleep(); +- _2 = sleep() -> unwind continue; + goto -> bb1; + } + diff --git a/tests/mir-opt/inline/inline_diverging.g.Inline.panic-unwind.diff b/tests/mir-opt/inline/inline_diverging.g.Inline.panic-unwind.diff index d65efa43a7b1..5663b4624001 100644 --- a/tests/mir-opt/inline/inline_diverging.g.Inline.panic-unwind.diff +++ b/tests/mir-opt/inline/inline_diverging.g.Inline.panic-unwind.diff @@ -33,9 +33,9 @@ bb2: { StorageLive(_6); -- _6 = panic(); +- _6 = panic() -> unwind continue; + StorageLive(_7); -+ _7 = begin_panic::<&str>(const "explicit panic"); ++ _7 = begin_panic::<&str>(const "explicit panic") -> unwind continue; } } diff --git a/tests/mir-opt/inline/inline_diverging.h.Inline.panic-unwind.diff b/tests/mir-opt/inline/inline_diverging.h.Inline.panic-unwind.diff index f7e0e1c55f8b..dfc12db12a88 100644 --- a/tests/mir-opt/inline/inline_diverging.h.Inline.panic-unwind.diff +++ b/tests/mir-opt/inline/inline_diverging.h.Inline.panic-unwind.diff @@ -27,7 +27,7 @@ bb0: { StorageLive(_1); -- _1 = call_twice:: ! {sleep}>(sleep); +- _1 = call_twice:: ! {sleep}>(sleep) -> unwind continue; + StorageLive(_2); + _2 = sleep; + StorageLive(_6); diff --git a/tests/mir-opt/inline/inline_generator.main.Inline.panic-unwind.diff b/tests/mir-opt/inline/inline_generator.main.Inline.panic-unwind.diff index 588f04048d67..fedcf04231d7 100644 --- a/tests/mir-opt/inline/inline_generator.main.Inline.panic-unwind.diff +++ b/tests/mir-opt/inline/inline_generator.main.Inline.panic-unwind.diff @@ -35,7 +35,7 @@ StorageLive(_2); StorageLive(_3); StorageLive(_4); -- _4 = g() -> bb1; +- _4 = g() -> [return: bb1, unwind continue]; - } - - bb1: { diff --git a/tests/mir-opt/inline/inline_into_box_place.main.Inline.panic-unwind.diff b/tests/mir-opt/inline/inline_into_box_place.main.Inline.panic-unwind.diff index 4615a3f98267..0b643b3c7a92 100644 --- a/tests/mir-opt/inline/inline_into_box_place.main.Inline.panic-unwind.diff +++ b/tests/mir-opt/inline/inline_into_box_place.main.Inline.panic-unwind.diff @@ -117,7 +117,7 @@ bb0: { StorageLive(_1); StorageLive(_2); -- _2 = Vec::::new() -> bb1; +- _2 = Vec::::new() -> [return: bb1, unwind continue]; + StorageLive(_3); + _3 = const _; + _2 = Vec:: { buf: move _3, len: const 0_usize }; diff --git a/tests/mir-opt/inline/inline_options.main.Inline.after.panic-unwind.mir b/tests/mir-opt/inline/inline_options.main.Inline.after.panic-unwind.mir index d006c73f9542..df0cab513eca 100644 --- a/tests/mir-opt/inline/inline_options.main.Inline.after.panic-unwind.mir +++ b/tests/mir-opt/inline/inline_options.main.Inline.after.panic-unwind.mir @@ -12,7 +12,7 @@ fn main() -> () { bb0: { StorageLive(_1); - _1 = not_inlined() -> bb1; + _1 = not_inlined() -> [return: bb1, unwind continue]; } bb1: { @@ -21,7 +21,7 @@ fn main() -> () { StorageLive(_3); StorageLive(_4); StorageLive(_5); - _3 = g() -> bb3; + _3 = g() -> [return: bb3, unwind continue]; } bb2: { @@ -34,10 +34,10 @@ fn main() -> () { } bb3: { - _4 = g() -> bb4; + _4 = g() -> [return: bb4, unwind continue]; } bb4: { - _5 = g() -> bb2; + _5 = g() -> [return: bb2, unwind continue]; } } diff --git a/tests/mir-opt/inline/inline_shims.clone.Inline.panic-unwind.diff b/tests/mir-opt/inline/inline_shims.clone.Inline.panic-unwind.diff index 9897ed78edff..00e92a0f5e5a 100644 --- a/tests/mir-opt/inline/inline_shims.clone.Inline.panic-unwind.diff +++ b/tests/mir-opt/inline/inline_shims.clone.Inline.panic-unwind.diff @@ -11,7 +11,7 @@ bb0: { StorageLive(_2); _2 = &_1; -- _0 = ::clone(move _2) -> bb1; +- _0 = ::clone(move _2) -> [return: bb1, unwind continue]; - } - - bb1: { diff --git a/tests/mir-opt/inline/inline_shims.drop.Inline.panic-unwind.diff b/tests/mir-opt/inline/inline_shims.drop.Inline.panic-unwind.diff index 1d24756e1d22..4270ae00b668 100644 --- a/tests/mir-opt/inline/inline_shims.drop.Inline.panic-unwind.diff +++ b/tests/mir-opt/inline/inline_shims.drop.Inline.panic-unwind.diff @@ -21,7 +21,7 @@ StorageLive(_3); StorageLive(_4); _4 = _1; - _3 = std::ptr::drop_in_place::>(move _4) -> bb1; + _3 = std::ptr::drop_in_place::>(move _4) -> [return: bb1, unwind continue]; } bb1: { @@ -29,7 +29,7 @@ StorageDead(_3); StorageLive(_5); _5 = _2; -- _0 = std::ptr::drop_in_place::>(move _5) -> bb2; +- _0 = std::ptr::drop_in_place::>(move _5) -> [return: bb2, unwind continue]; + StorageLive(_6); + StorageLive(_7); + _6 = discriminant((*_5)); @@ -44,7 +44,7 @@ + } + + bb3: { -+ drop((((*_5) as Some).0: B)) -> bb2; ++ drop((((*_5) as Some).0: B)) -> [return: bb2, unwind continue]; } } diff --git a/tests/mir-opt/inline/inline_specialization.main.Inline.panic-unwind.diff b/tests/mir-opt/inline/inline_specialization.main.Inline.panic-unwind.diff index 0f7b1909f8dd..bc841101df73 100644 --- a/tests/mir-opt/inline/inline_specialization.main.Inline.panic-unwind.diff +++ b/tests/mir-opt/inline/inline_specialization.main.Inline.panic-unwind.diff @@ -12,7 +12,7 @@ bb0: { StorageLive(_1); -- _1 = as Foo>::bar() -> bb1; +- _1 = as Foo>::bar() -> [return: bb1, unwind continue]; - } - - bb1: { diff --git a/tests/mir-opt/inline/inline_trait_method.test.Inline.after.panic-unwind.mir b/tests/mir-opt/inline/inline_trait_method.test.Inline.after.panic-unwind.mir index 9550fdea1920..da18a5adc376 100644 --- a/tests/mir-opt/inline/inline_trait_method.test.Inline.after.panic-unwind.mir +++ b/tests/mir-opt/inline/inline_trait_method.test.Inline.after.panic-unwind.mir @@ -8,7 +8,7 @@ fn test(_1: &dyn X) -> u32 { bb0: { StorageLive(_2); _2 = &(*_1); - _0 = ::y(move _2) -> bb1; + _0 = ::y(move _2) -> [return: bb1, unwind continue]; } bb1: { diff --git a/tests/mir-opt/inline/inline_trait_method_2.test2.Inline.after.panic-unwind.mir b/tests/mir-opt/inline/inline_trait_method_2.test2.Inline.after.panic-unwind.mir index ffc16bfe6709..5d4979680a48 100644 --- a/tests/mir-opt/inline/inline_trait_method_2.test2.Inline.after.panic-unwind.mir +++ b/tests/mir-opt/inline/inline_trait_method_2.test2.Inline.after.panic-unwind.mir @@ -15,7 +15,7 @@ fn test2(_1: &dyn X) -> bool { _3 = &(*_1); _2 = move _3 as &dyn X (Pointer(Unsize)); StorageDead(_3); - _0 = ::y(_2) -> bb1; + _0 = ::y(_2) -> [return: bb1, unwind continue]; } bb1: { diff --git a/tests/mir-opt/inline/issue_106141.outer.Inline.panic-unwind.diff b/tests/mir-opt/inline/issue_106141.outer.Inline.panic-unwind.diff index 1e407f07d096..16a19f4a3569 100644 --- a/tests/mir-opt/inline/issue_106141.outer.Inline.panic-unwind.diff +++ b/tests/mir-opt/inline/issue_106141.outer.Inline.panic-unwind.diff @@ -16,16 +16,16 @@ + } bb0: { -- _0 = inner() -> bb1; +- _0 = inner() -> [return: bb1, unwind continue]; + StorageLive(_1); + _1 = const _; -+ _0 = index() -> bb1; ++ _0 = index() -> [return: bb1, unwind continue]; } bb1: { + StorageLive(_3); + _2 = Lt(_0, const 1_usize); -+ assert(move _2, "index out of bounds: the length is {} but the index is {}", const 1_usize, _0) -> bb2; ++ assert(move _2, "index out of bounds: the length is {} but the index is {}", const 1_usize, _0) -> [success: bb2, unwind continue]; + } + + bb2: { diff --git a/tests/mir-opt/inline/unchecked_shifts.unchecked_shl_unsigned_bigger.Inline.panic-unwind.diff b/tests/mir-opt/inline/unchecked_shifts.unchecked_shl_unsigned_bigger.Inline.panic-unwind.diff index 577fc8bee66f..d71b5c4a626e 100644 --- a/tests/mir-opt/inline/unchecked_shifts.unchecked_shl_unsigned_bigger.Inline.panic-unwind.diff +++ b/tests/mir-opt/inline/unchecked_shifts.unchecked_shl_unsigned_bigger.Inline.panic-unwind.diff @@ -20,7 +20,7 @@ _3 = _1; StorageLive(_4); _4 = _2; -- _0 = core::num::::unchecked_shl(move _3, move _4) -> bb1; +- _0 = core::num::::unchecked_shl(move _3, move _4) -> [return: bb1, unwind continue]; - } - - bb1: { diff --git a/tests/mir-opt/inline/unchecked_shifts.unchecked_shl_unsigned_smaller.Inline.panic-unwind.diff b/tests/mir-opt/inline/unchecked_shifts.unchecked_shl_unsigned_smaller.Inline.panic-unwind.diff index ba159c063b3b..cae25759cd8e 100644 --- a/tests/mir-opt/inline/unchecked_shifts.unchecked_shl_unsigned_smaller.Inline.panic-unwind.diff +++ b/tests/mir-opt/inline/unchecked_shifts.unchecked_shl_unsigned_smaller.Inline.panic-unwind.diff @@ -22,7 +22,7 @@ _3 = _1; StorageLive(_4); _4 = _2; -- _0 = core::num::::unchecked_shl(move _3, move _4) -> bb1; +- _0 = core::num::::unchecked_shl(move _3, move _4) -> [return: bb1, unwind continue]; - } - - bb1: { diff --git a/tests/mir-opt/inline/unchecked_shifts.unchecked_shr_signed_bigger.Inline.panic-unwind.diff b/tests/mir-opt/inline/unchecked_shifts.unchecked_shr_signed_bigger.Inline.panic-unwind.diff index d7ff104b92e9..6aafb61dc557 100644 --- a/tests/mir-opt/inline/unchecked_shifts.unchecked_shr_signed_bigger.Inline.panic-unwind.diff +++ b/tests/mir-opt/inline/unchecked_shifts.unchecked_shr_signed_bigger.Inline.panic-unwind.diff @@ -20,7 +20,7 @@ _3 = _1; StorageLive(_4); _4 = _2; -- _0 = core::num::::unchecked_shr(move _3, move _4) -> bb1; +- _0 = core::num::::unchecked_shr(move _3, move _4) -> [return: bb1, unwind continue]; - } - - bb1: { diff --git a/tests/mir-opt/inline/unchecked_shifts.unchecked_shr_signed_smaller.Inline.panic-unwind.diff b/tests/mir-opt/inline/unchecked_shifts.unchecked_shr_signed_smaller.Inline.panic-unwind.diff index 3d398e00fc89..fe5331214866 100644 --- a/tests/mir-opt/inline/unchecked_shifts.unchecked_shr_signed_smaller.Inline.panic-unwind.diff +++ b/tests/mir-opt/inline/unchecked_shifts.unchecked_shr_signed_smaller.Inline.panic-unwind.diff @@ -22,7 +22,7 @@ _3 = _1; StorageLive(_4); _4 = _2; -- _0 = core::num::::unchecked_shr(move _3, move _4) -> bb1; +- _0 = core::num::::unchecked_shr(move _3, move _4) -> [return: bb1, unwind continue]; - } - - bb1: { diff --git a/tests/mir-opt/issue_101973.inner.ConstProp.panic-unwind.diff b/tests/mir-opt/issue_101973.inner.ConstProp.panic-unwind.diff index fbfb8f1fd4e6..a6bd29e1c9d1 100644 --- a/tests/mir-opt/issue_101973.inner.ConstProp.panic-unwind.diff +++ b/tests/mir-opt/issue_101973.inner.ConstProp.panic-unwind.diff @@ -45,10 +45,10 @@ StorageLive(_8); - _10 = const 8_i32 as u32 (IntToInt); - _11 = Lt(move _10, const 32_u32); -- assert(move _11, "attempt to shift right by `{}`, which would overflow", const 8_i32) -> bb1; +- assert(move _11, "attempt to shift right by `{}`, which would overflow", const 8_i32) -> [success: bb1, unwind continue]; + _10 = const 8_u32; + _11 = const true; -+ assert(const true, "attempt to shift right by `{}`, which would overflow", const 8_i32) -> bb1; ++ assert(const true, "attempt to shift right by `{}`, which would overflow", const 8_i32) -> [success: bb1, unwind continue]; } bb1: { @@ -57,10 +57,10 @@ StorageDead(_8); - _12 = const 1_i32 as u32 (IntToInt); - _13 = Lt(move _12, const 32_u32); -- assert(move _13, "attempt to shift left by `{}`, which would overflow", const 1_i32) -> bb2; +- assert(move _13, "attempt to shift left by `{}`, which would overflow", const 1_i32) -> [success: bb2, unwind continue]; + _12 = const 1_u32; + _13 = const true; -+ assert(const true, "attempt to shift left by `{}`, which would overflow", const 1_i32) -> bb2; ++ assert(const true, "attempt to shift left by `{}`, which would overflow", const 1_i32) -> [success: bb2, unwind continue]; } bb2: { diff --git a/tests/mir-opt/issue_104451_unwindable_intrinsics.main.AbortUnwindingCalls.after.panic-unwind.mir b/tests/mir-opt/issue_104451_unwindable_intrinsics.main.AbortUnwindingCalls.after.panic-unwind.mir index 8ffd46311dc5..1851747f0a62 100644 --- a/tests/mir-opt/issue_104451_unwindable_intrinsics.main.AbortUnwindingCalls.after.panic-unwind.mir +++ b/tests/mir-opt/issue_104451_unwindable_intrinsics.main.AbortUnwindingCalls.after.panic-unwind.mir @@ -11,6 +11,6 @@ fn main() -> () { StorageLive(_1); StorageLive(_2); _2 = (); - _1 = const_eval_select::<(), fn() -> ! {ow_ct}, fn() -> ! {ow_ct}, !>(move _2, ow_ct, ow_ct); + _1 = const_eval_select::<(), fn() -> ! {ow_ct}, fn() -> ! {ow_ct}, !>(move _2, ow_ct, ow_ct) -> unwind continue; } } diff --git a/tests/mir-opt/issue_41110.test.ElaborateDrops.panic-unwind.diff b/tests/mir-opt/issue_41110.test.ElaborateDrops.panic-unwind.diff index b33d8fc52b40..254658c810db 100644 --- a/tests/mir-opt/issue_41110.test.ElaborateDrops.panic-unwind.diff +++ b/tests/mir-opt/issue_41110.test.ElaborateDrops.panic-unwind.diff @@ -58,7 +58,7 @@ bb5: { StorageDead(_2); -- drop(_1) -> bb6; +- drop(_1) -> [return: bb6, unwind continue]; + goto -> bb6; } diff --git a/tests/mir-opt/issue_41888.main.ElaborateDrops.panic-unwind.diff b/tests/mir-opt/issue_41888.main.ElaborateDrops.panic-unwind.diff index 04071c72555e..4ef3650cdea3 100644 --- a/tests/mir-opt/issue_41888.main.ElaborateDrops.panic-unwind.diff +++ b/tests/mir-opt/issue_41888.main.ElaborateDrops.panic-unwind.diff @@ -85,7 +85,7 @@ bb9: { StorageDead(_2); -- drop(_1) -> bb10; +- drop(_1) -> [return: bb10, unwind continue]; + goto -> bb19; } diff --git a/tests/mir-opt/issue_62289.test.ElaborateDrops.before.panic-unwind.mir b/tests/mir-opt/issue_62289.test.ElaborateDrops.before.panic-unwind.mir index 4bbfe47299c8..7ecdc428e59e 100644 --- a/tests/mir-opt/issue_62289.test.ElaborateDrops.before.panic-unwind.mir +++ b/tests/mir-opt/issue_62289.test.ElaborateDrops.before.panic-unwind.mir @@ -31,7 +31,7 @@ fn test() -> Option> { StorageLive(_1); _2 = SizeOf(u32); _3 = AlignOf(u32); - _4 = alloc::alloc::exchange_malloc(move _2, move _3) -> bb1; + _4 = alloc::alloc::exchange_malloc(move _2, move _3) -> [return: bb1, unwind continue]; } bb1: { @@ -73,13 +73,13 @@ fn test() -> Option> { bb6: { StorageDead(_11); StorageDead(_9); - drop(_5) -> bb9; + drop(_5) -> [return: bb9, unwind continue]; } bb7: { StorageDead(_5); _0 = Option::>::Some(move _1); - drop(_1) -> bb8; + drop(_1) -> [return: bb8, unwind continue]; } bb8: { diff --git a/tests/mir-opt/issue_76432.test.SimplifyComparisonIntegral.panic-unwind.diff b/tests/mir-opt/issue_76432.test.SimplifyComparisonIntegral.panic-unwind.diff index 761673ca546b..25df839c2db9 100644 --- a/tests/mir-opt/issue_76432.test.SimplifyComparisonIntegral.panic-unwind.diff +++ b/tests/mir-opt/issue_76432.test.SimplifyComparisonIntegral.panic-unwind.diff @@ -42,7 +42,7 @@ } bb1: { - _15 = core::panicking::panic(const "internal error: entered unreachable code"); + _15 = core::panicking::panic(const "internal error: entered unreachable code") -> unwind continue; } bb2: { diff --git a/tests/mir-opt/issues/issue_59352.num_to_digit.PreCodegen.after.panic-unwind.mir b/tests/mir-opt/issues/issue_59352.num_to_digit.PreCodegen.after.panic-unwind.mir index e7c1be7e6e65..43a1a1eed20d 100644 --- a/tests/mir-opt/issues/issue_59352.num_to_digit.PreCodegen.after.panic-unwind.mir +++ b/tests/mir-opt/issues/issue_59352.num_to_digit.PreCodegen.after.panic-unwind.mir @@ -26,7 +26,7 @@ fn num_to_digit(_1: char) -> u32 { bb0: { StorageLive(_3); StorageLive(_2); - _2 = char::methods::::to_digit(_1, const 8_u32) -> bb1; + _2 = char::methods::::to_digit(_1, const 8_u32) -> [return: bb1, unwind continue]; } bb1: { @@ -39,7 +39,7 @@ fn num_to_digit(_1: char) -> u32 { bb2: { StorageLive(_5); - _5 = char::methods::::to_digit(_1, const 8_u32) -> bb3; + _5 = char::methods::::to_digit(_1, const 8_u32) -> [return: bb3, unwind continue]; } bb3: { @@ -48,7 +48,7 @@ fn num_to_digit(_1: char) -> u32 { } bb4: { - _7 = core::panicking::panic(const "called `Option::unwrap()` on a `None` value"); + _7 = core::panicking::panic(const "called `Option::unwrap()` on a `None` value") -> unwind continue; } bb5: { diff --git a/tests/mir-opt/lower_array_len.array_bound.NormalizeArrayLen.panic-unwind.diff b/tests/mir-opt/lower_array_len.array_bound.NormalizeArrayLen.panic-unwind.diff index 35a1e51a3ac9..1cba0f27afaa 100644 --- a/tests/mir-opt/lower_array_len.array_bound.NormalizeArrayLen.panic-unwind.diff +++ b/tests/mir-opt/lower_array_len.array_bound.NormalizeArrayLen.panic-unwind.diff @@ -42,7 +42,7 @@ _8 = _1; _9 = Len((*_2)); _10 = Lt(_8, _9); - assert(move _10, "index out of bounds: the length is {} but the index is {}", move _9, _8) -> bb3; + assert(move _10, "index out of bounds: the length is {} but the index is {}", move _9, _8) -> [success: bb3, unwind continue]; } bb3: { diff --git a/tests/mir-opt/lower_array_len.array_bound_mut.NormalizeArrayLen.panic-unwind.diff b/tests/mir-opt/lower_array_len.array_bound_mut.NormalizeArrayLen.panic-unwind.diff index 3c6f37346246..6c450067cc4a 100644 --- a/tests/mir-opt/lower_array_len.array_bound_mut.NormalizeArrayLen.panic-unwind.diff +++ b/tests/mir-opt/lower_array_len.array_bound_mut.NormalizeArrayLen.panic-unwind.diff @@ -45,7 +45,7 @@ _8 = _1; _9 = Len((*_2)); _10 = Lt(_8, _9); - assert(move _10, "index out of bounds: the length is {} but the index is {}", move _9, _8) -> bb3; + assert(move _10, "index out of bounds: the length is {} but the index is {}", move _9, _8) -> [success: bb3, unwind continue]; } bb3: { @@ -59,7 +59,7 @@ _11 = const 0_usize; _12 = Len((*_2)); _13 = Lt(_11, _12); - assert(move _13, "index out of bounds: the length is {} but the index is {}", move _12, _11) -> bb5; + assert(move _13, "index out of bounds: the length is {} but the index is {}", move _12, _11) -> [success: bb5, unwind continue]; } bb5: { diff --git a/tests/mir-opt/lower_slice_len.bound.LowerSliceLenCalls.panic-unwind.diff b/tests/mir-opt/lower_slice_len.bound.LowerSliceLenCalls.panic-unwind.diff index d90f3dddf58e..310b3b26ac56 100644 --- a/tests/mir-opt/lower_slice_len.bound.LowerSliceLenCalls.panic-unwind.diff +++ b/tests/mir-opt/lower_slice_len.bound.LowerSliceLenCalls.panic-unwind.diff @@ -20,7 +20,7 @@ StorageLive(_5); StorageLive(_6); _6 = &(*_2); -- _5 = core::slice::::len(move _6) -> bb1; +- _5 = core::slice::::len(move _6) -> [return: bb1, unwind continue]; + _5 = Len((*_6)); + goto -> bb1; } @@ -38,7 +38,7 @@ _7 = _1; _8 = Len((*_2)); _9 = Lt(_7, _8); - assert(move _9, "index out of bounds: the length is {} but the index is {}", move _8, _7) -> bb3; + assert(move _9, "index out of bounds: the length is {} but the index is {}", move _8, _7) -> [success: bb3, unwind continue]; } bb3: { diff --git a/tests/mir-opt/no_spurious_drop_after_call.main.ElaborateDrops.before.panic-unwind.mir b/tests/mir-opt/no_spurious_drop_after_call.main.ElaborateDrops.before.panic-unwind.mir index 568ad441cbcd..6fb107929e6b 100644 --- a/tests/mir-opt/no_spurious_drop_after_call.main.ElaborateDrops.before.panic-unwind.mir +++ b/tests/mir-opt/no_spurious_drop_after_call.main.ElaborateDrops.before.panic-unwind.mir @@ -14,7 +14,7 @@ fn main() -> () { StorageLive(_4); _4 = const ""; _3 = &(*_4); - _2 = ::to_string(move _3) -> bb1; + _2 = ::to_string(move _3) -> [return: bb1, unwind continue]; } bb1: { diff --git a/tests/mir-opt/nrvo_simple.nrvo.RenameReturnPlace.panic-unwind.diff b/tests/mir-opt/nrvo_simple.nrvo.RenameReturnPlace.panic-unwind.diff index b17675ec1edf..3df8e567f1fe 100644 --- a/tests/mir-opt/nrvo_simple.nrvo.RenameReturnPlace.panic-unwind.diff +++ b/tests/mir-opt/nrvo_simple.nrvo.RenameReturnPlace.panic-unwind.diff @@ -26,7 +26,7 @@ - _6 = &mut _2; + _6 = &mut _0; _5 = &mut (*_6); - _3 = move _4(move _5) -> bb1; + _3 = move _4(move _5) -> [return: bb1, unwind continue]; } bb1: { diff --git a/tests/mir-opt/pre-codegen/checked_ops.step_forward.PreCodegen.after.mir b/tests/mir-opt/pre-codegen/checked_ops.step_forward.PreCodegen.after.mir index 46c078cea0d6..98c267e8e71e 100644 --- a/tests/mir-opt/pre-codegen/checked_ops.step_forward.PreCodegen.after.mir +++ b/tests/mir-opt/pre-codegen/checked_ops.step_forward.PreCodegen.after.mir @@ -31,7 +31,7 @@ fn step_forward(_1: u32, _2: usize) -> u32 { StorageLive(_7); StorageLive(_4); StorageLive(_3); - _3 = ::forward_checked(_1, _2) -> bb1; + _3 = ::forward_checked(_1, _2) -> [return: bb1, unwind continue]; } bb1: { @@ -47,7 +47,7 @@ fn step_forward(_1: u32, _2: usize) -> u32 { } bb2: { - assert(!const true, "attempt to compute `{} + {}`, which would overflow", const _, const 1_u32) -> bb3; + assert(!const true, "attempt to compute `{} + {}`, which would overflow", const _, const 1_u32) -> [success: bb3, unwind continue]; } bb3: { diff --git a/tests/mir-opt/pre-codegen/loops.filter_mapped.PreCodegen.after.mir b/tests/mir-opt/pre-codegen/loops.filter_mapped.PreCodegen.after.mir index b8b2d91adb69..3b49cb711b77 100644 --- a/tests/mir-opt/pre-codegen/loops.filter_mapped.PreCodegen.after.mir +++ b/tests/mir-opt/pre-codegen/loops.filter_mapped.PreCodegen.after.mir @@ -30,7 +30,7 @@ fn filter_mapped(_1: impl Iterator, _2: impl Fn(T) -> Option) -> () bb0: { StorageLive(_4); StorageLive(_3); - _3 = as Iterator>::filter_map:: Option>(move _1, move _2) -> bb1; + _3 = as Iterator>::filter_map:: Option>(move _1, move _2) -> [return: bb1, unwind continue]; } bb1: { @@ -60,7 +60,7 @@ fn filter_mapped(_1: impl Iterator, _2: impl Fn(T) -> Option) -> () bb4: { StorageDead(_9); - drop(_5) -> bb5; + drop(_5) -> [return: bb5, unwind continue]; } bb5: { diff --git a/tests/mir-opt/pre-codegen/loops.int_range.PreCodegen.after.mir b/tests/mir-opt/pre-codegen/loops.int_range.PreCodegen.after.mir index 609555c8c43e..40bb3a37c585 100644 --- a/tests/mir-opt/pre-codegen/loops.int_range.PreCodegen.after.mir +++ b/tests/mir-opt/pre-codegen/loops.int_range.PreCodegen.after.mir @@ -79,7 +79,7 @@ fn int_range(_1: usize, _2: usize) -> () { bb3: { _12 = ((*_5).0: usize); StorageLive(_13); - _13 = ::forward_unchecked(_12, const 1_usize) -> bb4; + _13 = ::forward_unchecked(_12, const 1_usize) -> [return: bb4, unwind continue]; } bb4: { @@ -104,7 +104,7 @@ fn int_range(_1: usize, _2: usize) -> () { bb7: { _15 = ((_11 as Some).0: usize); - _16 = opaque::(_15) -> bb8; + _16 = opaque::(_15) -> [return: bb8, unwind continue]; } bb8: { diff --git a/tests/mir-opt/pre-codegen/loops.mapped.PreCodegen.after.mir b/tests/mir-opt/pre-codegen/loops.mapped.PreCodegen.after.mir index f756f34b7d66..e4e1d052e733 100644 --- a/tests/mir-opt/pre-codegen/loops.mapped.PreCodegen.after.mir +++ b/tests/mir-opt/pre-codegen/loops.mapped.PreCodegen.after.mir @@ -25,7 +25,7 @@ fn mapped(_1: impl Iterator, _2: impl Fn(T) -> U) -> () { bb0: { StorageLive(_4); StorageLive(_3); - _3 = as Iterator>::map:: U>(move _1, move _2) -> bb1; + _3 = as Iterator>::map:: U>(move _1, move _2) -> [return: bb1, unwind continue]; } bb1: { @@ -49,7 +49,7 @@ fn mapped(_1: impl Iterator, _2: impl Fn(T) -> U) -> () { bb4: { StorageDead(_7); - drop(_5) -> bb5; + drop(_5) -> [return: bb5, unwind continue]; } bb5: { diff --git a/tests/mir-opt/pre-codegen/loops.vec_move.PreCodegen.after.mir b/tests/mir-opt/pre-codegen/loops.vec_move.PreCodegen.after.mir index 604cb773da57..1b5f2a0884b0 100644 --- a/tests/mir-opt/pre-codegen/loops.vec_move.PreCodegen.after.mir +++ b/tests/mir-opt/pre-codegen/loops.vec_move.PreCodegen.after.mir @@ -19,7 +19,7 @@ fn vec_move(_1: Vec) -> () { bb0: { StorageLive(_2); - _2 = as IntoIterator>::into_iter(move _1) -> bb1; + _2 = as IntoIterator>::into_iter(move _1) -> [return: bb1, unwind continue]; } bb1: { @@ -41,7 +41,7 @@ fn vec_move(_1: Vec) -> () { bb4: { StorageDead(_5); - drop(_3) -> bb5; + drop(_3) -> [return: bb5, unwind continue]; } bb5: { diff --git a/tests/mir-opt/pre-codegen/optimizes_into_variable.main.ConstProp.32bit.panic-unwind.diff b/tests/mir-opt/pre-codegen/optimizes_into_variable.main.ConstProp.32bit.panic-unwind.diff index a57ce86bc25a..b6929f3f93c6 100644 --- a/tests/mir-opt/pre-codegen/optimizes_into_variable.main.ConstProp.32bit.panic-unwind.diff +++ b/tests/mir-opt/pre-codegen/optimizes_into_variable.main.ConstProp.32bit.panic-unwind.diff @@ -25,9 +25,9 @@ bb0: { StorageLive(_1); - _2 = CheckedAdd(const 2_i32, const 2_i32); -- assert(!move (_2.1: bool), "attempt to compute `{} + {}`, which would overflow", const 2_i32, const 2_i32) -> bb1; +- assert(!move (_2.1: bool), "attempt to compute `{} + {}`, which would overflow", const 2_i32, const 2_i32) -> [success: bb1, unwind continue]; + _2 = const (4_i32, false); -+ assert(!const false, "attempt to compute `{} + {}`, which would overflow", const 2_i32, const 2_i32) -> bb1; ++ assert(!const false, "attempt to compute `{} + {}`, which would overflow", const 2_i32, const 2_i32) -> [success: bb1, unwind continue]; } bb1: { @@ -40,9 +40,9 @@ _5 = const 3_usize; _6 = const 6_usize; - _7 = Lt(_5, _6); -- assert(move _7, "index out of bounds: the length is {} but the index is {}", move _6, _5) -> bb2; +- assert(move _7, "index out of bounds: the length is {} but the index is {}", move _6, _5) -> [success: bb2, unwind continue]; + _7 = const true; -+ assert(const true, "index out of bounds: the length is {} but the index is {}", const 6_usize, const 3_usize) -> bb2; ++ assert(const true, "index out of bounds: the length is {} but the index is {}", const 6_usize, const 3_usize) -> [success: bb2, unwind continue]; } bb2: { diff --git a/tests/mir-opt/pre-codegen/optimizes_into_variable.main.ConstProp.64bit.panic-unwind.diff b/tests/mir-opt/pre-codegen/optimizes_into_variable.main.ConstProp.64bit.panic-unwind.diff index a57ce86bc25a..b6929f3f93c6 100644 --- a/tests/mir-opt/pre-codegen/optimizes_into_variable.main.ConstProp.64bit.panic-unwind.diff +++ b/tests/mir-opt/pre-codegen/optimizes_into_variable.main.ConstProp.64bit.panic-unwind.diff @@ -25,9 +25,9 @@ bb0: { StorageLive(_1); - _2 = CheckedAdd(const 2_i32, const 2_i32); -- assert(!move (_2.1: bool), "attempt to compute `{} + {}`, which would overflow", const 2_i32, const 2_i32) -> bb1; +- assert(!move (_2.1: bool), "attempt to compute `{} + {}`, which would overflow", const 2_i32, const 2_i32) -> [success: bb1, unwind continue]; + _2 = const (4_i32, false); -+ assert(!const false, "attempt to compute `{} + {}`, which would overflow", const 2_i32, const 2_i32) -> bb1; ++ assert(!const false, "attempt to compute `{} + {}`, which would overflow", const 2_i32, const 2_i32) -> [success: bb1, unwind continue]; } bb1: { @@ -40,9 +40,9 @@ _5 = const 3_usize; _6 = const 6_usize; - _7 = Lt(_5, _6); -- assert(move _7, "index out of bounds: the length is {} but the index is {}", move _6, _5) -> bb2; +- assert(move _7, "index out of bounds: the length is {} but the index is {}", move _6, _5) -> [success: bb2, unwind continue]; + _7 = const true; -+ assert(const true, "index out of bounds: the length is {} but the index is {}", const 6_usize, const 3_usize) -> bb2; ++ assert(const true, "index out of bounds: the length is {} but the index is {}", const 6_usize, const 3_usize) -> [success: bb2, unwind continue]; } bb2: { diff --git a/tests/mir-opt/pre-codegen/optimizes_into_variable.main.ScalarReplacementOfAggregates.32bit.panic-unwind.diff b/tests/mir-opt/pre-codegen/optimizes_into_variable.main.ScalarReplacementOfAggregates.32bit.panic-unwind.diff index 1a5617c7639b..e987969d313a 100644 --- a/tests/mir-opt/pre-codegen/optimizes_into_variable.main.ScalarReplacementOfAggregates.32bit.panic-unwind.diff +++ b/tests/mir-opt/pre-codegen/optimizes_into_variable.main.ScalarReplacementOfAggregates.32bit.panic-unwind.diff @@ -27,7 +27,7 @@ bb0: { StorageLive(_1); _2 = CheckedAdd(const 2_i32, const 2_i32); - assert(!move (_2.1: bool), "attempt to compute `{} + {}`, which would overflow", const 2_i32, const 2_i32) -> bb1; + assert(!move (_2.1: bool), "attempt to compute `{} + {}`, which would overflow", const 2_i32, const 2_i32) -> [success: bb1, unwind continue]; } bb1: { @@ -39,7 +39,7 @@ _5 = const 3_usize; _6 = Len(_4); _7 = Lt(_5, _6); - assert(move _7, "index out of bounds: the length is {} but the index is {}", move _6, _5) -> bb2; + assert(move _7, "index out of bounds: the length is {} but the index is {}", move _6, _5) -> [success: bb2, unwind continue]; } bb2: { diff --git a/tests/mir-opt/pre-codegen/optimizes_into_variable.main.ScalarReplacementOfAggregates.64bit.panic-unwind.diff b/tests/mir-opt/pre-codegen/optimizes_into_variable.main.ScalarReplacementOfAggregates.64bit.panic-unwind.diff index 1a5617c7639b..e987969d313a 100644 --- a/tests/mir-opt/pre-codegen/optimizes_into_variable.main.ScalarReplacementOfAggregates.64bit.panic-unwind.diff +++ b/tests/mir-opt/pre-codegen/optimizes_into_variable.main.ScalarReplacementOfAggregates.64bit.panic-unwind.diff @@ -27,7 +27,7 @@ bb0: { StorageLive(_1); _2 = CheckedAdd(const 2_i32, const 2_i32); - assert(!move (_2.1: bool), "attempt to compute `{} + {}`, which would overflow", const 2_i32, const 2_i32) -> bb1; + assert(!move (_2.1: bool), "attempt to compute `{} + {}`, which would overflow", const 2_i32, const 2_i32) -> [success: bb1, unwind continue]; } bb1: { @@ -39,7 +39,7 @@ _5 = const 3_usize; _6 = Len(_4); _7 = Lt(_5, _6); - assert(move _7, "index out of bounds: the length is {} but the index is {}", move _6, _5) -> bb2; + assert(move _7, "index out of bounds: the length is {} but the index is {}", move _6, _5) -> [success: bb2, unwind continue]; } bb2: { diff --git a/tests/mir-opt/pre-codegen/range_iter.forward_loop.PreCodegen.after.panic-unwind.mir b/tests/mir-opt/pre-codegen/range_iter.forward_loop.PreCodegen.after.panic-unwind.mir index cf98f2022c5a..fbe16dc3cd47 100644 --- a/tests/mir-opt/pre-codegen/range_iter.forward_loop.PreCodegen.after.panic-unwind.mir +++ b/tests/mir-opt/pre-codegen/range_iter.forward_loop.PreCodegen.after.panic-unwind.mir @@ -102,7 +102,7 @@ fn forward_loop(_1: u32, _2: u32, _3: impl Fn(u32)) -> () { bb6: { StorageDead(_12); StorageDead(_5); - drop(_3) -> bb7; + drop(_3) -> [return: bb7, unwind continue]; } bb7: { diff --git a/tests/mir-opt/pre-codegen/range_iter.inclusive_loop.PreCodegen.after.panic-unwind.mir b/tests/mir-opt/pre-codegen/range_iter.inclusive_loop.PreCodegen.after.panic-unwind.mir index a7525b8b9a81..04d6da1d9bd4 100644 --- a/tests/mir-opt/pre-codegen/range_iter.inclusive_loop.PreCodegen.after.panic-unwind.mir +++ b/tests/mir-opt/pre-codegen/range_iter.inclusive_loop.PreCodegen.after.panic-unwind.mir @@ -52,7 +52,7 @@ fn inclusive_loop(_1: u32, _2: u32, _3: impl Fn(u32)) -> () { bb3: { StorageDead(_7); StorageDead(_5); - drop(_3) -> bb4; + drop(_3) -> [return: bb4, unwind continue]; } bb4: { diff --git a/tests/mir-opt/pre-codegen/range_iter.range_inclusive_iter_next.PreCodegen.after.panic-unwind.mir b/tests/mir-opt/pre-codegen/range_iter.range_inclusive_iter_next.PreCodegen.after.panic-unwind.mir index af775b454a7f..fd565fe75ec3 100644 --- a/tests/mir-opt/pre-codegen/range_iter.range_inclusive_iter_next.PreCodegen.after.panic-unwind.mir +++ b/tests/mir-opt/pre-codegen/range_iter.range_inclusive_iter_next.PreCodegen.after.panic-unwind.mir @@ -8,7 +8,7 @@ fn range_inclusive_iter_next(_1: &mut RangeInclusive) -> Option { } bb0: { - _0 = as iter::range::RangeInclusiveIteratorImpl>::spec_next(_1) -> bb1; + _0 = as iter::range::RangeInclusiveIteratorImpl>::spec_next(_1) -> [return: bb1, unwind continue]; } bb1: { diff --git a/tests/mir-opt/pre-codegen/range_iter.range_iter_next.PreCodegen.after.panic-unwind.mir b/tests/mir-opt/pre-codegen/range_iter.range_iter_next.PreCodegen.after.panic-unwind.mir index 33752e970d1a..65870f693c06 100644 --- a/tests/mir-opt/pre-codegen/range_iter.range_iter_next.PreCodegen.after.panic-unwind.mir +++ b/tests/mir-opt/pre-codegen/range_iter.range_iter_next.PreCodegen.after.panic-unwind.mir @@ -53,7 +53,7 @@ fn range_iter_next(_1: &mut std::ops::Range) -> Option { bb2: { _7 = ((*_1).0: u32); StorageLive(_8); - _8 = ::forward_unchecked(_7, const 1_usize) -> bb3; + _8 = ::forward_unchecked(_7, const 1_usize) -> [return: bb3, unwind continue]; } bb3: { diff --git a/tests/mir-opt/pre-codegen/slice_index.slice_index_range.PreCodegen.after.panic-unwind.mir b/tests/mir-opt/pre-codegen/slice_index.slice_index_range.PreCodegen.after.panic-unwind.mir index 9f7fca639f75..a6b931d2c244 100644 --- a/tests/mir-opt/pre-codegen/slice_index.slice_index_range.PreCodegen.after.panic-unwind.mir +++ b/tests/mir-opt/pre-codegen/slice_index.slice_index_range.PreCodegen.after.panic-unwind.mir @@ -12,7 +12,7 @@ fn slice_index_range(_1: &[u32], _2: std::ops::Range) -> &[u32] { bb0: { StorageLive(_3); - _3 = as SliceIndex<[u32]>>::index(move _2, _1) -> bb1; + _3 = as SliceIndex<[u32]>>::index(move _2, _1) -> [return: bb1, unwind continue]; } bb1: { diff --git a/tests/mir-opt/pre-codegen/slice_index.slice_index_usize.PreCodegen.after.panic-unwind.mir b/tests/mir-opt/pre-codegen/slice_index.slice_index_usize.PreCodegen.after.panic-unwind.mir index 13bd84f9596c..d576520a8d56 100644 --- a/tests/mir-opt/pre-codegen/slice_index.slice_index_usize.PreCodegen.after.panic-unwind.mir +++ b/tests/mir-opt/pre-codegen/slice_index.slice_index_usize.PreCodegen.after.panic-unwind.mir @@ -10,7 +10,7 @@ fn slice_index_usize(_1: &[u32], _2: usize) -> u32 { bb0: { _3 = Len((*_1)); _4 = Lt(_2, _3); - assert(move _4, "index out of bounds: the length is {} but the index is {}", move _3, _2) -> bb1; + assert(move _4, "index out of bounds: the length is {} but the index is {}", move _3, _2) -> [success: bb1, unwind continue]; } bb1: { diff --git a/tests/mir-opt/pre-codegen/slice_iter.enumerated_loop.PreCodegen.after.panic-unwind.mir b/tests/mir-opt/pre-codegen/slice_iter.enumerated_loop.PreCodegen.after.panic-unwind.mir index 71162df4bd06..8294a5cb6dc5 100644 --- a/tests/mir-opt/pre-codegen/slice_iter.enumerated_loop.PreCodegen.after.panic-unwind.mir +++ b/tests/mir-opt/pre-codegen/slice_iter.enumerated_loop.PreCodegen.after.panic-unwind.mir @@ -164,7 +164,7 @@ fn enumerated_loop(_1: &[T], _2: impl Fn(usize, &T)) -> () { bb6: { StorageDead(_17); StorageDead(_15); - drop(_2) -> bb7; + drop(_2) -> [return: bb7, unwind continue]; } bb7: { diff --git a/tests/mir-opt/pre-codegen/slice_iter.forward_loop.PreCodegen.after.panic-unwind.mir b/tests/mir-opt/pre-codegen/slice_iter.forward_loop.PreCodegen.after.panic-unwind.mir index 08d829d52cce..ff40e450968a 100644 --- a/tests/mir-opt/pre-codegen/slice_iter.forward_loop.PreCodegen.after.panic-unwind.mir +++ b/tests/mir-opt/pre-codegen/slice_iter.forward_loop.PreCodegen.after.panic-unwind.mir @@ -152,7 +152,7 @@ fn forward_loop(_1: &[T], _2: impl Fn(&T)) -> () { bb6: { StorageDead(_16); StorageDead(_14); - drop(_2) -> bb7; + drop(_2) -> [return: bb7, unwind continue]; } bb7: { diff --git a/tests/mir-opt/pre-codegen/slice_iter.range_loop.PreCodegen.after.panic-unwind.mir b/tests/mir-opt/pre-codegen/slice_iter.range_loop.PreCodegen.after.panic-unwind.mir index 5ce8143d98b3..3423c5d865de 100644 --- a/tests/mir-opt/pre-codegen/slice_iter.range_loop.PreCodegen.after.panic-unwind.mir +++ b/tests/mir-opt/pre-codegen/slice_iter.range_loop.PreCodegen.after.panic-unwind.mir @@ -111,7 +111,7 @@ fn range_loop(_1: &[T], _2: impl Fn(usize, &T)) -> () { bb6: { StorageDead(_12); StorageDead(_5); - drop(_2) -> bb7; + drop(_2) -> [return: bb7, unwind continue]; } bb7: { diff --git a/tests/mir-opt/pre-codegen/slice_iter.reverse_loop.PreCodegen.after.panic-unwind.mir b/tests/mir-opt/pre-codegen/slice_iter.reverse_loop.PreCodegen.after.panic-unwind.mir index 14ca6004dfe2..b40d9209d253 100644 --- a/tests/mir-opt/pre-codegen/slice_iter.reverse_loop.PreCodegen.after.panic-unwind.mir +++ b/tests/mir-opt/pre-codegen/slice_iter.reverse_loop.PreCodegen.after.panic-unwind.mir @@ -169,7 +169,7 @@ fn reverse_loop(_1: &[T], _2: impl Fn(&T)) -> () { bb6: { StorageDead(_18); StorageDead(_15); - drop(_2) -> bb7; + drop(_2) -> [return: bb7, unwind continue]; } bb7: { diff --git a/tests/mir-opt/pre-codegen/slice_iter.slice_iter_mut_next_back.PreCodegen.after.panic-unwind.mir b/tests/mir-opt/pre-codegen/slice_iter.slice_iter_mut_next_back.PreCodegen.after.panic-unwind.mir index f9253a321f9c..386f3a9edcd6 100644 --- a/tests/mir-opt/pre-codegen/slice_iter.slice_iter_mut_next_back.PreCodegen.after.panic-unwind.mir +++ b/tests/mir-opt/pre-codegen/slice_iter.slice_iter_mut_next_back.PreCodegen.after.panic-unwind.mir @@ -5,7 +5,7 @@ fn slice_iter_mut_next_back(_1: &mut std::slice::IterMut<'_, T>) -> Option<&mut let mut _0: std::option::Option<&mut T>; bb0: { - _0 = as DoubleEndedIterator>::next_back(_1) -> bb1; + _0 = as DoubleEndedIterator>::next_back(_1) -> [return: bb1, unwind continue]; } bb1: { diff --git a/tests/mir-opt/pre-codegen/slice_iter.slice_iter_next.PreCodegen.after.panic-unwind.mir b/tests/mir-opt/pre-codegen/slice_iter.slice_iter_next.PreCodegen.after.panic-unwind.mir index 207fc8c752f3..e76ec00391cc 100644 --- a/tests/mir-opt/pre-codegen/slice_iter.slice_iter_next.PreCodegen.after.panic-unwind.mir +++ b/tests/mir-opt/pre-codegen/slice_iter.slice_iter_next.PreCodegen.after.panic-unwind.mir @@ -5,7 +5,7 @@ fn slice_iter_next(_1: &mut std::slice::Iter<'_, T>) -> Option<&T> { let mut _0: std::option::Option<&T>; bb0: { - _0 = as Iterator>::next(_1) -> bb1; + _0 = as Iterator>::next(_1) -> [return: bb1, unwind continue]; } bb1: { diff --git a/tests/mir-opt/pre-codegen/spans.outer.PreCodegen.after.panic-unwind.mir b/tests/mir-opt/pre-codegen/spans.outer.PreCodegen.after.panic-unwind.mir index 52e85809735e..1e20b1be56b9 100644 --- a/tests/mir-opt/pre-codegen/spans.outer.PreCodegen.after.panic-unwind.mir +++ b/tests/mir-opt/pre-codegen/spans.outer.PreCodegen.after.panic-unwind.mir @@ -7,7 +7,7 @@ fn outer(_1: u8) -> u8 { bb0: { _2 = &_1; // scope 0 at $DIR/spans.rs:11:11: 11:13 - _0 = inner(_2) -> bb1; // scope 0 at $DIR/spans.rs:11:5: 11:14 + _0 = inner(_2) -> [return: bb1, unwind continue]; // scope 0 at $DIR/spans.rs:11:5: 11:14 // mir::Constant // + span: $DIR/spans.rs:11:5: 11:10 // + literal: Const { ty: for<'a> fn(&'a u8) -> u8 {inner}, val: Value() } diff --git a/tests/mir-opt/reference_prop.debuginfo.ReferencePropagation.diff b/tests/mir-opt/reference_prop.debuginfo.ReferencePropagation.diff index 6732f8b4bb3f..132f66a1ad3c 100644 --- a/tests/mir-opt/reference_prop.debuginfo.ReferencePropagation.diff +++ b/tests/mir-opt/reference_prop.debuginfo.ReferencePropagation.diff @@ -104,7 +104,7 @@ _13 = &(*_26); StorageLive(_15); _15 = RangeFull; - _12 = <[i32; 10] as Index>::index(move _13, move _15) -> bb5; + _12 = <[i32; 10] as Index>::index(move _13, move _15) -> [return: bb5, unwind continue]; } bb5: { diff --git a/tests/mir-opt/reference_prop.dominate_storage.ReferencePropagation.diff b/tests/mir-opt/reference_prop.dominate_storage.ReferencePropagation.diff index 3baa565f03e4..012efa9693ec 100644 --- a/tests/mir-opt/reference_prop.dominate_storage.ReferencePropagation.diff +++ b/tests/mir-opt/reference_prop.dominate_storage.ReferencePropagation.diff @@ -22,7 +22,7 @@ bb2: { _5 = (*_2); - _0 = opaque::(_5) -> bb3; + _0 = opaque::(_5) -> [return: bb3, unwind continue]; } bb3: { diff --git a/tests/mir-opt/reference_prop.maybe_dead.ReferencePropagation.diff b/tests/mir-opt/reference_prop.maybe_dead.ReferencePropagation.diff index 9ceb5a7634dd..c6bd6c212109 100644 --- a/tests/mir-opt/reference_prop.maybe_dead.ReferencePropagation.diff +++ b/tests/mir-opt/reference_prop.maybe_dead.ReferencePropagation.diff @@ -27,17 +27,17 @@ bb1: { StorageDead(_2); StorageDead(_3); - _0 = opaque::(_6) -> bb2; + _0 = opaque::(_6) -> [return: bb2, unwind continue]; } bb2: { _7 = (*_4); - _0 = opaque::(_7) -> bb3; + _0 = opaque::(_7) -> [return: bb3, unwind continue]; } bb3: { _8 = (*_5); - _0 = opaque::(_8) -> bb4; + _0 = opaque::(_8) -> [return: bb4, unwind continue]; } bb4: { diff --git a/tests/mir-opt/reference_prop.multiple_storage.ReferencePropagation.diff b/tests/mir-opt/reference_prop.multiple_storage.ReferencePropagation.diff index 03add1265450..0fd74155aa30 100644 --- a/tests/mir-opt/reference_prop.multiple_storage.ReferencePropagation.diff +++ b/tests/mir-opt/reference_prop.multiple_storage.ReferencePropagation.diff @@ -14,7 +14,7 @@ StorageDead(_1); StorageLive(_1); _3 = (*_2); - _0 = opaque::(_3) -> bb1; + _0 = opaque::(_3) -> [return: bb1, unwind continue]; } bb1: { diff --git a/tests/mir-opt/reference_prop.reference_propagation.ReferencePropagation.diff b/tests/mir-opt/reference_prop.reference_propagation.ReferencePropagation.diff index 43292dd7249a..f1f77cffd200 100644 --- a/tests/mir-opt/reference_prop.reference_propagation.ReferencePropagation.diff +++ b/tests/mir-opt/reference_prop.reference_propagation.ReferencePropagation.diff @@ -201,7 +201,7 @@ StorageLive(_7); StorageLive(_8); _8 = (); - _7 = opaque::<()>(move _8) -> bb1; + _7 = opaque::<()>(move _8) -> [return: bb1, unwind continue]; } bb1: { @@ -232,7 +232,7 @@ StorageLive(_16); StorageLive(_17); _17 = (); - _16 = opaque::<()>(move _17) -> bb2; + _16 = opaque::<()>(move _17) -> [return: bb2, unwind continue]; } bb2: { @@ -256,7 +256,7 @@ StorageLive(_23); StorageLive(_24); _24 = _21; - _23 = opaque::<&&usize>(move _24) -> bb3; + _23 = opaque::<&&usize>(move _24) -> [return: bb3, unwind continue]; } bb3: { @@ -280,7 +280,7 @@ StorageLive(_30); StorageLive(_31); _31 = _28; - _30 = opaque::<*mut &usize>(move _31) -> bb4; + _30 = opaque::<*mut &usize>(move _31) -> [return: bb4, unwind continue]; } bb4: { @@ -303,7 +303,7 @@ StorageLive(_36); StorageLive(_37); _37 = _34; - _36 = opaque::<&usize>(move _37) -> bb5; + _36 = opaque::<&usize>(move _37) -> [return: bb5, unwind continue]; } bb5: { @@ -332,7 +332,7 @@ StorageLive(_45); StorageLive(_46); _46 = _44; - _45 = opaque::<&usize>(move _46) -> bb6; + _45 = opaque::<&usize>(move _46) -> [return: bb6, unwind continue]; } bb6: { @@ -355,7 +355,7 @@ StorageLive(_50); StorageLive(_51); _51 = (); - _50 = opaque::<()>(move _51) -> bb7; + _50 = opaque::<()>(move _51) -> [return: bb7, unwind continue]; } bb7: { @@ -381,7 +381,7 @@ StorageLive(_57); StorageLive(_58); _58 = (); - _57 = opaque::<()>(move _58) -> bb8; + _57 = opaque::<()>(move _58) -> [return: bb8, unwind continue]; } bb8: { @@ -404,7 +404,7 @@ StorageLive(_64); StorageLive(_65); _65 = (); - _64 = opaque::<()>(move _65) -> bb9; + _64 = opaque::<()>(move _65) -> [return: bb9, unwind continue]; } bb9: { @@ -428,7 +428,7 @@ StorageLive(_70); StorageLive(_71); _71 = (); - _70 = opaque::<()>(move _71) -> bb10; + _70 = opaque::<()>(move _71) -> [return: bb10, unwind continue]; } bb10: { diff --git a/tests/mir-opt/reference_prop.reference_propagation_const_ptr.ReferencePropagation.diff b/tests/mir-opt/reference_prop.reference_propagation_const_ptr.ReferencePropagation.diff index 3a317853bdb7..05eab7989dfb 100644 --- a/tests/mir-opt/reference_prop.reference_propagation_const_ptr.ReferencePropagation.diff +++ b/tests/mir-opt/reference_prop.reference_propagation_const_ptr.ReferencePropagation.diff @@ -242,7 +242,7 @@ StorageLive(_7); StorageLive(_8); _8 = (); - _7 = opaque::<()>(move _8) -> bb1; + _7 = opaque::<()>(move _8) -> [return: bb1, unwind continue]; } bb1: { @@ -269,7 +269,7 @@ StorageLive(_15); StorageLive(_16); _16 = (); - _15 = opaque::<()>(move _16) -> bb2; + _15 = opaque::<()>(move _16) -> [return: bb2, unwind continue]; } bb2: { @@ -293,7 +293,7 @@ StorageLive(_22); StorageLive(_23); _23 = _20; - _22 = opaque::<&*const usize>(move _23) -> bb3; + _22 = opaque::<&*const usize>(move _23) -> [return: bb3, unwind continue]; } bb3: { @@ -317,7 +317,7 @@ StorageLive(_29); StorageLive(_30); _30 = _27; - _29 = opaque::<*mut *const usize>(move _30) -> bb4; + _29 = opaque::<*mut *const usize>(move _30) -> [return: bb4, unwind continue]; } bb4: { @@ -340,7 +340,7 @@ StorageLive(_35); StorageLive(_36); _36 = _33; - _35 = opaque::<*const usize>(move _36) -> bb5; + _35 = opaque::<*const usize>(move _36) -> [return: bb5, unwind continue]; } bb5: { @@ -369,7 +369,7 @@ StorageLive(_44); StorageLive(_45); _45 = _43; - _44 = opaque::<*const usize>(move _45) -> bb6; + _44 = opaque::<*const usize>(move _45) -> [return: bb6, unwind continue]; } bb6: { @@ -392,7 +392,7 @@ StorageLive(_49); StorageLive(_50); _50 = (); - _49 = opaque::<()>(move _50) -> bb7; + _49 = opaque::<()>(move _50) -> [return: bb7, unwind continue]; } bb7: { @@ -414,7 +414,7 @@ StorageLive(_55); StorageLive(_56); _56 = (); - _55 = opaque::<()>(move _56) -> bb8; + _55 = opaque::<()>(move _56) -> [return: bb8, unwind continue]; } bb8: { @@ -437,7 +437,7 @@ StorageLive(_62); StorageLive(_63); _63 = (); - _62 = opaque::<()>(move _63) -> bb9; + _62 = opaque::<()>(move _63) -> [return: bb9, unwind continue]; } bb9: { @@ -462,7 +462,7 @@ StorageLive(_69); StorageLive(_70); _70 = (); - _69 = opaque::<()>(move _70) -> bb10; + _69 = opaque::<()>(move _70) -> [return: bb10, unwind continue]; } bb10: { @@ -486,7 +486,7 @@ StorageLive(_75); StorageLive(_76); _76 = (); - _75 = opaque::<()>(move _76) -> bb11; + _75 = opaque::<()>(move _76) -> [return: bb11, unwind continue]; } bb11: { diff --git a/tests/mir-opt/reference_prop.reference_propagation_mut.ReferencePropagation.diff b/tests/mir-opt/reference_prop.reference_propagation_mut.ReferencePropagation.diff index 91c6b2b63220..ee680fdb3f21 100644 --- a/tests/mir-opt/reference_prop.reference_propagation_mut.ReferencePropagation.diff +++ b/tests/mir-opt/reference_prop.reference_propagation_mut.ReferencePropagation.diff @@ -201,7 +201,7 @@ StorageLive(_7); StorageLive(_8); _8 = (); - _7 = opaque::<()>(move _8) -> bb1; + _7 = opaque::<()>(move _8) -> [return: bb1, unwind continue]; } bb1: { @@ -232,7 +232,7 @@ StorageLive(_16); StorageLive(_17); _17 = (); - _16 = opaque::<()>(move _17) -> bb2; + _16 = opaque::<()>(move _17) -> [return: bb2, unwind continue]; } bb2: { @@ -256,7 +256,7 @@ StorageLive(_23); StorageLive(_24); _24 = _21; - _23 = opaque::<&&mut usize>(move _24) -> bb3; + _23 = opaque::<&&mut usize>(move _24) -> [return: bb3, unwind continue]; } bb3: { @@ -280,7 +280,7 @@ StorageLive(_30); StorageLive(_31); _31 = _28; - _30 = opaque::<*mut &mut usize>(move _31) -> bb4; + _30 = opaque::<*mut &mut usize>(move _31) -> [return: bb4, unwind continue]; } bb4: { @@ -302,7 +302,7 @@ StorageLive(_36); StorageLive(_37); _37 = move _34; - _36 = opaque::<&mut usize>(move _37) -> bb5; + _36 = opaque::<&mut usize>(move _37) -> [return: bb5, unwind continue]; } bb5: { @@ -329,7 +329,7 @@ StorageLive(_45); StorageLive(_46); _46 = move _44; - _45 = opaque::<&mut usize>(move _46) -> bb6; + _45 = opaque::<&mut usize>(move _46) -> [return: bb6, unwind continue]; } bb6: { @@ -352,7 +352,7 @@ StorageLive(_50); StorageLive(_51); _51 = (); - _50 = opaque::<()>(move _51) -> bb7; + _50 = opaque::<()>(move _51) -> [return: bb7, unwind continue]; } bb7: { @@ -378,7 +378,7 @@ StorageLive(_57); StorageLive(_58); _58 = (); - _57 = opaque::<()>(move _58) -> bb8; + _57 = opaque::<()>(move _58) -> [return: bb8, unwind continue]; } bb8: { @@ -401,7 +401,7 @@ StorageLive(_64); StorageLive(_65); _65 = (); - _64 = opaque::<()>(move _65) -> bb9; + _64 = opaque::<()>(move _65) -> [return: bb9, unwind continue]; } bb9: { @@ -425,7 +425,7 @@ StorageLive(_70); StorageLive(_71); _71 = (); - _70 = opaque::<()>(move _71) -> bb10; + _70 = opaque::<()>(move _71) -> [return: bb10, unwind continue]; } bb10: { diff --git a/tests/mir-opt/reference_prop.reference_propagation_mut_ptr.ReferencePropagation.diff b/tests/mir-opt/reference_prop.reference_propagation_mut_ptr.ReferencePropagation.diff index 8c669644c48a..fb0ef3184f00 100644 --- a/tests/mir-opt/reference_prop.reference_propagation_mut_ptr.ReferencePropagation.diff +++ b/tests/mir-opt/reference_prop.reference_propagation_mut_ptr.ReferencePropagation.diff @@ -219,7 +219,7 @@ StorageLive(_7); StorageLive(_8); _8 = (); - _7 = opaque::<()>(move _8) -> bb1; + _7 = opaque::<()>(move _8) -> [return: bb1, unwind continue]; } bb1: { @@ -246,7 +246,7 @@ StorageLive(_15); StorageLive(_16); _16 = (); - _15 = opaque::<()>(move _16) -> bb2; + _15 = opaque::<()>(move _16) -> [return: bb2, unwind continue]; } bb2: { @@ -270,7 +270,7 @@ StorageLive(_22); StorageLive(_23); _23 = _20; - _22 = opaque::<&*mut usize>(move _23) -> bb3; + _22 = opaque::<&*mut usize>(move _23) -> [return: bb3, unwind continue]; } bb3: { @@ -294,7 +294,7 @@ StorageLive(_29); StorageLive(_30); _30 = _27; - _29 = opaque::<*mut *mut usize>(move _30) -> bb4; + _29 = opaque::<*mut *mut usize>(move _30) -> [return: bb4, unwind continue]; } bb4: { @@ -316,7 +316,7 @@ StorageLive(_35); StorageLive(_36); _36 = _33; - _35 = opaque::<*mut usize>(move _36) -> bb5; + _35 = opaque::<*mut usize>(move _36) -> [return: bb5, unwind continue]; } bb5: { @@ -343,7 +343,7 @@ StorageLive(_44); StorageLive(_45); _45 = _43; - _44 = opaque::<*mut usize>(move _45) -> bb6; + _44 = opaque::<*mut usize>(move _45) -> [return: bb6, unwind continue]; } bb6: { @@ -366,7 +366,7 @@ StorageLive(_49); StorageLive(_50); _50 = (); - _49 = opaque::<()>(move _50) -> bb7; + _49 = opaque::<()>(move _50) -> [return: bb7, unwind continue]; } bb7: { @@ -388,7 +388,7 @@ StorageLive(_55); StorageLive(_56); _56 = (); - _55 = opaque::<()>(move _56) -> bb8; + _55 = opaque::<()>(move _56) -> [return: bb8, unwind continue]; } bb8: { @@ -411,7 +411,7 @@ StorageLive(_62); StorageLive(_63); _63 = (); - _62 = opaque::<()>(move _63) -> bb9; + _62 = opaque::<()>(move _63) -> [return: bb9, unwind continue]; } bb9: { @@ -435,7 +435,7 @@ StorageLive(_68); StorageLive(_69); _69 = (); - _68 = opaque::<()>(move _69) -> bb10; + _68 = opaque::<()>(move _69) -> [return: bb10, unwind continue]; } bb10: { diff --git a/tests/mir-opt/reference_prop.unique_with_copies.ReferencePropagation.diff b/tests/mir-opt/reference_prop.unique_with_copies.ReferencePropagation.diff index b4c34c07022b..b4912a918ba4 100644 --- a/tests/mir-opt/reference_prop.unique_with_copies.ReferencePropagation.diff +++ b/tests/mir-opt/reference_prop.unique_with_copies.ReferencePropagation.diff @@ -34,7 +34,7 @@ StorageLive(_4); StorageLive(_5); _5 = (*_3); - _4 = opaque::(move _5) -> bb1; + _4 = opaque::(move _5) -> [return: bb1, unwind continue]; } bb1: { @@ -47,7 +47,7 @@ StorageLive(_7); - _7 = (*_1); + _7 = (*_3); - _6 = opaque::(move _7) -> bb2; + _6 = opaque::(move _7) -> [return: bb2, unwind continue]; } bb2: { diff --git a/tests/mir-opt/remove_storage_markers.main.RemoveStorageMarkers.panic-unwind.diff b/tests/mir-opt/remove_storage_markers.main.RemoveStorageMarkers.panic-unwind.diff index d7f867e31dde..faaebc300efa 100644 --- a/tests/mir-opt/remove_storage_markers.main.RemoveStorageMarkers.panic-unwind.diff +++ b/tests/mir-opt/remove_storage_markers.main.RemoveStorageMarkers.panic-unwind.diff @@ -32,7 +32,7 @@ - StorageLive(_2); - StorageLive(_3); _3 = std::ops::Range:: { start: const 0_i32, end: const 10_i32 }; - _2 = as IntoIterator>::into_iter(move _3) -> bb1; + _2 = as IntoIterator>::into_iter(move _3) -> [return: bb1, unwind continue]; } bb1: { @@ -49,7 +49,7 @@ - StorageLive(_9); _9 = &mut _4; _8 = &mut (*_9); - _7 = as Iterator>::next(move _8) -> bb3; + _7 = as Iterator>::next(move _8) -> [return: bb3, unwind continue]; } bb3: { diff --git a/tests/mir-opt/remove_unneeded_drops.opt.RemoveUnneededDrops.panic-unwind.diff b/tests/mir-opt/remove_unneeded_drops.opt.RemoveUnneededDrops.panic-unwind.diff index 8cb773e48076..a335e8853f38 100644 --- a/tests/mir-opt/remove_unneeded_drops.opt.RemoveUnneededDrops.panic-unwind.diff +++ b/tests/mir-opt/remove_unneeded_drops.opt.RemoveUnneededDrops.panic-unwind.diff @@ -14,7 +14,7 @@ - nop; StorageLive(_3); _3 = _1; -- drop(_3) -> bb1; +- drop(_3) -> [return: bb1, unwind continue]; - } - - bb1: { diff --git a/tests/mir-opt/remove_unneeded_drops.opt_generic_copy.RemoveUnneededDrops.panic-unwind.diff b/tests/mir-opt/remove_unneeded_drops.opt_generic_copy.RemoveUnneededDrops.panic-unwind.diff index d189e5879820..1f7a6f9ad59f 100644 --- a/tests/mir-opt/remove_unneeded_drops.opt_generic_copy.RemoveUnneededDrops.panic-unwind.diff +++ b/tests/mir-opt/remove_unneeded_drops.opt_generic_copy.RemoveUnneededDrops.panic-unwind.diff @@ -14,7 +14,7 @@ - nop; StorageLive(_3); _3 = _1; -- drop(_3) -> bb1; +- drop(_3) -> [return: bb1, unwind continue]; - } - - bb1: { diff --git a/tests/mir-opt/retag.array_casts.SimplifyCfg-elaborate-drops.after.panic-unwind.mir b/tests/mir-opt/retag.array_casts.SimplifyCfg-elaborate-drops.after.panic-unwind.mir index 18eb21d6542e..93f14af29b4e 100644 --- a/tests/mir-opt/retag.array_casts.SimplifyCfg-elaborate-drops.after.panic-unwind.mir +++ b/tests/mir-opt/retag.array_casts.SimplifyCfg-elaborate-drops.after.panic-unwind.mir @@ -76,7 +76,7 @@ fn array_casts() -> () { StorageLive(_6); StorageLive(_7); _7 = _2; - _6 = ptr::mut_ptr::::add(move _7, const 1_usize) -> bb1; + _6 = ptr::mut_ptr::::add(move _7, const 1_usize) -> [return: bb1, unwind continue]; } bb1: { @@ -102,7 +102,7 @@ fn array_casts() -> () { StorageLive(_16); StorageLive(_17); _17 = _9; - _16 = ptr::const_ptr::::add(move _17, const 1_usize) -> bb2; + _16 = ptr::const_ptr::::add(move _17, const 1_usize) -> [return: bb2, unwind continue]; } bb2: { @@ -154,7 +154,7 @@ fn array_casts() -> () { StorageLive(_34); _34 = Option::>::None; Retag(_34); - _28 = core::panicking::assert_failed::(move _29, move _30, move _32, move _34); + _28 = core::panicking::assert_failed::(move _29, move _30, move _32, move _34) -> unwind continue; } bb4: { diff --git a/tests/mir-opt/retag.core.ptr-drop_in_place.Test.SimplifyCfg-make_shim.after.panic-unwind.mir b/tests/mir-opt/retag.core.ptr-drop_in_place.Test.SimplifyCfg-make_shim.after.panic-unwind.mir index 96d2abf98b4f..70c53bafa373 100644 --- a/tests/mir-opt/retag.core.ptr-drop_in_place.Test.SimplifyCfg-make_shim.after.panic-unwind.mir +++ b/tests/mir-opt/retag.core.ptr-drop_in_place.Test.SimplifyCfg-make_shim.after.panic-unwind.mir @@ -10,7 +10,7 @@ fn std::ptr::drop_in_place(_1: *mut Test) -> () { _2 = &mut (*_1); Retag([fn entry] _2); _3 = &mut (*_2); - _4 = ::drop(move _3) -> bb1; + _4 = ::drop(move _3) -> [return: bb1, unwind continue]; } bb1: { diff --git a/tests/mir-opt/retag.main.SimplifyCfg-elaborate-drops.after.panic-unwind.mir b/tests/mir-opt/retag.main.SimplifyCfg-elaborate-drops.after.panic-unwind.mir index 483485f2942e..450349463287 100644 --- a/tests/mir-opt/retag.main.SimplifyCfg-elaborate-drops.after.panic-unwind.mir +++ b/tests/mir-opt/retag.main.SimplifyCfg-elaborate-drops.after.panic-unwind.mir @@ -114,7 +114,7 @@ fn main() -> () { StorageLive(_18); _18 = &_1; _17 = &(*_18); - _15 = move _16(move _17) -> bb3; + _15 = move _16(move _17) -> [return: bb3, unwind continue]; } bb3: { @@ -153,7 +153,7 @@ fn main() -> () { _25 = _26; StorageDead(_26); StorageLive(_27); - _27 = array_casts() -> bb6; + _27 = array_casts() -> [return: bb6, unwind continue]; } bb6: { diff --git a/tests/mir-opt/simplify_if.main.SimplifyConstCondition-after-const-prop.panic-unwind.diff b/tests/mir-opt/simplify_if.main.SimplifyConstCondition-after-const-prop.panic-unwind.diff index 2a841f72ba39..81903c64dbd4 100644 --- a/tests/mir-opt/simplify_if.main.SimplifyConstCondition-after-const-prop.panic-unwind.diff +++ b/tests/mir-opt/simplify_if.main.SimplifyConstCondition-after-const-prop.panic-unwind.diff @@ -14,7 +14,7 @@ } bb1: { - _2 = noop() -> bb2; + _2 = noop() -> [return: bb2, unwind continue]; } bb2: { diff --git a/tests/mir-opt/simplify_locals_fixedpoint.foo.SimplifyLocals-final.panic-unwind.diff b/tests/mir-opt/simplify_locals_fixedpoint.foo.SimplifyLocals-final.panic-unwind.diff index ef3a923fd696..ba5262b0ee14 100644 --- a/tests/mir-opt/simplify_locals_fixedpoint.foo.SimplifyLocals-final.panic-unwind.diff +++ b/tests/mir-opt/simplify_locals_fixedpoint.foo.SimplifyLocals-final.panic-unwind.diff @@ -39,7 +39,7 @@ } bb3: { - drop(_1) -> bb4; + drop(_1) -> [return: bb4, unwind continue]; } bb4: { diff --git a/tests/mir-opt/simplify_locals_removes_unused_consts.main.SimplifyLocals-before-const-prop.panic-unwind.diff b/tests/mir-opt/simplify_locals_removes_unused_consts.main.SimplifyLocals-before-const-prop.panic-unwind.diff index dca516020214..a5d9bbc49af0 100644 --- a/tests/mir-opt/simplify_locals_removes_unused_consts.main.SimplifyLocals-before-const-prop.panic-unwind.diff +++ b/tests/mir-opt/simplify_locals_removes_unused_consts.main.SimplifyLocals-before-const-prop.panic-unwind.diff @@ -36,7 +36,7 @@ + _2 = (move _3, move _4); + StorageDead(_4); StorageDead(_3); -+ _1 = use_zst(move _2) -> bb1; ++ _1 = use_zst(move _2) -> [return: bb1, unwind continue]; + } + + bb1: { @@ -55,8 +55,8 @@ + _6 = Add(move _7, const 2_u8); StorageDead(_7); - StorageDead(_6); -- _4 = use_zst(move _5) -> bb1; -+ _5 = use_u8(move _6) -> bb2; +- _4 = use_zst(move _5) -> [return: bb1, unwind continue]; ++ _5 = use_u8(move _6) -> [return: bb2, unwind continue]; } - bb1: { @@ -70,7 +70,7 @@ - _10 = (_11.0: u8); - _9 = Add(move _10, const 2_u8); - StorageDead(_10); -- _8 = use_u8(move _9) -> bb2; +- _8 = use_u8(move _9) -> [return: bb2, unwind continue]; - } - bb2: { diff --git a/tests/mir-opt/simplify_match.main.ConstProp.panic-unwind.diff b/tests/mir-opt/simplify_match.main.ConstProp.panic-unwind.diff index dc2f75ec9b28..c881dec28c77 100644 --- a/tests/mir-opt/simplify_match.main.ConstProp.panic-unwind.diff +++ b/tests/mir-opt/simplify_match.main.ConstProp.panic-unwind.diff @@ -20,7 +20,7 @@ } bb2: { - _0 = noop() -> bb3; + _0 = noop() -> [return: bb3, unwind continue]; } bb3: { diff --git a/tests/mir-opt/unreachable.main.UnreachablePropagation.panic-unwind.diff b/tests/mir-opt/unreachable.main.UnreachablePropagation.panic-unwind.diff index 19ea846bf2ce..906dce9819fd 100644 --- a/tests/mir-opt/unreachable.main.UnreachablePropagation.panic-unwind.diff +++ b/tests/mir-opt/unreachable.main.UnreachablePropagation.panic-unwind.diff @@ -19,7 +19,7 @@ bb0: { StorageLive(_1); - _1 = empty() -> bb1; + _1 = empty() -> [return: bb1, unwind continue]; } bb1: { diff --git a/tests/mir-opt/unreachable_diverging.main.UnreachablePropagation.panic-unwind.diff b/tests/mir-opt/unreachable_diverging.main.UnreachablePropagation.panic-unwind.diff index 9d54a2f234b1..a0479fb91304 100644 --- a/tests/mir-opt/unreachable_diverging.main.UnreachablePropagation.panic-unwind.diff +++ b/tests/mir-opt/unreachable_diverging.main.UnreachablePropagation.panic-unwind.diff @@ -21,7 +21,7 @@ StorageLive(_1); _1 = const true; StorageLive(_2); - _2 = empty() -> bb1; + _2 = empty() -> [return: bb1, unwind continue]; } bb1: { @@ -39,7 +39,7 @@ } bb3: { - _5 = loop_forever() -> bb5; + _5 = loop_forever() -> [return: bb5, unwind continue]; } bb4: { diff --git a/tests/mir-opt/while_storage.while_loop.PreCodegen.after.panic-unwind.mir b/tests/mir-opt/while_storage.while_loop.PreCodegen.after.panic-unwind.mir index ec4782e5f3c7..7dc4f7ab1a87 100644 --- a/tests/mir-opt/while_storage.while_loop.PreCodegen.after.panic-unwind.mir +++ b/tests/mir-opt/while_storage.while_loop.PreCodegen.after.panic-unwind.mir @@ -12,7 +12,7 @@ fn while_loop(_1: bool) -> () { bb1: { StorageLive(_2); - _2 = get_bool(_1) -> bb2; + _2 = get_bool(_1) -> [return: bb2, unwind continue]; } bb2: { @@ -21,7 +21,7 @@ fn while_loop(_1: bool) -> () { bb3: { StorageLive(_3); - _3 = get_bool(_1) -> bb4; + _3 = get_bool(_1) -> [return: bb4, unwind continue]; } bb4: { diff --git a/tests/run-make-fulldeps/obtain-borrowck/driver.rs b/tests/run-make-fulldeps/obtain-borrowck/driver.rs index b59a65a713f9..04c551cf4bb6 100644 --- a/tests/run-make-fulldeps/obtain-borrowck/driver.rs +++ b/tests/run-make-fulldeps/obtain-borrowck/driver.rs @@ -27,7 +27,7 @@ use rustc_interface::{Config, Queries}; use rustc_middle::query::queries::mir_borrowck::ProvidedValue; use rustc_middle::query::{ExternProviders, Providers}; use rustc_middle::ty::TyCtxt; -use rustc_session::Session; +use rustc_session::{Session, EarlyErrorHandler}; use std::cell::RefCell; use std::collections::HashMap; use std::thread_local; @@ -58,6 +58,7 @@ impl rustc_driver::Callbacks for CompilerCalls { // the result. fn after_analysis<'tcx>( &mut self, + _handler: &EarlyErrorHandler, compiler: &Compiler, queries: &'tcx Queries<'tcx>, ) -> Compilation { diff --git a/tests/run-make/const_fn_mir/dump.mir b/tests/run-make/const_fn_mir/dump.mir index 25ac0c7e852a..ced170bbeee2 100644 --- a/tests/run-make/const_fn_mir/dump.mir +++ b/tests/run-make/const_fn_mir/dump.mir @@ -6,7 +6,7 @@ fn foo() -> i32 { bb0: { _1 = CheckedAdd(const 5_i32, const 6_i32); - assert(!move (_1.1: bool), "attempt to compute `{} + {}`, which would overflow", const 5_i32, const 6_i32) -> bb1; + assert(!move (_1.1: bool), "attempt to compute `{} + {}`, which would overflow", const 5_i32, const 6_i32) -> [success: bb1, unwind continue]; } bb1: { @@ -22,7 +22,7 @@ fn foo() -> i32 { bb0: { _1 = CheckedAdd(const 5_i32, const 6_i32); - assert(!move (_1.1: bool), "attempt to compute `{} + {}`, which would overflow", const 5_i32, const 6_i32) -> bb1; + assert(!move (_1.1: bool), "attempt to compute `{} + {}`, which would overflow", const 5_i32, const 6_i32) -> [success: bb1, unwind continue]; } bb1: { @@ -36,7 +36,7 @@ fn main() -> () { let _1: i32; bb0: { - _1 = foo() -> bb1; + _1 = foo() -> [return: bb1, unwind continue]; } bb1: { diff --git a/tests/rustdoc-gui/docblock-code-block-line-number.goml b/tests/rustdoc-gui/docblock-code-block-line-number.goml index 4c36394a30ce..a50449e17010 100644 --- a/tests/rustdoc-gui/docblock-code-block-line-number.goml +++ b/tests/rustdoc-gui/docblock-code-block-line-number.goml @@ -37,15 +37,15 @@ define-function: ( ) call-function: ("check-colors", { "theme": "ayu", - "color": "rgb(92, 103, 115)", + "color": "#5c6773", }) call-function: ("check-colors", { "theme": "dark", - "color": "rgb(59, 145, 226)", + "color": "#3b91e2", }) call-function: ("check-colors", { "theme": "light", - "color": "rgb(198, 126, 45)", + "color": "#c67e2d", }) // The first code block has two lines so let's check its `
` elements lists both of them.
diff --git a/tests/rustdoc-gui/search-result-display.goml b/tests/rustdoc-gui/search-result-display.goml
index afb3a44be303..6593c1a9c45a 100644
--- a/tests/rustdoc-gui/search-result-display.goml
+++ b/tests/rustdoc-gui/search-result-display.goml
@@ -14,7 +14,8 @@ set-window-size: (600, 100)
 assert-size: (".search-results div.desc", {"width": 566})
 
 // The result set is all on one line.
-assert-css: (".search-results .result-name > span", {"display": "inline"})
+assert-css: (".search-results .result-name > span:not(.typename)", {"display": "inline"})
+assert-css: (".search-results .result-name > span.typename", {"display": "inline-block"})
 
 // Check that the crate filter `