diff --git a/compiler/rustc_infer/src/infer/mod.rs b/compiler/rustc_infer/src/infer/mod.rs index 6f88b83a473..3ff14a10b90 100644 --- a/compiler/rustc_infer/src/infer/mod.rs +++ b/compiler/rustc_infer/src/infer/mod.rs @@ -891,6 +891,10 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { .region_constraints_added_in_snapshot(&snapshot.undo_snapshot) } + pub fn opaque_types_added_in_snapshot(&self, snapshot: &CombinedSnapshot<'a, 'tcx>) -> bool { + self.inner.borrow().undo_log.opaque_types_in_snapshot(&snapshot.undo_snapshot) + } + pub fn add_given(&self, sub: ty::Region<'tcx>, sup: ty::RegionVid) { self.inner.borrow_mut().unwrap_region_constraints().add_given(sub, sup); } diff --git a/compiler/rustc_infer/src/infer/undo_log.rs b/compiler/rustc_infer/src/infer/undo_log.rs index 1b696f21cbc..74a26ebc39f 100644 --- a/compiler/rustc_infer/src/infer/undo_log.rs +++ b/compiler/rustc_infer/src/infer/undo_log.rs @@ -185,6 +185,10 @@ impl<'tcx> InferCtxtUndoLogs<'tcx> { }) } + pub(crate) fn opaque_types_in_snapshot(&self, s: &Snapshot<'tcx>) -> bool { + self.logs[s.undo_len..].iter().any(|log| matches!(log, UndoLog::OpaqueTypes(..))) + } + pub(crate) fn region_constraints( &self, ) -> impl Iterator> + Clone { diff --git a/compiler/rustc_middle/src/traits/select.rs b/compiler/rustc_middle/src/traits/select.rs index ffa70cddbd5..025059fcbcf 100644 --- a/compiler/rustc_middle/src/traits/select.rs +++ b/compiler/rustc_middle/src/traits/select.rs @@ -174,6 +174,10 @@ pub enum SelectionCandidate<'tcx> { pub enum EvaluationResult { /// Evaluation successful. EvaluatedToOk, + /// Evaluation successful, but need to rerun because opaque types got + /// hidden types assigned without it being known whether the opaque types + /// are within their defining scope + EvaluatedToOkModuloOpaqueTypes, /// Evaluation successful, but there were unevaluated region obligations. EvaluatedToOkModuloRegions, /// Evaluation is known to be ambiguous -- it *might* hold for some @@ -252,9 +256,11 @@ impl EvaluationResult { pub fn may_apply(self) -> bool { match self { - EvaluatedToOk | EvaluatedToOkModuloRegions | EvaluatedToAmbig | EvaluatedToUnknown => { - true - } + EvaluatedToOkModuloOpaqueTypes + | EvaluatedToOk + | EvaluatedToOkModuloRegions + | EvaluatedToAmbig + | EvaluatedToUnknown => true, EvaluatedToErr | EvaluatedToRecur => false, } @@ -264,7 +270,11 @@ impl EvaluationResult { match self { EvaluatedToUnknown | EvaluatedToRecur => true, - EvaluatedToOk | EvaluatedToOkModuloRegions | EvaluatedToAmbig | EvaluatedToErr => false, + EvaluatedToOkModuloOpaqueTypes + | EvaluatedToOk + | EvaluatedToOkModuloRegions + | EvaluatedToAmbig + | EvaluatedToErr => false, } } } diff --git a/compiler/rustc_middle/src/ty/flags.rs b/compiler/rustc_middle/src/ty/flags.rs index 49db121db1b..ea6bb8a7abd 100644 --- a/compiler/rustc_middle/src/ty/flags.rs +++ b/compiler/rustc_middle/src/ty/flags.rs @@ -207,11 +207,6 @@ impl FlagComputation { &ty::FnDef(_, substs) => { self.add_substs(substs); - // HACK(#98608, oli-obk): Function items with opaque types in their signature will - // end up not having the HAS_TY_OPAQUE flag set, causing `evaluate_obligation` to - // optimistically assume the function item matches any signature. See documentation - // on `HAS_FREE_LOCAL_NAMES` for details. - self.add_flags(TypeFlags::HAS_TY_OPAQUE); } &ty::FnPtr(fn_sig) => self.bound_computation(fn_sig, |computation, fn_sig| { 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 12858172ee5..45f7a890e01 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs @@ -777,6 +777,7 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> { Ok( EvaluationResult::EvaluatedToOk | EvaluationResult::EvaluatedToOkModuloRegions + | EvaluationResult::EvaluatedToOkModuloOpaqueTypes | EvaluationResult::EvaluatedToAmbig, ) => {} _ => return false, diff --git a/compiler/rustc_trait_selection/src/traits/select/mod.rs b/compiler/rustc_trait_selection/src/traits/select/mod.rs index 4223cdb5dbb..32856915662 100644 --- a/compiler/rustc_trait_selection/src/traits/select/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/select/mod.rs @@ -394,6 +394,10 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { Err(_) => return Ok(EvaluatedToErr), } + if self.infcx.opaque_types_added_in_snapshot(snapshot) { + return Ok(result.max(EvaluatedToOkModuloOpaqueTypes)); + } + match self.infcx.region_constraints_added_in_snapshot(snapshot) { None => Ok(result), Some(_) => Ok(result.max(EvaluatedToOkModuloRegions)), diff --git a/src/test/ui/type-alias-impl-trait/issue-53398-cyclic-types.rs b/src/test/ui/type-alias-impl-trait/issue-53398-cyclic-types.rs index 4bc0f9d9200..6c838f41003 100644 --- a/src/test/ui/type-alias-impl-trait/issue-53398-cyclic-types.rs +++ b/src/test/ui/type-alias-impl-trait/issue-53398-cyclic-types.rs @@ -3,7 +3,7 @@ type Foo = impl Fn() -> Foo; fn foo() -> Foo { - foo //~ ERROR: overflow evaluating the requirement ` Foo {foo} as FnOnce<()>>::Output == fn() -> Foo {foo}` + foo //~ ERROR: overflow evaluating the requirement `fn() -> Foo {foo}: Sized` } fn main() {} diff --git a/src/test/ui/type-alias-impl-trait/issue-53398-cyclic-types.stderr b/src/test/ui/type-alias-impl-trait/issue-53398-cyclic-types.stderr index f69514b7808..a9c2c18630c 100644 --- a/src/test/ui/type-alias-impl-trait/issue-53398-cyclic-types.stderr +++ b/src/test/ui/type-alias-impl-trait/issue-53398-cyclic-types.stderr @@ -1,8 +1,10 @@ -error[E0275]: overflow evaluating the requirement ` Foo {foo} as FnOnce<()>>::Output == fn() -> Foo {foo}` +error[E0275]: overflow evaluating the requirement `fn() -> Foo {foo}: Sized` --> $DIR/issue-53398-cyclic-types.rs:6:5 | LL | foo | ^^^ + | + = help: consider increasing the recursion limit by adding a `#![recursion_limit = "256"]` attribute to your crate (`issue_53398_cyclic_types`) error: aborting due to previous error