Skip to content
Open
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
5 changes: 3 additions & 2 deletions compiler/rustc_next_trait_solver/src/solve/assembly/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -199,6 +199,7 @@ where
/// but prevents incorrect normalization while hiding any trait errors.
fn consider_error_guaranteed_candidate(
ecx: &mut EvalCtxt<'_, D>,
goal: Goal<I, Self>,
guar: I::ErrorGuaranteed,
) -> Result<Candidate<I>, NoSolution>;

Expand Down Expand Up @@ -522,8 +523,8 @@ where
// Instead of adding the logic here, it's a better idea to add it in
// `EvalCtxt::disqualify_auto_trait_candidate_due_to_possible_impl` in
// `solve::trait_goals` instead.
let result = if let Err(guar) = goal.predicate.error_reported() {
G::consider_error_guaranteed_candidate(self, guar)
let result = if let ty::Error(guar) = goal.predicate.self_ty().kind() {
G::consider_error_guaranteed_candidate(self, goal, guar)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we should move this out of assemble_builtin_impl_candidate to avoid ambiguity between e.g. blanket impls and the builtin impl candidate 🤔

} else if cx.trait_is_auto(trait_def_id) {
G::consider_auto_trait_candidate(self, goal)
} else if cx.trait_is_alias(trait_def_id) {
Expand Down
1 change: 1 addition & 0 deletions compiler/rustc_next_trait_solver/src/solve/effect_goals.rs
Original file line number Diff line number Diff line change
Expand Up @@ -182,6 +182,7 @@ where

fn consider_error_guaranteed_candidate(
ecx: &mut EvalCtxt<'_, D>,
_goal: Goal<I, Self>,
_guar: I::ErrorGuaranteed,
) -> Result<Candidate<I>, NoSolution> {
ecx.probe_builtin_trait_candidate(BuiltinImplSource::Misc)
Expand Down
12 changes: 10 additions & 2 deletions compiler/rustc_next_trait_solver/src/solve/normalizes_to/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -391,9 +391,17 @@ where
/// Fail to normalize if the predicate contains an error, alternatively, we could normalize to `ty::Error`
/// and succeed. Can experiment with this to figure out what results in better error messages.
fn consider_error_guaranteed_candidate(
_ecx: &mut EvalCtxt<'_, D>,
_guar: I::ErrorGuaranteed,
ecx: &mut EvalCtxt<'_, D>,
goal: Goal<I, Self>,
guar: I::ErrorGuaranteed,
) -> Result<Candidate<I>, NoSolution> {
let cx = ecx.cx();
let error_term = match goal.predicate.alias.kind(cx) {
ty::AliasTermKind::ProjectionTy => Ty::new_error(cx, guar).into(),
ty::AliasTermKind::ProjectionConst => Const::new_error(cx, guar).into(),
kind => panic!("expected projection, found {kind:?}"),
};
ecx.instantiate_normalizes_to_term(goal, error_term);
Err(NoSolution)
}

Expand Down
1 change: 1 addition & 0 deletions compiler/rustc_next_trait_solver/src/solve/trait_goals.rs
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,7 @@ where

fn consider_error_guaranteed_candidate(
ecx: &mut EvalCtxt<'_, D>,
_goal: Goal<I, Self>,
_guar: I::ErrorGuaranteed,
) -> Result<Candidate<I>, NoSolution> {
ecx.probe_builtin_trait_candidate(BuiltinImplSource::Misc)
Expand Down
9 changes: 9 additions & 0 deletions compiler/rustc_type_ir/src/ty_kind/closure.rs
Original file line number Diff line number Diff line change
Expand Up @@ -459,6 +459,15 @@ impl<I: Interner> CoroutineClosureSignature<I> {
coroutine_captures_by_ref_ty: I::Ty,
env_region: I::Region,
) -> I::Ty {
// If either of the tupled capture types are constrained to error
// (e.g. during typeck when the infcx is tainted), then just return
// the error type directly.
if let ty::Error(_) = tupled_inputs_ty.kind() {
return tupled_inputs_ty;
} else if let ty::Error(_) = coroutine_captures_by_ref_ty.kind() {
return coroutine_captures_by_ref_ty;
}
Comment on lines +462 to +469
Copy link
Member Author

@compiler-errors compiler-errors Sep 15, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is necessary b/c we now try to project some <{async closure} as FnOnce>::Output predicate whose substs have been constrained to {type error} (namely, the tupled upvars and coroutine captures by ref tys), whereas we used to bail.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I guess that's fine 🤔 👍


match kind {
ty::ClosureKind::Fn | ty::ClosureKind::FnMut => {
let ty::FnPtr(sig_tys, _) = coroutine_captures_by_ref_ty.kind() else {
Expand Down
2 changes: 1 addition & 1 deletion tests/ui/traits/const-traits/call-const-closure.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ impl Bar for () {
const FOO: () = {
(const || ().foo())();
//~^ ERROR the trait bound `(): [const] Bar` is not satisfied
// FIXME(const_trait_impl): The constness environment for const closures is wrong.
//~| ERROR [const] Fn()` is not satisfied
};

fn main() {}
8 changes: 7 additions & 1 deletion tests/ui/traits/const-traits/call-const-closure.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,12 @@ error[E0277]: the trait bound `(): [const] Bar` is not satisfied
LL | (const || ().foo())();
| ^^^

error: aborting due to 1 previous error
error[E0277]: the trait bound `{closure@$DIR/call-const-closure.rs:17:6: 17:14}: [const] Fn()` is not satisfied
--> $DIR/call-const-closure.rs:17:5
|
LL | (const || ().foo())();
| ^^^^^^^^^^^^^^^^^^^^^

error: aborting due to 2 previous errors

For more information about this error, try `rustc --explain E0277`.
Loading