From ed983c21842be5e84f11b745c0c04ea23baa5509 Mon Sep 17 00:00:00 2001 From: dianne Date: Mon, 19 May 2025 18:02:54 -0700 Subject: [PATCH 1/7] only resolve top-level guard patterns' guards once We resolve guard patterns' guards in `resolve_pattern_inner`, so to avoid resolving them multiple times, we must avoid doing so earlier. To accomplish this, `LateResolutionVisitor::visit_pat` contains a case for guard patterns that avoids visiting their guards while walking patterns. This fixes an ICE due to `visit::walk_pat` being used instead, which meant guards at the top level of a pattern would be visited twice. --- compiler/rustc_resolve/src/late.rs | 4 +- ...ve-top-level-guard-expr-once-ice-141265.rs | 12 +++++ ...op-level-guard-expr-once-ice-141265.stderr | 48 +++++++++++++++++++ 3 files changed, 63 insertions(+), 1 deletion(-) create mode 100644 tests/ui/pattern/rfc-3637-guard-patterns/only-resolve-top-level-guard-expr-once-ice-141265.rs create mode 100644 tests/ui/pattern/rfc-3637-guard-patterns/only-resolve-top-level-guard-expr-once-ice-141265.stderr diff --git a/compiler/rustc_resolve/src/late.rs b/compiler/rustc_resolve/src/late.rs index 1b682d0cf8ae9..fd977a8eb6c0b 100644 --- a/compiler/rustc_resolve/src/late.rs +++ b/compiler/rustc_resolve/src/late.rs @@ -3901,7 +3901,9 @@ impl<'a, 'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> { // We walk the pattern before declaring the pattern's inner bindings, // so that we avoid resolving a literal expression to a binding defined // by the pattern. - visit::walk_pat(self, pat); + // NB: `Self::visit_pat` must be used rather than `visit::walk_pat` to avoid resolving guard + // patterns' guard expressions multiple times (#141265). + self.visit_pat(pat); self.resolve_pattern_inner(pat, pat_src, bindings); // This has to happen *after* we determine which pat_idents are variants: self.check_consistent_bindings(pat); diff --git a/tests/ui/pattern/rfc-3637-guard-patterns/only-resolve-top-level-guard-expr-once-ice-141265.rs b/tests/ui/pattern/rfc-3637-guard-patterns/only-resolve-top-level-guard-expr-once-ice-141265.rs new file mode 100644 index 0000000000000..7dc9ef7161d1b --- /dev/null +++ b/tests/ui/pattern/rfc-3637-guard-patterns/only-resolve-top-level-guard-expr-once-ice-141265.rs @@ -0,0 +1,12 @@ +//! Regression test for . +//! Make sure expressions in top-level guard patterns are only resolved once. + +fn main() { + for + else if b 0 {} + //~^ ERROR expected identifier, found keyword `else` + //~| ERROR missing `in` in `for` loop + //~| ERROR cannot find value `b` in this scope + //~| ERROR guard patterns are experimental + //~| ERROR `{integer}` is not an iterator +} diff --git a/tests/ui/pattern/rfc-3637-guard-patterns/only-resolve-top-level-guard-expr-once-ice-141265.stderr b/tests/ui/pattern/rfc-3637-guard-patterns/only-resolve-top-level-guard-expr-once-ice-141265.stderr new file mode 100644 index 0000000000000..dae384137f529 --- /dev/null +++ b/tests/ui/pattern/rfc-3637-guard-patterns/only-resolve-top-level-guard-expr-once-ice-141265.stderr @@ -0,0 +1,48 @@ +error: expected identifier, found keyword `else` + --> $DIR/only-resolve-top-level-guard-expr-once-ice-141265.rs:6:5 + | +LL | else if b 0 {} + | ^^^^ expected identifier, found keyword + +error: missing `in` in `for` loop + --> $DIR/only-resolve-top-level-guard-expr-once-ice-141265.rs:6:14 + | +LL | else if b 0 {} + | ^ + | +help: try adding `in` here + | +LL | else if b in 0 {} + | ++ + +error[E0425]: cannot find value `b` in this scope + --> $DIR/only-resolve-top-level-guard-expr-once-ice-141265.rs:6:13 + | +LL | else if b 0 {} + | ^ not found in this scope + +error[E0658]: guard patterns are experimental + --> $DIR/only-resolve-top-level-guard-expr-once-ice-141265.rs:6:13 + | +LL | else if b 0 {} + | ^ + | + = note: see issue #129967 for more information + = help: add `#![feature(guard_patterns)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date + = help: consider using match arm guards + +error[E0277]: `{integer}` is not an iterator + --> $DIR/only-resolve-top-level-guard-expr-once-ice-141265.rs:6:15 + | +LL | else if b 0 {} + | ^ `{integer}` is not an iterator + | + = help: the trait `Iterator` is not implemented for `{integer}` + = note: if you want to iterate between `start` until a value `end`, use the exclusive range syntax `start..end` or the inclusive range syntax `start..=end` + = note: required for `{integer}` to implement `IntoIterator` + +error: aborting due to 5 previous errors + +Some errors have detailed explanations: E0277, E0425, E0658. +For more information about an error, try `rustc --explain E0277`. From eb530325f08b9151cb1917d01a8cb913ab1dd1ab Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jakub=20Ber=C3=A1nek?= Date: Tue, 20 May 2025 10:39:34 +0200 Subject: [PATCH 2/7] Use Docker cache from the current repository This is needed to make the cache work after moving CI from the `rust-lang-ci` org to `rust-lang`. --- src/ci/docker/run.sh | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/ci/docker/run.sh b/src/ci/docker/run.sh index 36f7df2b06907..4e69fb2f37057 100755 --- a/src/ci/docker/run.sh +++ b/src/ci/docker/run.sh @@ -97,9 +97,8 @@ if [ -f "$docker_dir/$image/Dockerfile" ]; then docker --version REGISTRY=ghcr.io - # Hardcode username to reuse cache between auto and pr jobs - # FIXME: should be changed after move from rust-lang-ci - REGISTRY_USERNAME=rust-lang-ci + # Default to `rust-lang` to allow reusing the cache for local builds + REGISTRY_USERNAME=${GITHUB_REPOSITORY_OWNER:-rust-lang} # Tag used to push the final Docker image, so that it can be pulled by e.g. rustup IMAGE_TAG=${REGISTRY}/${REGISTRY_USERNAME}/rust-ci:${cksum} # Tag used to cache the Docker build From 44a2af306825dcfa9fc28547e6ccea1cb5076c68 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Wed, 21 May 2025 09:17:47 +0000 Subject: [PATCH 3/7] Do not eagerly fold consts in normalize_param_env_or_error if new solver --- compiler/rustc_trait_selection/src/traits/mod.rs | 4 +--- tests/ui/traits/next-solver/no-param-env-const-fold.rs | 10 ++++++++++ 2 files changed, 11 insertions(+), 3 deletions(-) create mode 100644 tests/ui/traits/next-solver/no-param-env-const-fold.rs diff --git a/compiler/rustc_trait_selection/src/traits/mod.rs b/compiler/rustc_trait_selection/src/traits/mod.rs index 31b075db04b96..f73603c00539d 100644 --- a/compiler/rustc_trait_selection/src/traits/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/mod.rs @@ -340,7 +340,7 @@ pub fn normalize_param_env_or_error<'tcx>( let mut predicates: Vec<_> = util::elaborate( tcx, unnormalized_env.caller_bounds().into_iter().map(|predicate| { - if tcx.features().generic_const_exprs() { + if tcx.features().generic_const_exprs() || tcx.next_trait_solver_globally() { return predicate; } @@ -405,8 +405,6 @@ pub fn normalize_param_env_or_error<'tcx>( // compatibility. Eventually when lazy norm is implemented this can just be removed. // We do not normalize types here as there is no backwards compatibility requirement // for us to do so. - // - // FIXME(-Znext-solver): remove this hack since we have deferred projection equality predicate.fold_with(&mut ConstNormalizer(tcx)) }), ) diff --git a/tests/ui/traits/next-solver/no-param-env-const-fold.rs b/tests/ui/traits/next-solver/no-param-env-const-fold.rs new file mode 100644 index 0000000000000..4f47332dd23ae --- /dev/null +++ b/tests/ui/traits/next-solver/no-param-env-const-fold.rs @@ -0,0 +1,10 @@ +//@ check-pass +//@ compile-flags: -Znext-solver + +// Regression test for . + +use std::ops::Deref; + +trait Trait: Deref {} + +fn main() {} From ad59f0b6e6e5c45ea64064758a88e8521259bfcf Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Wed, 21 May 2025 10:02:54 +0000 Subject: [PATCH 4/7] Use DeepRejectCtxt in assemble_inherent_candidates_from_param --- compiler/rustc_hir_typeck/src/lib.rs | 1 + compiler/rustc_hir_typeck/src/method/probe.rs | 23 +++++++-------- ...am-method-from-unnormalized-param-env-2.rs | 29 +++++++++++++++++++ ...aram-method-from-unnormalized-param-env.rs | 17 +++++++++++ 4 files changed, 58 insertions(+), 12 deletions(-) create mode 100644 tests/ui/traits/next-solver/method/param-method-from-unnormalized-param-env-2.rs create mode 100644 tests/ui/traits/next-solver/method/param-method-from-unnormalized-param-env.rs diff --git a/compiler/rustc_hir_typeck/src/lib.rs b/compiler/rustc_hir_typeck/src/lib.rs index 161f5e981d430..a7444b45ab0f2 100644 --- a/compiler/rustc_hir_typeck/src/lib.rs +++ b/compiler/rustc_hir_typeck/src/lib.rs @@ -2,6 +2,7 @@ #![allow(rustc::diagnostic_outside_of_impl)] #![allow(rustc::untranslatable_diagnostic)] #![feature(array_windows)] +#![feature(assert_matches)] #![feature(box_patterns)] #![feature(if_let_guard)] #![feature(iter_intersperse)] diff --git a/compiler/rustc_hir_typeck/src/method/probe.rs b/compiler/rustc_hir_typeck/src/method/probe.rs index 6090c0f9aee22..725240b480ba9 100644 --- a/compiler/rustc_hir_typeck/src/method/probe.rs +++ b/compiler/rustc_hir_typeck/src/method/probe.rs @@ -1,3 +1,4 @@ +use std::assert_matches::debug_assert_matches; use std::cell::{Cell, RefCell}; use std::cmp::max; use std::ops::Deref; @@ -16,7 +17,7 @@ use rustc_infer::traits::ObligationCauseCode; use rustc_middle::middle::stability; use rustc_middle::query::Providers; use rustc_middle::ty::elaborate::supertrait_def_ids; -use rustc_middle::ty::fast_reject::{TreatParams, simplify_type}; +use rustc_middle::ty::fast_reject::{DeepRejectCtxt, TreatParams, simplify_type}; use rustc_middle::ty::{ self, AssocItem, AssocItemContainer, GenericArgs, GenericArgsRef, GenericParamDefKind, ParamEnvAnd, Ty, TyCtxt, TypeVisitableExt, Upcast, @@ -807,8 +808,8 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> { ); } } - ty::Param(p) => { - self.assemble_inherent_candidates_from_param(p); + ty::Param(_) => { + self.assemble_inherent_candidates_from_param(raw_self_ty); } ty::Bool | ty::Char @@ -909,18 +910,16 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> { } #[instrument(level = "debug", skip(self))] - fn assemble_inherent_candidates_from_param(&mut self, param_ty: ty::ParamTy) { + fn assemble_inherent_candidates_from_param(&mut self, param_ty: Ty<'tcx>) { + debug_assert_matches!(param_ty.kind(), ty::Param(_)); + + let tcx = self.tcx; let bounds = self.param_env.caller_bounds().iter().filter_map(|predicate| { let bound_predicate = predicate.kind(); match bound_predicate.skip_binder() { - 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)) - } - _ => None, - } - } + ty::ClauseKind::Trait(trait_predicate) => DeepRejectCtxt::relate_rigid_rigid(tcx) + .types_may_unify(param_ty, trait_predicate.trait_ref.self_ty()) + .then(|| bound_predicate.rebind(trait_predicate.trait_ref)), ty::ClauseKind::RegionOutlives(_) | ty::ClauseKind::TypeOutlives(_) | ty::ClauseKind::Projection(_) diff --git a/tests/ui/traits/next-solver/method/param-method-from-unnormalized-param-env-2.rs b/tests/ui/traits/next-solver/method/param-method-from-unnormalized-param-env-2.rs new file mode 100644 index 0000000000000..ffb99d6d63855 --- /dev/null +++ b/tests/ui/traits/next-solver/method/param-method-from-unnormalized-param-env-2.rs @@ -0,0 +1,29 @@ +//@ check-pass +//@ revisions: current next +//@ ignore-compare-mode-next-solver (explicit revisions) +//@[next] compile-flags: -Znext-solver + +// Regression test for . +// See comment below. + +trait A { + fn hello(&self) {} +} + +trait B { + fn hello(&self) {} +} + +impl A for T {} +impl B for T {} + +fn test(q: F::Item) +where + F: Iterator, + // We want to prefer `A` for `R.hello()` + F::Item: A, +{ + q.hello(); +} + +fn main() {} diff --git a/tests/ui/traits/next-solver/method/param-method-from-unnormalized-param-env.rs b/tests/ui/traits/next-solver/method/param-method-from-unnormalized-param-env.rs new file mode 100644 index 0000000000000..dde4f745879e4 --- /dev/null +++ b/tests/ui/traits/next-solver/method/param-method-from-unnormalized-param-env.rs @@ -0,0 +1,17 @@ +//@ check-pass +//@ compile-flags: -Znext-solver + +// Regression test for . + +fn execute(q: F::Item) -> R +where + F: Iterator, + // Both of the below bounds should be considered for `.into()`, and then be combined + // into a single `R: Into` bound which can be inferred to `?0 = R`. + F::Item: Into, + R: Into, +{ + q.into() +} + +fn main() {} From 196c3b3ef40a84a05d265f4ec599cbe157cc5cb6 Mon Sep 17 00:00:00 2001 From: lcnr Date: Wed, 21 May 2025 10:02:30 +0000 Subject: [PATCH 5/7] eagerly check nested obligations when coercing fndefs --- compiler/rustc_hir_typeck/src/coercion.rs | 20 ++++++++++++++++--- .../src/traits/engine.rs | 14 +++++++++++++ .../coerce-ambig-alias-to-rigid-alias.rs | 0 .../{ => coercion}/coerce-depth.rs | 0 .../fn-def-coerce-nested-obligations.rs | 16 +++++++++++++++ .../non-wf-in-coerce-pointers.rs | 0 .../non-wf-in-coerce-pointers.stderr | 0 .../trait-upcast-lhs-needs-normalization.rs | 0 .../{ => coercion}/upcast-right-substs.rs | 0 .../{ => coercion}/upcast-wrong-substs.rs | 0 .../{ => coercion}/upcast-wrong-substs.stderr | 0 11 files changed, 47 insertions(+), 3 deletions(-) rename tests/ui/traits/next-solver/{ => coercion}/coerce-ambig-alias-to-rigid-alias.rs (100%) rename tests/ui/traits/next-solver/{ => coercion}/coerce-depth.rs (100%) create mode 100644 tests/ui/traits/next-solver/coercion/fn-def-coerce-nested-obligations.rs rename tests/ui/traits/next-solver/{ => coercion}/non-wf-in-coerce-pointers.rs (100%) rename tests/ui/traits/next-solver/{ => coercion}/non-wf-in-coerce-pointers.stderr (100%) rename tests/ui/traits/next-solver/{ => coercion}/trait-upcast-lhs-needs-normalization.rs (100%) rename tests/ui/traits/next-solver/{ => coercion}/upcast-right-substs.rs (100%) rename tests/ui/traits/next-solver/{ => coercion}/upcast-wrong-substs.rs (100%) rename tests/ui/traits/next-solver/{ => coercion}/upcast-wrong-substs.stderr (100%) diff --git a/compiler/rustc_hir_typeck/src/coercion.rs b/compiler/rustc_hir_typeck/src/coercion.rs index d2fc5ae05434a..9c07f97a73400 100644 --- a/compiler/rustc_hir_typeck/src/coercion.rs +++ b/compiler/rustc_hir_typeck/src/coercion.rs @@ -1190,9 +1190,23 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { (ty::FnDef(..), ty::FnDef(..)) => { // Don't reify if the function types have a LUB, i.e., they // are the same function and their parameters have a LUB. - match self - .commit_if_ok(|_| self.at(cause, self.param_env).lub(prev_ty, new_ty)) - { + match self.commit_if_ok(|_| { + // We need to eagerly handle nested obligations due to lazy norm. + if self.next_trait_solver() { + let ocx = ObligationCtxt::new(self); + let value = ocx.lub(cause, self.param_env, prev_ty, new_ty)?; + if ocx.select_where_possible().is_empty() { + Ok(InferOk { + value, + obligations: ocx.into_pending_obligations(), + }) + } else { + Err(TypeError::Mismatch) + } + } else { + self.at(cause, self.param_env).lub(prev_ty, new_ty) + } + }) { // We have a LUB of prev_ty and new_ty, just return it. Ok(ok) => return Ok(self.register_infer_ok_obligations(ok)), Err(_) => { diff --git a/compiler/rustc_trait_selection/src/traits/engine.rs b/compiler/rustc_trait_selection/src/traits/engine.rs index 8d6e6b4a65165..18f28d72f6f8f 100644 --- a/compiler/rustc_trait_selection/src/traits/engine.rs +++ b/compiler/rustc_trait_selection/src/traits/engine.rs @@ -188,6 +188,20 @@ where .map(|infer_ok| self.register_infer_ok_obligations(infer_ok)) } + /// Computes the least-upper-bound, or mutual supertype, of two values. + pub fn lub>( + &self, + cause: &ObligationCause<'tcx>, + param_env: ty::ParamEnv<'tcx>, + expected: T, + actual: T, + ) -> Result> { + self.infcx + .at(cause, param_env) + .lub(expected, actual) + .map(|infer_ok| self.register_infer_ok_obligations(infer_ok)) + } + #[must_use] pub fn select_where_possible(&self) -> Vec { self.engine.borrow_mut().select_where_possible(self.infcx) diff --git a/tests/ui/traits/next-solver/coerce-ambig-alias-to-rigid-alias.rs b/tests/ui/traits/next-solver/coercion/coerce-ambig-alias-to-rigid-alias.rs similarity index 100% rename from tests/ui/traits/next-solver/coerce-ambig-alias-to-rigid-alias.rs rename to tests/ui/traits/next-solver/coercion/coerce-ambig-alias-to-rigid-alias.rs diff --git a/tests/ui/traits/next-solver/coerce-depth.rs b/tests/ui/traits/next-solver/coercion/coerce-depth.rs similarity index 100% rename from tests/ui/traits/next-solver/coerce-depth.rs rename to tests/ui/traits/next-solver/coercion/coerce-depth.rs diff --git a/tests/ui/traits/next-solver/coercion/fn-def-coerce-nested-obligations.rs b/tests/ui/traits/next-solver/coercion/fn-def-coerce-nested-obligations.rs new file mode 100644 index 0000000000000..1b5abcb02f2f8 --- /dev/null +++ b/tests/ui/traits/next-solver/coercion/fn-def-coerce-nested-obligations.rs @@ -0,0 +1,16 @@ +//@ compile-flags: -Znext-solver +//@ check-pass + +// Make sure that we consider nested obligations when checking whether +// we should coerce fn definitions to function pointers. + +fn foo() {} +fn bar() {} +fn main() { + let _ = if true { foo::<{ 0 + 0 }> } else { foo::<1> }; + let _ = if true { + bar:: fn( as IntoIterator>::Item)> + } else { + bar:: + }; +} diff --git a/tests/ui/traits/next-solver/non-wf-in-coerce-pointers.rs b/tests/ui/traits/next-solver/coercion/non-wf-in-coerce-pointers.rs similarity index 100% rename from tests/ui/traits/next-solver/non-wf-in-coerce-pointers.rs rename to tests/ui/traits/next-solver/coercion/non-wf-in-coerce-pointers.rs diff --git a/tests/ui/traits/next-solver/non-wf-in-coerce-pointers.stderr b/tests/ui/traits/next-solver/coercion/non-wf-in-coerce-pointers.stderr similarity index 100% rename from tests/ui/traits/next-solver/non-wf-in-coerce-pointers.stderr rename to tests/ui/traits/next-solver/coercion/non-wf-in-coerce-pointers.stderr diff --git a/tests/ui/traits/next-solver/trait-upcast-lhs-needs-normalization.rs b/tests/ui/traits/next-solver/coercion/trait-upcast-lhs-needs-normalization.rs similarity index 100% rename from tests/ui/traits/next-solver/trait-upcast-lhs-needs-normalization.rs rename to tests/ui/traits/next-solver/coercion/trait-upcast-lhs-needs-normalization.rs diff --git a/tests/ui/traits/next-solver/upcast-right-substs.rs b/tests/ui/traits/next-solver/coercion/upcast-right-substs.rs similarity index 100% rename from tests/ui/traits/next-solver/upcast-right-substs.rs rename to tests/ui/traits/next-solver/coercion/upcast-right-substs.rs diff --git a/tests/ui/traits/next-solver/upcast-wrong-substs.rs b/tests/ui/traits/next-solver/coercion/upcast-wrong-substs.rs similarity index 100% rename from tests/ui/traits/next-solver/upcast-wrong-substs.rs rename to tests/ui/traits/next-solver/coercion/upcast-wrong-substs.rs diff --git a/tests/ui/traits/next-solver/upcast-wrong-substs.stderr b/tests/ui/traits/next-solver/coercion/upcast-wrong-substs.stderr similarity index 100% rename from tests/ui/traits/next-solver/upcast-wrong-substs.stderr rename to tests/ui/traits/next-solver/coercion/upcast-wrong-substs.stderr From dc794f18a425a20563943ea4201b34ebea2aa017 Mon Sep 17 00:00:00 2001 From: Andrew Zhogin Date: Wed, 21 May 2025 15:21:01 +0700 Subject: [PATCH 6/7] When AsyncDrop impl is empty, sync drop generated in elaborator (Fixes #140974) --- .../rustc_mir_transform/src/elaborate_drop.rs | 24 ++++++++++++++++++- .../elaborate-index-out-of-bounds.rs} | 7 ++++-- .../elaborate-index-out-of-bounds.stderr | 11 +++++++++ 3 files changed, 39 insertions(+), 3 deletions(-) rename tests/{crashes/140974.rs => ui/async-await/async-drop/elaborate-index-out-of-bounds.rs} (62%) create mode 100644 tests/ui/async-await/async-drop/elaborate-index-out-of-bounds.stderr diff --git a/compiler/rustc_mir_transform/src/elaborate_drop.rs b/compiler/rustc_mir_transform/src/elaborate_drop.rs index 73a58160a6aac..5d86b1353c07b 100644 --- a/compiler/rustc_mir_transform/src/elaborate_drop.rs +++ b/compiler/rustc_mir_transform/src/elaborate_drop.rs @@ -251,7 +251,29 @@ where span_bug!(span, "invalid `AsyncDrop` impl_source: {:?}", impl_source); } }; - let drop_fn_def_id = tcx.associated_item_def_ids(drop_trait)[0]; + // impl_item_refs may be empty if drop fn is not implemented in 'impl AsyncDrop for ...' + // (#140974). + // Such code will report error, so just generate sync drop here and return + let Some(drop_fn_def_id) = + tcx.associated_item_def_ids(drop_trait).into_iter().nth(0).copied() + else { + tcx.dcx().span_delayed_bug( + self.elaborator.body().span, + "AsyncDrop type without correct `async fn drop(...)`.", + ); + self.elaborator.patch().patch_terminator( + pin_obj_bb, + TerminatorKind::Drop { + place, + target: succ, + unwind: unwind.into_action(), + replace: false, + drop: None, + async_fut: None, + }, + ); + return pin_obj_bb; + }; let drop_fn = Ty::new_fn_def(tcx, drop_fn_def_id, trait_args); let sig = drop_fn.fn_sig(tcx); let sig = tcx.instantiate_bound_regions_with_erased(sig); diff --git a/tests/crashes/140974.rs b/tests/ui/async-await/async-drop/elaborate-index-out-of-bounds.rs similarity index 62% rename from tests/crashes/140974.rs rename to tests/ui/async-await/async-drop/elaborate-index-out-of-bounds.rs index ac1051a64fd31..bd0a95eb1e497 100644 --- a/tests/crashes/140974.rs +++ b/tests/ui/async-await/async-drop/elaborate-index-out-of-bounds.rs @@ -1,5 +1,7 @@ -//@ known-bug: #140974 -//@edition:2021 +//@ edition: 2024 +// Ex-ICE: #140974 +#![crate_type = "lib"] +#![allow(incomplete_features)] #![feature(async_drop)] use core::future::AsyncDrop; @@ -10,5 +12,6 @@ impl Drop for HasIncompleteAsyncDrop { fn drop(&mut self) {} } impl AsyncDrop for HasIncompleteAsyncDrop { + //~^ ERROR: not all trait items implemented, missing: `drop` [E0046] // not implemented yet.. } diff --git a/tests/ui/async-await/async-drop/elaborate-index-out-of-bounds.stderr b/tests/ui/async-await/async-drop/elaborate-index-out-of-bounds.stderr new file mode 100644 index 0000000000000..d8582398c797e --- /dev/null +++ b/tests/ui/async-await/async-drop/elaborate-index-out-of-bounds.stderr @@ -0,0 +1,11 @@ +error[E0046]: not all trait items implemented, missing: `drop` + --> $DIR/elaborate-index-out-of-bounds.rs:14:1 + | +LL | impl AsyncDrop for HasIncompleteAsyncDrop { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ missing `drop` in implementation + | + = help: implement the missing item: `async fn drop(self: Pin<&mut Self>) { todo!() }` + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0046`. From 7c38b6fd28b1972659b662683866c359f198a6f7 Mon Sep 17 00:00:00 2001 From: Andrew Zhogin Date: Tue, 20 May 2025 22:36:03 +0700 Subject: [PATCH 7/7] Async drop fix for 'broken mir in AsyncDropGlue, place has deref as a later projection' (#140975) --- .../rustc_mir_transform/src/elaborate_drop.rs | 21 ++++++++++++------- .../async-drop/deref-later-projection.rs} | 10 ++++++--- 2 files changed, 20 insertions(+), 11 deletions(-) rename tests/{crashes/140975.rs => ui/async-await/async-drop/deref-later-projection.rs} (70%) diff --git a/compiler/rustc_mir_transform/src/elaborate_drop.rs b/compiler/rustc_mir_transform/src/elaborate_drop.rs index 73a58160a6aac..61312eb7d1ae6 100644 --- a/compiler/rustc_mir_transform/src/elaborate_drop.rs +++ b/compiler/rustc_mir_transform/src/elaborate_drop.rs @@ -318,15 +318,20 @@ where bug!(); }; let obj_ptr_ty = Ty::new_mut_ptr(tcx, drop_ty); - let obj_ptr_place = Place::from(self.new_temp(obj_ptr_ty)); let unwrap_ty = adt_def.non_enum_variant().fields[FieldIdx::ZERO].ty(tcx, adt_args); - let addr = Rvalue::RawPtr( - RawPtrKind::Mut, - pin_obj_place.project_deeper( - &[ProjectionElem::Field(FieldIdx::ZERO, unwrap_ty), ProjectionElem::Deref], - tcx, - ), - ); + let obj_ref_place = Place::from(self.new_temp(unwrap_ty)); + call_statements.push(self.assign( + obj_ref_place, + Rvalue::Use(Operand::Copy(tcx.mk_place_field( + pin_obj_place, + FieldIdx::ZERO, + unwrap_ty, + ))), + )); + + let obj_ptr_place = Place::from(self.new_temp(obj_ptr_ty)); + + let addr = Rvalue::RawPtr(RawPtrKind::Mut, tcx.mk_place_deref(obj_ref_place)); call_statements.push(self.assign(obj_ptr_place, addr)); obj_ptr_place }; diff --git a/tests/crashes/140975.rs b/tests/ui/async-await/async-drop/deref-later-projection.rs similarity index 70% rename from tests/crashes/140975.rs rename to tests/ui/async-await/async-drop/deref-later-projection.rs index e11dd40612cef..baf81daf766b6 100644 --- a/tests/crashes/140975.rs +++ b/tests/ui/async-await/async-drop/deref-later-projection.rs @@ -1,7 +1,11 @@ -//@ known-bug: #140975 -//@ compile-flags: --crate-type lib -Zvalidate-mir -//@ edition: 2021 +// Ex-ICE: #140975 +//@ compile-flags: -Zvalidate-mir +//@ build-pass +//@ edition:2021 +#![crate_type = "lib"] #![feature(async_drop)] +#![allow(incomplete_features)] + use std::{future::AsyncDrop, pin::Pin}; struct HasAsyncDrop ;