1
Fork 0

Rollup merge of #139022 - lcnr:incr-obligation-depth, r=oli-obk

increment depth of nested obligations

properly fixes the root cause of #109268. While we didn't get hangs here before, I ended up encountering its root cause again with #138785.

r? types
This commit is contained in:
Matthias Krüger 2025-04-01 20:25:22 +02:00 committed by GitHub
commit 000d018110
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
15 changed files with 70 additions and 72 deletions

View file

@ -106,10 +106,6 @@ fn match_candidate<'tcx>(
more_nested(selcx, &mut nested); more_nested(selcx, &mut nested);
for nested in &mut nested {
nested.set_depth_from_parent(obligation.recursion_depth);
}
Ok(nested) Ok(nested)
} }
@ -378,10 +374,6 @@ fn evaluate_host_effect_from_selection_candiate<'tcx>(
}), }),
); );
for nested in &mut nested {
nested.set_depth_from_parent(obligation.recursion_depth);
}
Ok(nested) Ok(nested)
} }
_ => Err(EvaluationFailure::NoSolution), _ => Err(EvaluationFailure::NoSolution),

View file

@ -225,9 +225,15 @@ struct FulfillProcessor<'a, 'tcx> {
selcx: SelectionContext<'a, 'tcx>, selcx: SelectionContext<'a, 'tcx>,
} }
fn mk_pending<'tcx>(os: PredicateObligations<'tcx>) -> PendingPredicateObligations<'tcx> { fn mk_pending<'tcx>(
parent: &PredicateObligation<'tcx>,
os: PredicateObligations<'tcx>,
) -> PendingPredicateObligations<'tcx> {
os.into_iter() os.into_iter()
.map(|o| PendingPredicateObligation { obligation: o, stalled_on: vec![] }) .map(|mut o| {
o.set_depth_from_parent(parent.recursion_depth);
PendingPredicateObligation { obligation: o, stalled_on: vec![] }
})
.collect() .collect()
} }
@ -341,7 +347,7 @@ impl<'a, 'tcx> ObligationProcessor for FulfillProcessor<'a, 'tcx> {
); );
if predicate != obligation.predicate { if predicate != obligation.predicate {
obligations.push(obligation.with(infcx.tcx, predicate)); obligations.push(obligation.with(infcx.tcx, predicate));
return ProcessResult::Changed(mk_pending(obligations)); return ProcessResult::Changed(mk_pending(obligation, obligations));
} }
} }
let binder = obligation.predicate.kind(); let binder = obligation.predicate.kind();
@ -385,7 +391,7 @@ impl<'a, 'tcx> ObligationProcessor for FulfillProcessor<'a, 'tcx> {
let mut obligations = PredicateObligations::with_capacity(1); let mut obligations = PredicateObligations::with_capacity(1);
obligations.push(obligation.with(infcx.tcx, pred)); obligations.push(obligation.with(infcx.tcx, pred));
ProcessResult::Changed(mk_pending(obligations)) ProcessResult::Changed(mk_pending(obligation, obligations))
} }
ty::PredicateKind::Ambiguous => ProcessResult::Unchanged, ty::PredicateKind::Ambiguous => ProcessResult::Unchanged,
ty::PredicateKind::NormalizesTo(..) => { ty::PredicateKind::NormalizesTo(..) => {
@ -410,6 +416,7 @@ impl<'a, 'tcx> ObligationProcessor for FulfillProcessor<'a, 'tcx> {
let host_obligation = obligation.with(infcx.tcx, data); let host_obligation = obligation.with(infcx.tcx, data);
self.process_host_obligation( self.process_host_obligation(
obligation,
host_obligation, host_obligation,
&mut pending_obligation.stalled_on, &mut pending_obligation.stalled_on,
) )
@ -486,7 +493,10 @@ impl<'a, 'tcx> ObligationProcessor for FulfillProcessor<'a, 'tcx> {
// `<lhs_ty as Add<rhs_ty>>::Output` when this is an `Expr` representing // `<lhs_ty as Add<rhs_ty>>::Output` when this is an `Expr` representing
// `lhs + rhs`. // `lhs + rhs`.
ty::ConstKind::Expr(_) => { ty::ConstKind::Expr(_) => {
return ProcessResult::Changed(mk_pending(PredicateObligations::new())); return ProcessResult::Changed(mk_pending(
obligation,
PredicateObligations::new(),
));
} }
ty::ConstKind::Placeholder(_) => { ty::ConstKind::Placeholder(_) => {
bug!("placeholder const {:?} in old solver", ct) bug!("placeholder const {:?} in old solver", ct)
@ -503,7 +513,10 @@ impl<'a, 'tcx> ObligationProcessor for FulfillProcessor<'a, 'tcx> {
ct_ty, ct_ty,
ty, ty,
) { ) {
Ok(inf_ok) => ProcessResult::Changed(mk_pending(inf_ok.into_obligations())), Ok(inf_ok) => ProcessResult::Changed(mk_pending(
obligation,
inf_ok.into_obligations(),
)),
Err(_) => ProcessResult::Error(FulfillmentErrorCode::Select( Err(_) => ProcessResult::Error(FulfillmentErrorCode::Select(
SelectionError::ConstArgHasWrongType { ct, ct_ty, expected_ty: ty }, SelectionError::ConstArgHasWrongType { ct, ct_ty, expected_ty: ty },
)), )),
@ -537,7 +550,7 @@ impl<'a, 'tcx> ObligationProcessor for FulfillProcessor<'a, 'tcx> {
vec![TyOrConstInferVar::maybe_from_generic_arg(arg).unwrap()]; vec![TyOrConstInferVar::maybe_from_generic_arg(arg).unwrap()];
ProcessResult::Unchanged ProcessResult::Unchanged
} }
Some(os) => ProcessResult::Changed(mk_pending(os)), Some(os) => ProcessResult::Changed(mk_pending(obligation, os)),
} }
} }
@ -553,11 +566,8 @@ impl<'a, 'tcx> ObligationProcessor for FulfillProcessor<'a, 'tcx> {
vec![TyOrConstInferVar::Ty(a), TyOrConstInferVar::Ty(b)]; vec![TyOrConstInferVar::Ty(a), TyOrConstInferVar::Ty(b)];
ProcessResult::Unchanged ProcessResult::Unchanged
} }
Ok(Ok(mut ok)) => { Ok(Ok(ok)) => {
for subobligation in &mut ok.obligations { ProcessResult::Changed(mk_pending(obligation, ok.obligations))
subobligation.set_depth_from_parent(obligation.recursion_depth);
}
ProcessResult::Changed(mk_pending(ok.obligations))
} }
Ok(Err(err)) => { Ok(Err(err)) => {
let expected_found = if subtype.a_is_expected { let expected_found = if subtype.a_is_expected {
@ -582,7 +592,9 @@ impl<'a, 'tcx> ObligationProcessor for FulfillProcessor<'a, 'tcx> {
vec![TyOrConstInferVar::Ty(a), TyOrConstInferVar::Ty(b)]; vec![TyOrConstInferVar::Ty(a), TyOrConstInferVar::Ty(b)];
ProcessResult::Unchanged ProcessResult::Unchanged
} }
Ok(Ok(ok)) => ProcessResult::Changed(mk_pending(ok.obligations)), Ok(Ok(ok)) => {
ProcessResult::Changed(mk_pending(obligation, ok.obligations))
}
Ok(Err(err)) => { Ok(Err(err)) => {
let expected_found = ExpectedFound::new(coerce.b, coerce.a); let expected_found = ExpectedFound::new(coerce.b, coerce.a);
ProcessResult::Error(FulfillmentErrorCode::Subtype(expected_found, err)) ProcessResult::Error(FulfillmentErrorCode::Subtype(expected_found, err))
@ -645,6 +657,7 @@ impl<'a, 'tcx> ObligationProcessor for FulfillProcessor<'a, 'tcx> {
) )
{ {
return ProcessResult::Changed(mk_pending( return ProcessResult::Changed(mk_pending(
obligation,
new_obligations.into_obligations(), new_obligations.into_obligations(),
)); ));
} }
@ -659,6 +672,7 @@ impl<'a, 'tcx> ObligationProcessor for FulfillProcessor<'a, 'tcx> {
.eq(DefineOpaqueTypes::Yes, c1, c2) .eq(DefineOpaqueTypes::Yes, c1, c2)
{ {
return ProcessResult::Changed(mk_pending( return ProcessResult::Changed(mk_pending(
obligation,
new_obligations.into_obligations(), new_obligations.into_obligations(),
)); ));
} }
@ -704,9 +718,10 @@ impl<'a, 'tcx> ObligationProcessor for FulfillProcessor<'a, 'tcx> {
c1, c1,
c2, c2,
) { ) {
Ok(inf_ok) => { Ok(inf_ok) => ProcessResult::Changed(mk_pending(
ProcessResult::Changed(mk_pending(inf_ok.into_obligations())) obligation,
} inf_ok.into_obligations(),
)),
Err(err) => { Err(err) => {
ProcessResult::Error(FulfillmentErrorCode::ConstEquate( ProcessResult::Error(FulfillmentErrorCode::ConstEquate(
ExpectedFound::new(c1, c2), ExpectedFound::new(c1, c2),
@ -790,7 +805,7 @@ impl<'a, 'tcx> FulfillProcessor<'a, 'tcx> {
match self.selcx.poly_select(&trait_obligation) { match self.selcx.poly_select(&trait_obligation) {
Ok(Some(impl_source)) => { Ok(Some(impl_source)) => {
debug!("selecting trait at depth {} yielded Ok(Some)", obligation.recursion_depth); debug!("selecting trait at depth {} yielded Ok(Some)", obligation.recursion_depth);
ProcessResult::Changed(mk_pending(impl_source.nested_obligations())) ProcessResult::Changed(mk_pending(obligation, impl_source.nested_obligations()))
} }
Ok(None) => { Ok(None) => {
debug!("selecting trait at depth {} yielded Ok(None)", obligation.recursion_depth); debug!("selecting trait at depth {} yielded Ok(None)", obligation.recursion_depth);
@ -854,7 +869,7 @@ impl<'a, 'tcx> FulfillProcessor<'a, 'tcx> {
} }
match project::poly_project_and_unify_term(&mut self.selcx, &project_obligation) { match project::poly_project_and_unify_term(&mut self.selcx, &project_obligation) {
ProjectAndUnifyResult::Holds(os) => ProcessResult::Changed(mk_pending(os)), ProjectAndUnifyResult::Holds(os) => ProcessResult::Changed(mk_pending(obligation, os)),
ProjectAndUnifyResult::FailedNormalization => { ProjectAndUnifyResult::FailedNormalization => {
stalled_on.clear(); stalled_on.clear();
stalled_on.extend(args_infer_vars( stalled_on.extend(args_infer_vars(
@ -868,7 +883,7 @@ impl<'a, 'tcx> FulfillProcessor<'a, 'tcx> {
let mut obligations = PredicateObligations::with_capacity(1); let mut obligations = PredicateObligations::with_capacity(1);
obligations.push(project_obligation.with(tcx, project_obligation.predicate)); obligations.push(project_obligation.with(tcx, project_obligation.predicate));
ProcessResult::Changed(mk_pending(obligations)) ProcessResult::Changed(mk_pending(obligation, obligations))
} }
ProjectAndUnifyResult::MismatchedProjectionTypes(e) => { ProjectAndUnifyResult::MismatchedProjectionTypes(e) => {
ProcessResult::Error(FulfillmentErrorCode::Project(e)) ProcessResult::Error(FulfillmentErrorCode::Project(e))
@ -878,11 +893,12 @@ impl<'a, 'tcx> FulfillProcessor<'a, 'tcx> {
fn process_host_obligation( fn process_host_obligation(
&mut self, &mut self,
obligation: &PredicateObligation<'tcx>,
host_obligation: HostEffectObligation<'tcx>, host_obligation: HostEffectObligation<'tcx>,
stalled_on: &mut Vec<TyOrConstInferVar>, stalled_on: &mut Vec<TyOrConstInferVar>,
) -> ProcessResult<PendingPredicateObligation<'tcx>, FulfillmentErrorCode<'tcx>> { ) -> ProcessResult<PendingPredicateObligation<'tcx>, FulfillmentErrorCode<'tcx>> {
match effects::evaluate_host_effect_obligation(&mut self.selcx, &host_obligation) { match effects::evaluate_host_effect_obligation(&mut self.selcx, &host_obligation) {
Ok(nested) => ProcessResult::Changed(mk_pending(nested)), Ok(nested) => ProcessResult::Changed(mk_pending(obligation, nested)),
Err(effects::EvaluationFailure::Ambiguous) => { Err(effects::EvaluationFailure::Ambiguous) => {
stalled_on.clear(); stalled_on.clear();
stalled_on.extend(args_infer_vars( stalled_on.extend(args_infer_vars(

View file

@ -39,7 +39,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
obligation: &PolyTraitObligation<'tcx>, obligation: &PolyTraitObligation<'tcx>,
candidate: SelectionCandidate<'tcx>, candidate: SelectionCandidate<'tcx>,
) -> Result<Selection<'tcx>, SelectionError<'tcx>> { ) -> Result<Selection<'tcx>, SelectionError<'tcx>> {
let mut impl_src = match candidate { Ok(match candidate {
SizedCandidate { has_nested } => { SizedCandidate { has_nested } => {
let data = self.confirm_builtin_candidate(obligation, has_nested); let data = self.confirm_builtin_candidate(obligation, has_nested);
ImplSource::Builtin(BuiltinImplSource::Misc, data) ImplSource::Builtin(BuiltinImplSource::Misc, data)
@ -139,15 +139,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
BikeshedGuaranteedNoDropCandidate => { BikeshedGuaranteedNoDropCandidate => {
self.confirm_bikeshed_guaranteed_no_drop_candidate(obligation) self.confirm_bikeshed_guaranteed_no_drop_candidate(obligation)
} }
}; })
// The obligations returned by confirmation are recursively evaluated
// so we need to make sure they have the correct depth.
for subobligation in impl_src.borrow_nested_obligations_mut() {
subobligation.set_depth_from_parent(obligation.recursion_depth);
}
Ok(impl_src)
} }
fn confirm_projection_candidate( fn confirm_projection_candidate(

View file

@ -1,8 +1,8 @@
error[E0275]: overflow assigning `Box<_>` to `_` error[E0275]: overflow assigning `Box<_>` to `_`
--> $DIR/infinite-autoderef.rs:16:13 --> $DIR/infinite-autoderef.rs:16:22
| |
LL | x = Box::new(x); LL | x = Box::new(x);
| ^^^^^^^^^^^ | ^
error: aborting due to 1 previous error error: aborting due to 1 previous error

View file

@ -4,6 +4,6 @@ fn main() {
let g; let g;
g = f; g = f;
f = Box::new(g);
//~^ ERROR overflow assigning `Box<_>` to `_` //~^ ERROR overflow assigning `Box<_>` to `_`
f = Box::new(g);
} }

View file

@ -1,8 +1,8 @@
error[E0275]: overflow assigning `Box<_>` to `_` error[E0275]: overflow assigning `Box<_>` to `_`
--> $DIR/occurs-check-2.rs:7:9 --> $DIR/occurs-check-2.rs:6:9
| |
LL | f = Box::new(g); LL | g = f;
| ^^^^^^^^^^^ | ^
error: aborting due to 1 previous error error: aborting due to 1 previous error

View file

@ -1,8 +1,8 @@
error[E0275]: overflow assigning `Clam<_>` to `_` error[E0275]: overflow assigning `Clam<_>` to `_`
--> $DIR/occurs-check-3.rs:6:9 --> $DIR/occurs-check-3.rs:6:17
| |
LL | c = Clam::A(c); LL | c = Clam::A(c);
| ^^^^^^^^^^ | ^
error: aborting due to 1 previous error error: aborting due to 1 previous error

View file

@ -1,8 +1,8 @@
error[E0275]: overflow assigning `Box<_>` to `_` error[E0275]: overflow assigning `Box<_>` to `_`
--> $DIR/occurs-check.rs:3:9 --> $DIR/occurs-check.rs:3:18
| |
LL | f = Box::new(f); LL | f = Box::new(f);
| ^^^^^^^^^^^ | ^
error: aborting due to 1 previous error error: aborting due to 1 previous error

View file

@ -2,7 +2,7 @@ error[E0275]: overflow assigning `_` to `Option<_>`
--> $DIR/mutual-recursion-issue-75860.rs:9:33 --> $DIR/mutual-recursion-issue-75860.rs:9:33
| |
LL | let left = |o_a: Option<_>| o_a.unwrap(); LL | let left = |o_a: Option<_>| o_a.unwrap();
| ^^^ | ^^^^^^^^^^^^
error: aborting due to 1 previous error error: aborting due to 1 previous error

View file

@ -1,9 +1,10 @@
#![feature(type_alias_impl_trait)] #![feature(type_alias_impl_trait)]
//@ known-bug: #109268
type Foo = impl Fn() -> Foo; type Foo = impl Fn() -> Foo;
#[define_opaque(Foo)]
fn crash(x: Foo) -> Foo { fn crash(x: Foo) -> Foo {
//~^ ERROR overflow evaluating the requirement `<Foo as FnOnce<()>>::Output == Foo`
x x
} }

View file

@ -1,10 +1,9 @@
error: unconstrained opaque type error[E0275]: overflow evaluating the requirement `<Foo as FnOnce<()>>::Output == Foo`
--> $DIR/type-alias-impl-trait-with-cycle-error-1.rs:4:12 --> $DIR/type-alias-impl-trait-with-cycle-error-1.rs:6:21
| |
LL | type Foo = impl Fn() -> Foo; LL | fn crash(x: Foo) -> Foo {
| ^^^^^^^^^^^^^^^^ | ^^^
|
= note: `Foo` must be used in combination with a concrete type within the same crate
error: aborting due to 1 previous error error: aborting due to 1 previous error
For more information about this error, try `rustc --explain E0275`.

View file

@ -1,13 +1,13 @@
#![feature(type_alias_impl_trait)] #![feature(type_alias_impl_trait)]
//@ known-bug: #109268
pub trait Bar<T> { pub trait Bar<T> {
type Item; type Item;
} }
type Foo = impl Bar<Foo, Item = Foo>; type Foo = impl Bar<Foo, Item = Foo>;
#[define_opaque(Foo)]
fn crash(x: Foo) -> Foo { fn crash(x: Foo) -> Foo {
//~^ ERROR overflow evaluating the requirement `<Foo as Bar<Foo>>::Item == Foo`
x x
} }

View file

@ -1,10 +1,9 @@
error: unconstrained opaque type error[E0275]: overflow evaluating the requirement `<Foo as Bar<Foo>>::Item == Foo`
--> $DIR/type-alias-impl-trait-with-cycle-error-2.rs:8:12 --> $DIR/type-alias-impl-trait-with-cycle-error-2.rs:9:21
| |
LL | type Foo = impl Bar<Foo, Item = Foo>; LL | fn crash(x: Foo) -> Foo {
| ^^^^^^^^^^^^^^^^^^^^^^^^^ | ^^^
|
= note: `Foo` must be used in combination with a concrete type within the same crate
error: aborting due to 1 previous error error: aborting due to 1 previous error
For more information about this error, try `rustc --explain E0275`.

View file

@ -1,9 +1,9 @@
#![feature(type_alias_impl_trait)] #![feature(type_alias_impl_trait)]
//@ known-bug: #109268
type Foo<'a> = impl Fn() -> Foo<'a>; type Foo<'a> = impl Fn() -> Foo<'a>;
#[define_opaque(Foo)]
fn crash<'a>(_: &'a (), x: Foo<'a>) -> Foo<'a> { fn crash<'a>(_: &'a (), x: Foo<'a>) -> Foo<'a> {
//~^ ERROR overflow evaluating the requirement `<Foo<'_> as FnOnce<()>>::Output == Foo<'a>`
x x
} }

View file

@ -1,10 +1,9 @@
error: unconstrained opaque type error[E0275]: overflow evaluating the requirement `<Foo<'_> as FnOnce<()>>::Output == Foo<'a>`
--> $DIR/type-alias-impl-trait-with-cycle-error-3.rs:4:16 --> $DIR/type-alias-impl-trait-with-cycle-error-3.rs:5:40
| |
LL | type Foo<'a> = impl Fn() -> Foo<'a>; LL | fn crash<'a>(_: &'a (), x: Foo<'a>) -> Foo<'a> {
| ^^^^^^^^^^^^^^^^^^^^ | ^^^^^^^
|
= note: `Foo` must be used in combination with a concrete type within the same crate
error: aborting due to 1 previous error error: aborting due to 1 previous error
For more information about this error, try `rustc --explain E0275`.