about summary refs log tree commit diff
diff options
context:
space:
mode:
authorMatthias Krüger <matthias.krueger@famsik.de>2024-01-26 14:43:32 +0100
committerGitHub <noreply@github.com>2024-01-26 14:43:32 +0100
commitb4b483574f8597ab40d4e4be6adb10a3a91174ec (patch)
tree930a676778f8291a4987665266c15bca9624bbd4
parent37b9022ceff4ee6d90ffcba513afe3324a964299 (diff)
parent2aa746913bda5c52b3efeefb756e13c72618f793 (diff)
downloadrust-b4b483574f8597ab40d4e4be6adb10a3a91174ec.tar.gz
rust-b4b483574f8597ab40d4e4be6adb10a3a91174ec.zip
Rollup merge of #120360 - compiler-errors:afit-sized-lol, r=lcnr
Don't fire `OPAQUE_HIDDEN_INFERRED_BOUND` on sized return of AFIT

Conceptually, we should probably not fire `OPAQUE_HIDDEN_INFERRED_BOUND` for methods like:

```
trait Foo { async fn bar() -> Self; }
```

Even though we technically cannot prove that `Self: Sized`, which is one of the item bounds of the `Output` type in the `-> impl Future<Output = Sized>` from the async desugaring.

This is somewhat justifiable along the same lines as how we allow regular methods to return `-> Self` even though `Self` isn't sized.

Fixes #113538

(side-note: some days i wonder if we should just remove the `OPAQUE_HIDDEN_INFERRED_BOUND` lint... it does make me sad that we have non-well-formed types in signatures, though.)
-rw-r--r--compiler/rustc_lint/src/opaque_hidden_inferred_bound.rs13
-rw-r--r--tests/ui/async-await/in-trait/returning-possibly-unsized-self.rs18
2 files changed, 30 insertions, 1 deletions
diff --git a/compiler/rustc_lint/src/opaque_hidden_inferred_bound.rs b/compiler/rustc_lint/src/opaque_hidden_inferred_bound.rs
index f64509fe8bc..bed5d3c80c0 100644
--- a/compiler/rustc_lint/src/opaque_hidden_inferred_bound.rs
+++ b/compiler/rustc_lint/src/opaque_hidden_inferred_bound.rs
@@ -4,7 +4,7 @@ use rustc_macros::{LintDiagnostic, Subdiagnostic};
 use rustc_middle::ty::{
     self, fold::BottomUpFolder, print::TraitPredPrintModifiersAndPath, Ty, TypeFoldable,
 };
-use rustc_span::Span;
+use rustc_span::{symbol::kw, Span};
 use rustc_trait_selection::traits;
 use rustc_trait_selection::traits::query::evaluate_obligation::InferCtxtExt;
 
@@ -96,6 +96,17 @@ impl<'tcx> LateLintPass<'tcx> for OpaqueHiddenInferredBound {
                 continue;
             }
 
+            // HACK: `async fn() -> Self` in traits is "ok"...
+            // This is not really that great, but it's similar to why the `-> Self`
+            // return type is well-formed in traits even when `Self` isn't sized.
+            if let ty::Param(param_ty) = *proj_term.kind()
+                && param_ty.name == kw::SelfUpper
+                && matches!(opaque.origin, hir::OpaqueTyOrigin::AsyncFn(_))
+                && opaque.in_trait
+            {
+                continue;
+            }
+
             let proj_ty =
                 Ty::new_projection(cx.tcx, proj.projection_ty.def_id, proj.projection_ty.args);
             // For every instance of the projection type in the bounds,
diff --git a/tests/ui/async-await/in-trait/returning-possibly-unsized-self.rs b/tests/ui/async-await/in-trait/returning-possibly-unsized-self.rs
new file mode 100644
index 00000000000..72f02679d77
--- /dev/null
+++ b/tests/ui/async-await/in-trait/returning-possibly-unsized-self.rs
@@ -0,0 +1,18 @@
+// check-pass
+// edition:2021
+
+#![deny(opaque_hidden_inferred_bound)]
+
+trait Repository /* : ?Sized */ {
+    async fn new() -> Self;
+}
+
+struct MyRepository {}
+
+impl Repository for MyRepository {
+    async fn new() -> Self {
+        todo!()
+    }
+}
+
+fn main() {}