diff --git a/compiler/rustc_lint/src/unused.rs b/compiler/rustc_lint/src/unused.rs index 1159d11e5c0c8..28cc63198af55 100644 --- a/compiler/rustc_lint/src/unused.rs +++ b/compiler/rustc_lint/src/unused.rs @@ -103,8 +103,10 @@ impl<'tcx> LateLintPass<'tcx> for UnusedResults { && let ty = cx.typeck_results().expr_ty(&await_expr) && let ty::Alias(ty::Opaque, ty::AliasTy { def_id: future_def_id, .. }) = ty.kind() && cx.tcx.ty_is_opaque_future(ty) - // FIXME: This also includes non-async fns that return `impl Future`. && let async_fn_def_id = cx.tcx.parent(*future_def_id) + && matches!(cx.tcx.def_kind(async_fn_def_id), DefKind::Fn | DefKind::AssocFn) + // Check that this `impl Future` actually comes from an `async fn` + && cx.tcx.asyncness(async_fn_def_id).is_async() && check_must_use_def( cx, async_fn_def_id, diff --git a/compiler/rustc_middle/src/traits/mod.rs b/compiler/rustc_middle/src/traits/mod.rs index 6a8ae525069c0..91f07389f0aca 100644 --- a/compiler/rustc_middle/src/traits/mod.rs +++ b/compiler/rustc_middle/src/traits/mod.rs @@ -697,9 +697,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, @@ -713,6 +713,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 5e60bc01bb644..88121f86536c3 100644 --- a/compiler/rustc_trait_selection/src/traits/select/confirmation.rs +++ b/compiler/rustc_trait_selection/src/traits/select/confirmation.rs @@ -131,6 +131,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/lint/unused/auxiliary/must-use-foreign.rs b/tests/ui/lint/unused/auxiliary/must-use-foreign.rs new file mode 100644 index 0000000000000..f773f09c3821b --- /dev/null +++ b/tests/ui/lint/unused/auxiliary/must-use-foreign.rs @@ -0,0 +1,12 @@ +// edition:2021 + +use std::future::Future; + +pub struct Manager; + +impl Manager { + #[must_use] + pub async fn new() -> (Self, impl Future) { + (Manager, async {}) + } +} diff --git a/tests/ui/lint/unused/must-use-foreign.rs b/tests/ui/lint/unused/must-use-foreign.rs new file mode 100644 index 0000000000000..21a1105856218 --- /dev/null +++ b/tests/ui/lint/unused/must-use-foreign.rs @@ -0,0 +1,15 @@ +// edition:2021 +// aux-build:must-use-foreign.rs +// check-pass + +extern crate must_use_foreign; + +use must_use_foreign::Manager; + +async fn async_main() { + Manager::new().await.1.await; +} + +fn main() { + let _ = async_main(); +} diff --git a/tests/ui/lint/unused/unused-async.rs b/tests/ui/lint/unused/unused-async.rs index 4be93aa155ad9..6355f47f037c7 100644 --- a/tests/ui/lint/unused/unused-async.rs +++ b/tests/ui/lint/unused/unused-async.rs @@ -33,7 +33,7 @@ async fn test() { foo().await; //~ ERROR unused output of future returned by `foo` that must be used bar(); //~ ERROR unused return value of `bar` that must be used //~^ ERROR unused implementer of `Future` that must be used - bar().await; //~ ERROR unused output of future returned by `bar` that must be used + bar().await; // ok, it's not an async fn baz(); //~ ERROR unused implementer of `Future` that must be used baz().await; // ok } diff --git a/tests/ui/lint/unused/unused-async.stderr b/tests/ui/lint/unused/unused-async.stderr index 1c3702ba265c0..e93a40658f3c2 100644 --- a/tests/ui/lint/unused/unused-async.stderr +++ b/tests/ui/lint/unused/unused-async.stderr @@ -52,17 +52,6 @@ help: use `let _ = ...` to ignore the resulting value LL | let _ = bar(); | +++++++ -error: unused output of future returned by `bar` that must be used - --> $DIR/unused-async.rs:36:5 - | -LL | bar().await; - | ^^^^^^^^^^^ - | -help: use `let _ = ...` to ignore the resulting value - | -LL | let _ = bar().await; - | +++++++ - error: unused implementer of `Future` that must be used --> $DIR/unused-async.rs:37:5 | @@ -71,5 +60,5 @@ LL | baz(); | = note: futures do nothing unless you `.await` or poll them -error: aborting due to 7 previous errors +error: aborting due to 6 previous errors diff --git a/tests/ui/traits/cycle-cache-err-60010.stderr b/tests/ui/traits/cycle-cache-err-60010.stderr index 2ff16b4af38d4..eeee997608e6e 100644 --- a/tests/ui/traits/cycle-cache-err-60010.stderr +++ b/tests/ui/traits/cycle-cache-err-60010.stderr @@ -1,9 +1,22 @@ -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` + = note: required because it appears within the type `Unique` + = note: required because it appears within the type `Box` +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`.