diff --git a/compiler/rustc_resolve/src/late/lifetimes.rs b/compiler/rustc_resolve/src/late/lifetimes.rs index 4c1d537d55fa3..a5dbbffeaa86b 100644 --- a/compiler/rustc_resolve/src/late/lifetimes.rs +++ b/compiler/rustc_resolve/src/late/lifetimes.rs @@ -2024,7 +2024,7 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> { // ensure that we issue lints in a repeatable order def_ids.sort_by_cached_key(|&def_id| self.tcx.def_path_hash(def_id)); - for def_id in def_ids { + 'lifetimes: for def_id in def_ids { debug!("check_uses_for_lifetimes_defined_by_scope: def_id = {:?}", def_id); let lifetimeuseset = self.lifetime_uses.remove(&def_id); @@ -2067,6 +2067,27 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> { { continue; } + + // opaque types generated when desugaring an async function can have a single + // use lifetime even if it is explicitly denied (Issue #77175) + if let hir::Node::Item(hir::Item { + kind: hir::ItemKind::OpaqueTy(ref opaque), + .. + }) = self.tcx.hir().get(parent_hir_id) + { + if opaque.origin != hir::OpaqueTyOrigin::AsyncFn { + continue 'lifetimes; + } + // We want to do this only if the liftime identifier is already defined + // in the async function that generated this. Otherwise it could be + // an opaque type defined by the developer and we still want this + // lint to fail compilation + for p in opaque.generics.params { + if defined_by.contains_key(&p.name) { + continue 'lifetimes; + } + } + } } } diff --git a/src/test/ui/lifetimes/issue-77175.rs b/src/test/ui/lifetimes/issue-77175.rs new file mode 100644 index 0000000000000..2282752b6c1fe --- /dev/null +++ b/src/test/ui/lifetimes/issue-77175.rs @@ -0,0 +1,19 @@ +#[deny(single_use_lifetimes)] +// edition:2018 +// check-pass + +// Prior to the fix, the compiler complained that the 'a lifetime was only used +// once. This was obviously wrong since the lifetime is used twice: For the s3 +// parameter and the return type. The issue was caused by the compiler +// desugaring the async function into a generator that uses only a single +// lifetime, which then the validator complained about becauase of the +// single_use_lifetimes constraints. +async fn bar<'a>(s1: String, s2: &'_ str, s3: &'a str) -> &'a str { + s3 +} + +fn foo<'a>(s1: String, s2: &'_ str, s3: &'a str) -> &'a str { + s3 +} + +fn main() {}