diff --git a/compiler/rustc_middle/src/traits/mod.rs b/compiler/rustc_middle/src/traits/mod.rs index 2f0b07d4c71b4..5b0b40cbfd9bc 100644 --- a/compiler/rustc_middle/src/traits/mod.rs +++ b/compiler/rustc_middle/src/traits/mod.rs @@ -701,9 +701,9 @@ impl<'tcx, N> ImplSource<'tcx, N> { } pub fn borrow_nested_obligations(&self) -> &[N] { - match &self { - ImplSource::UserDefined(i) => &i.nested[..], - ImplSource::Param(n, _) => &n, + match self { + ImplSource::UserDefined(i) => &i.nested, + ImplSource::Param(n, _) => n, ImplSource::Builtin(i) => &i.nested, ImplSource::AutoImpl(d) => &d.nested, ImplSource::Closure(c) => &c.nested, @@ -717,6 +717,23 @@ impl<'tcx, N> ImplSource<'tcx, N> { } } + pub fn borrow_nested_obligations_mut(&mut self) -> &mut [N] { + match self { + ImplSource::UserDefined(i) => &mut i.nested, + ImplSource::Param(n, _) => n, + ImplSource::Builtin(i) => &mut i.nested, + ImplSource::AutoImpl(d) => &mut d.nested, + ImplSource::Closure(c) => &mut c.nested, + ImplSource::Generator(c) => &mut c.nested, + ImplSource::Future(c) => &mut c.nested, + ImplSource::Object(d) => &mut d.nested, + ImplSource::FnPointer(d) => &mut d.nested, + ImplSource::TraitAlias(d) => &mut d.nested, + ImplSource::TraitUpcasting(d) => &mut d.nested, + ImplSource::ConstDestruct(i) => &mut i.nested, + } + } + pub fn map(self, f: F) -> ImplSource<'tcx, M> where F: FnMut(N) -> M, diff --git a/compiler/rustc_trait_selection/src/traits/select/confirmation.rs b/compiler/rustc_trait_selection/src/traits/select/confirmation.rs index de023501f9e85..0d9f55d4c2edf 100644 --- a/compiler/rustc_trait_selection/src/traits/select/confirmation.rs +++ b/compiler/rustc_trait_selection/src/traits/select/confirmation.rs @@ -132,6 +132,12 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { } }; + // 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); + } + if !obligation.predicate.is_const_if_const() { // normalize nested predicates according to parent predicate's constness. impl_src = impl_src.map(|mut o| { diff --git a/tests/ui/traits/cycle-cache-err-60010.stderr b/tests/ui/traits/cycle-cache-err-60010.stderr index 2ff16b4af38d4..aee41c43aefeb 100644 --- a/tests/ui/traits/cycle-cache-err-60010.stderr +++ b/tests/ui/traits/cycle-cache-err-60010.stderr @@ -1,9 +1,25 @@ -error[E0275]: overflow evaluating the requirement `RootDatabase: RefUnwindSafe` +error[E0275]: overflow evaluating the requirement `SalsaStorage: RefUnwindSafe` --> $DIR/cycle-cache-err-60010.rs:27:13 | LL | _parse: >::Data, | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | +note: required because it appears within the type `PhantomData` + --> $SRC_DIR/core/src/marker.rs:LL:COL +note: required because it appears within the type `Unique` + --> $SRC_DIR/core/src/ptr/unique.rs:LL:COL +note: required because it appears within the type `Box` + --> $SRC_DIR/alloc/src/boxed.rs:LL:COL +note: required because it appears within the type `Runtime` + --> $DIR/cycle-cache-err-60010.rs:23:8 + | +LL | struct Runtime { + | ^^^^^^^ +note: required because it appears within the type `RootDatabase` + --> $DIR/cycle-cache-err-60010.rs:20:8 + | +LL | struct RootDatabase { + | ^^^^^^^^^^^^ note: required for `RootDatabase` to implement `SourceDatabase` --> $DIR/cycle-cache-err-60010.rs:44:9 | diff --git a/tests/ui/traits/solver-cycles/cycle-via-builtin-auto-trait-impl.rs b/tests/ui/traits/solver-cycles/cycle-via-builtin-auto-trait-impl.rs new file mode 100644 index 0000000000000..d37943b929a1f --- /dev/null +++ b/tests/ui/traits/solver-cycles/cycle-via-builtin-auto-trait-impl.rs @@ -0,0 +1,34 @@ +//~ ERROR overflow +// A regression test for #111729 checking that we correctly +// track recursion depth for obligations returned by confirmation. +use std::panic::RefUnwindSafe; + +trait Database { + type Storage; +} +trait Query { + type Data; +} +struct ParseQuery; +struct RootDatabase { + _runtime: Runtime, +} + +impl Database for T { + type Storage = SalsaStorage; +} +impl Database for RootDatabase { + type Storage = SalsaStorage; +} + +struct Runtime { + _storage: Box, +} +struct SalsaStorage { + _parse: >::Data, +} + +impl Query for ParseQuery { + type Data = RootDatabase; +} +fn main() {} diff --git a/tests/ui/traits/solver-cycles/cycle-via-builtin-auto-trait-impl.stderr b/tests/ui/traits/solver-cycles/cycle-via-builtin-auto-trait-impl.stderr new file mode 100644 index 0000000000000..8f9ce3ef1e99c --- /dev/null +++ b/tests/ui/traits/solver-cycles/cycle-via-builtin-auto-trait-impl.stderr @@ -0,0 +1,24 @@ +error[E0275]: overflow evaluating the requirement `Runtime: RefUnwindSafe` + | + = help: consider increasing the recursion limit by adding a `#![recursion_limit = "256"]` attribute to your crate (`cycle_via_builtin_auto_trait_impl`) +note: required because it appears within the type `RootDatabase` + --> $DIR/cycle-via-builtin-auto-trait-impl.rs:13:8 + | +LL | struct RootDatabase { + | ^^^^^^^^^^^^ +note: required for `RootDatabase` to implement `Database` + --> $DIR/cycle-via-builtin-auto-trait-impl.rs:17:24 + | +LL | impl Database for T { + | ------------- ^^^^^^^^ ^ + | | + | unsatisfied trait bound introduced here +note: required because it appears within the type `Runtime` + --> $DIR/cycle-via-builtin-auto-trait-impl.rs:24:8 + | +LL | struct Runtime { + | ^^^^^^^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0275`.