Skip to content

Rollup of 7 pull requests #141345

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 14 commits into from
May 21, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 17 additions & 3 deletions compiler/rustc_hir_typeck/src/coercion.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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(_) => {
Expand Down
1 change: 1 addition & 0 deletions compiler/rustc_hir_typeck/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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)]
Expand Down
23 changes: 11 additions & 12 deletions compiler/rustc_hir_typeck/src/method/probe.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
use std::assert_matches::debug_assert_matches;
use std::cell::{Cell, RefCell};
use std::cmp::max;
use std::ops::Deref;
Expand All @@ -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,
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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(_)
Expand Down
45 changes: 36 additions & 9 deletions compiler/rustc_mir_transform/src/elaborate_drop.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down Expand Up @@ -318,15 +340,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
};
Expand Down
4 changes: 3 additions & 1 deletion compiler/rustc_resolve/src/late.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
14 changes: 14 additions & 0 deletions compiler/rustc_trait_selection/src/traits/engine.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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<T: ToTrace<'tcx>>(
&self,
cause: &ObligationCause<'tcx>,
param_env: ty::ParamEnv<'tcx>,
expected: T,
actual: T,
) -> Result<T, TypeError<'tcx>> {
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<E> {
self.engine.borrow_mut().select_where_possible(self.infcx)
Expand Down
4 changes: 1 addition & 3 deletions compiler/rustc_trait_selection/src/traits/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}

Expand Down Expand Up @@ -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))
}),
)
Expand Down
5 changes: 2 additions & 3 deletions src/ci/docker/run.sh
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
Original file line number Diff line number Diff line change
@@ -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 ;
Expand Down
Original file line number Diff line number Diff line change
@@ -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;

Expand All @@ -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..
}
Original file line number Diff line number Diff line change
@@ -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`.
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
//! Regression test for <https://github.com/rust-lang/rust/issues/141265>.
//! 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
}
Original file line number Diff line number Diff line change
@@ -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 <https://github.com/rust-lang/rust/issues/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`.
Original file line number Diff line number Diff line change
@@ -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<const N: usize>() {}
fn bar<T>() {}
fn main() {
let _ = if true { foo::<{ 0 + 0 }> } else { foo::<1> };
let _ = if true {
bar::<for<'a> fn(<Vec<&'a ()> as IntoIterator>::Item)>
} else {
bar::<fn(i32)>
};
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
//@ check-pass
//@ revisions: current next
//@ ignore-compare-mode-next-solver (explicit revisions)
//@[next] compile-flags: -Znext-solver

// Regression test for <https://github.com/rust-lang/trait-system-refactor-initiative/issues/214>.
// See comment below.

trait A {
fn hello(&self) {}
}

trait B {
fn hello(&self) {}
}

impl<T> A for T {}
impl<T> B for T {}

fn test<F, R>(q: F::Item)
where
F: Iterator<Item = R>,
// We want to prefer `A` for `R.hello()`
F::Item: A,
{
q.hello();
}

fn main() {}
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
//@ check-pass
//@ compile-flags: -Znext-solver

// Regression test for <https://github.com/rust-lang/trait-system-refactor-initiative/issues/214>.

fn execute<K, F, R>(q: F::Item) -> R
where
F: Iterator<Item = R>,
// Both of the below bounds should be considered for `.into()`, and then be combined
// into a single `R: Into<?0>` bound which can be inferred to `?0 = R`.
F::Item: Into<K>,
R: Into<String>,
{
q.into()
}

fn main() {}
10 changes: 10 additions & 0 deletions tests/ui/traits/next-solver/no-param-env-const-fold.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
//@ check-pass
//@ compile-flags: -Znext-solver

// Regression test for <https://github.com/rust-lang/trait-system-refactor-initiative/issues/213>.

use std::ops::Deref;

trait Trait: Deref<Target = [u8; { 1 + 1 }]> {}

fn main() {}
Loading