Rollup merge of #71338 - estebank:recursive-impl-trait, r=nikomatsakis

Expand "recursive opaque type" diagnostic

Fix #70968, partially address #66523.
This commit is contained in:
Manish Goregaokar 2020-06-18 15:20:33 -07:00 committed by GitHub
commit 45d033b21c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
13 changed files with 366 additions and 115 deletions

View File

@ -2726,6 +2726,18 @@ impl Node<'_> {
}
}
pub fn body_id(&self) -> Option<BodyId> {
match self {
Node::TraitItem(TraitItem {
kind: TraitItemKind::Fn(_, TraitFn::Provided(body_id)),
..
})
| Node::ImplItem(ImplItem { kind: ImplItemKind::Fn(_, body_id), .. })
| Node::Item(Item { kind: ItemKind::Fn(.., body_id), .. }) => Some(*body_id),
_ => None,
}
}
pub fn generics(&self) -> Option<&Generics<'_>> {
match self {
Node::TraitItem(TraitItem { generics, .. })

View File

@ -1992,8 +1992,8 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
/// Collect all the returned expressions within the input expression.
/// Used to point at the return spans when we want to suggest some change to them.
#[derive(Default)]
struct ReturnsVisitor<'v> {
returns: Vec<&'v hir::Expr<'v>>,
pub struct ReturnsVisitor<'v> {
pub returns: Vec<&'v hir::Expr<'v>>,
in_block_tail: bool,
}

View File

@ -138,6 +138,7 @@ use rustc_target::spec::abi::Abi;
use rustc_trait_selection::infer::InferCtxtExt as _;
use rustc_trait_selection::opaque_types::{InferCtxtExt as _, OpaqueTypeDecl};
use rustc_trait_selection::traits::error_reporting::recursive_type_with_infinite_size_error;
use rustc_trait_selection::traits::error_reporting::suggestions::ReturnsVisitor;
use rustc_trait_selection::traits::error_reporting::InferCtxtExt as _;
use rustc_trait_selection::traits::query::evaluate_obligation::InferCtxtExt as _;
use rustc_trait_selection::traits::{
@ -1710,6 +1711,173 @@ fn check_opaque_for_inheriting_lifetimes(tcx: TyCtxt<'tcx>, def_id: LocalDefId,
}
}
/// Given a `DefId` for an opaque type in return position, find its parent item's return
/// expressions.
fn get_owner_return_paths(
tcx: TyCtxt<'tcx>,
def_id: LocalDefId,
) -> Option<(hir::HirId, ReturnsVisitor<'tcx>)> {
let hir_id = tcx.hir().as_local_hir_id(def_id);
let id = tcx.hir().get_parent_item(hir_id);
tcx.hir()
.find(id)
.map(|n| (id, n))
.and_then(|(hir_id, node)| node.body_id().map(|b| (hir_id, b)))
.map(|(hir_id, body_id)| {
let body = tcx.hir().body(body_id);
let mut visitor = ReturnsVisitor::default();
visitor.visit_body(body);
(hir_id, visitor)
})
}
/// Emit an error for recursive opaque types.
///
/// If this is a return `impl Trait`, find the item's return expressions and point at them. For
/// direct recursion this is enough, but for indirect recursion also point at the last intermediary
/// `impl Trait`.
///
/// If all the return expressions evaluate to `!`, then we explain that the error will go away
/// after changing it. This can happen when a user uses `panic!()` or similar as a placeholder.
fn opaque_type_cycle_error(tcx: TyCtxt<'tcx>, def_id: LocalDefId, span: Span) {
let mut err = struct_span_err!(tcx.sess, span, E0720, "cannot resolve opaque type");
let mut label = false;
if let Some((hir_id, visitor)) = get_owner_return_paths(tcx, def_id) {
let tables = tcx.typeck_tables_of(tcx.hir().local_def_id(hir_id));
if visitor
.returns
.iter()
.filter_map(|expr| tables.node_type_opt(expr.hir_id))
.all(|ty| matches!(ty.kind, ty::Never))
{
let spans = visitor
.returns
.iter()
.filter(|expr| tables.node_type_opt(expr.hir_id).is_some())
.map(|expr| expr.span)
.collect::<Vec<Span>>();
let span_len = spans.len();
if span_len == 1 {
err.span_label(spans[0], "this returned value is of `!` type");
} else {
let mut multispan: MultiSpan = spans.clone().into();
for span in spans {
multispan
.push_span_label(span, "this returned value is of `!` type".to_string());
}
err.span_note(multispan, "these returned values have a concrete \"never\" type");
}
err.help("this error will resolve once the item's body returns a concrete type");
} else {
let mut seen = FxHashSet::default();
seen.insert(span);
err.span_label(span, "recursive opaque type");
label = true;
for (sp, ty) in visitor
.returns
.iter()
.filter_map(|e| tables.node_type_opt(e.hir_id).map(|t| (e.span, t)))
.filter(|(_, ty)| !matches!(ty.kind, ty::Never))
{
struct VisitTypes(Vec<DefId>);
impl<'tcx> ty::fold::TypeVisitor<'tcx> for VisitTypes {
fn visit_ty(&mut self, t: Ty<'tcx>) -> bool {
match t.kind {
ty::Opaque(def, _) => {
self.0.push(def);
false
}
_ => t.super_visit_with(self),
}
}
}
let mut visitor = VisitTypes(vec![]);
ty.visit_with(&mut visitor);
for def_id in visitor.0 {
let ty_span = tcx.def_span(def_id);
if !seen.contains(&ty_span) {
err.span_label(ty_span, &format!("returning this opaque type `{}`", ty));
seen.insert(ty_span);
}
err.span_label(sp, &format!("returning here with type `{}`", ty));
}
}
}
}
if !label {
err.span_label(span, "cannot resolve opaque type");
}
err.emit();
}
/// Emit an error for recursive opaque types in a `let` binding.
fn binding_opaque_type_cycle_error(
tcx: TyCtxt<'tcx>,
def_id: LocalDefId,
span: Span,
partially_expanded_type: Ty<'tcx>,
) {
let mut err = struct_span_err!(tcx.sess, span, E0720, "cannot resolve opaque type");
err.span_label(span, "cannot resolve opaque type");
// Find the the owner that declared this `impl Trait` type.
let hir_id = tcx.hir().as_local_hir_id(def_id);
let mut prev_hir_id = hir_id;
let mut hir_id = tcx.hir().get_parent_node(hir_id);
while let Some(node) = tcx.hir().find(hir_id) {
match node {
hir::Node::Local(hir::Local {
pat,
init: None,
ty: Some(ty),
source: hir::LocalSource::Normal,
..
}) => {
err.span_label(pat.span, "this binding might not have a concrete type");
err.span_suggestion_verbose(
ty.span.shrink_to_hi(),
"set the binding to a value for a concrete type to be resolved",
" = /* value */".to_string(),
Applicability::HasPlaceholders,
);
}
hir::Node::Local(hir::Local {
init: Some(expr),
source: hir::LocalSource::Normal,
..
}) => {
let hir_id = tcx.hir().as_local_hir_id(def_id);
let tables =
tcx.typeck_tables_of(tcx.hir().local_def_id(tcx.hir().get_parent_item(hir_id)));
if let Some(ty) = tables.node_type_opt(expr.hir_id) {
err.span_label(
expr.span,
&format!(
"this is of type `{}`, which doesn't constrain \
`{}` enough to arrive to a concrete type",
ty, partially_expanded_type
),
);
}
}
_ => {}
}
if prev_hir_id == hir_id {
break;
}
prev_hir_id = hir_id;
hir_id = tcx.hir().get_parent_node(hir_id);
}
err.emit();
}
fn async_opaque_type_cycle_error(tcx: TyCtxt<'tcx>, span: Span) {
struct_span_err!(tcx.sess, span, E0733, "recursion in an `async fn` requires boxing")
.span_label(span, "recursive `async fn`")
.note("a recursive `async fn` must be rewritten to return a boxed `dyn Future`")
.emit();
}
/// Checks that an opaque type does not contain cycles.
fn check_opaque_for_cycles<'tcx>(
tcx: TyCtxt<'tcx>,
@ -1720,21 +1888,12 @@ fn check_opaque_for_cycles<'tcx>(
) {
if let Err(partially_expanded_type) = tcx.try_expand_impl_trait_type(def_id.to_def_id(), substs)
{
if let hir::OpaqueTyOrigin::AsyncFn = origin {
struct_span_err!(tcx.sess, span, E0733, "recursion in an `async fn` requires boxing",)
.span_label(span, "recursive `async fn`")
.note("a recursive `async fn` must be rewritten to return a boxed `dyn Future`")
.emit();
} else {
let mut err =
struct_span_err!(tcx.sess, span, E0720, "opaque type expands to a recursive type",);
err.span_label(span, "expands to a recursive type");
if let ty::Opaque(..) = partially_expanded_type.kind {
err.note("type resolves to itself");
} else {
err.note(&format!("expanded type is `{}`", partially_expanded_type));
match origin {
hir::OpaqueTyOrigin::AsyncFn => async_opaque_type_cycle_error(tcx, span),
hir::OpaqueTyOrigin::Binding => {
binding_opaque_type_cycle_error(tcx, def_id, span, partially_expanded_type)
}
err.emit();
_ => opaque_type_cycle_error(tcx, def_id, span),
}
}
}

View File

@ -0,0 +1,9 @@
#![allow(incomplete_features)]
#![feature(impl_trait_in_bindings)]
fn foo() {
let _ : impl Copy;
//~^ ERROR cannot resolve opaque type
}
fn main() {}

View File

@ -0,0 +1,16 @@
error[E0720]: cannot resolve opaque type
--> $DIR/binding-without-value.rs:5:13
|
LL | let _ : impl Copy;
| - ^^^^^^^^^ cannot resolve opaque type
| |
| this binding might not have a concrete type
|
help: set the binding to a value for a concrete type to be resolved
|
LL | let _ : impl Copy = /* value */;
| ^^^^^^^^^^^^^
error: aborting due to previous error
For more information about this error, try `rustc --explain E0720`.

View File

@ -5,13 +5,13 @@
trait Quux {}
fn foo() -> impl Quux { //~ opaque type expands to a recursive type
fn foo() -> impl Quux { //~ ERROR cannot resolve opaque type
struct Foo<T>(T);
impl<T> Quux for Foo<T> {}
Foo(bar())
}
fn bar() -> impl Quux { //~ opaque type expands to a recursive type
fn bar() -> impl Quux { //~ ERROR cannot resolve opaque type
struct Bar<T>(T);
impl<T> Quux for Bar<T> {}
Bar(foo())

View File

@ -1,18 +1,26 @@
error[E0720]: opaque type expands to a recursive type
error[E0720]: cannot resolve opaque type
--> $DIR/infinite-impl-trait-issue-38064.rs:8:13
|
LL | fn foo() -> impl Quux {
| ^^^^^^^^^ expands to a recursive type
|
= note: expanded type is `foo::Foo<bar::Bar<impl Quux>>`
| ^^^^^^^^^ recursive opaque type
...
LL | Foo(bar())
| ---------- returning here with type `foo::Foo<impl Quux>`
...
LL | fn bar() -> impl Quux {
| --------- returning this opaque type `foo::Foo<impl Quux>`
error[E0720]: opaque type expands to a recursive type
error[E0720]: cannot resolve opaque type
--> $DIR/infinite-impl-trait-issue-38064.rs:14:13
|
LL | fn foo() -> impl Quux {
| --------- returning this opaque type `bar::Bar<impl Quux>`
...
LL | fn bar() -> impl Quux {
| ^^^^^^^^^ expands to a recursive type
|
= note: expanded type is `bar::Bar<foo::Foo<impl Quux>>`
| ^^^^^^^^^ recursive opaque type
...
LL | Bar(foo())
| ---------- returning here with type `bar::Bar<impl Quux>`
error: aborting due to 2 previous errors

View File

@ -1,10 +1,11 @@
error[E0720]: opaque type expands to a recursive type
error[E0720]: cannot resolve opaque type
--> $DIR/recursive-impl-trait-type-direct.rs:5:14
|
LL | fn test() -> impl Sized {
| ^^^^^^^^^^ expands to a recursive type
|
= note: type resolves to itself
| ^^^^^^^^^^ recursive opaque type
LL |
LL | test()
| ------ returning here with type `impl Sized`
error: aborting due to previous error

View File

@ -1,114 +1,147 @@
error[E0720]: opaque type expands to a recursive type
error[E0720]: cannot resolve opaque type
--> $DIR/recursive-impl-trait-type-indirect.rs:7:22
|
LL | fn option(i: i32) -> impl Sized {
| ^^^^^^^^^^ expands to a recursive type
|
= note: expanded type is `std::option::Option<(impl Sized, i32)>`
| ^^^^^^^^^^ recursive opaque type
LL |
LL | if i < 0 { None } else { Some((option(i - 1), i)) }
| ---- ------------------------ returning here with type `std::option::Option<(impl Sized, i32)>`
| |
| returning here with type `std::option::Option<(impl Sized, i32)>`
error[E0720]: opaque type expands to a recursive type
error[E0720]: cannot resolve opaque type
--> $DIR/recursive-impl-trait-type-indirect.rs:12:15
|
LL | fn tuple() -> impl Sized {
| ^^^^^^^^^^ expands to a recursive type
|
= note: expanded type is `(impl Sized,)`
| ^^^^^^^^^^ recursive opaque type
LL |
LL | (tuple(),)
| ---------- returning here with type `(impl Sized,)`
error[E0720]: opaque type expands to a recursive type
error[E0720]: cannot resolve opaque type
--> $DIR/recursive-impl-trait-type-indirect.rs:17:15
|
LL | fn array() -> impl Sized {
| ^^^^^^^^^^ expands to a recursive type
|
= note: expanded type is `[impl Sized; 1]`
| ^^^^^^^^^^ recursive opaque type
LL |
LL | [array()]
| --------- returning here with type `[impl Sized; 1]`
error[E0720]: opaque type expands to a recursive type
error[E0720]: cannot resolve opaque type
--> $DIR/recursive-impl-trait-type-indirect.rs:22:13
|
LL | fn ptr() -> impl Sized {
| ^^^^^^^^^^ expands to a recursive type
|
= note: expanded type is `*const impl Sized`
| ^^^^^^^^^^ recursive opaque type
LL |
LL | &ptr() as *const _
| ------------------ returning here with type `*const impl Sized`
error[E0720]: opaque type expands to a recursive type
error[E0720]: cannot resolve opaque type
--> $DIR/recursive-impl-trait-type-indirect.rs:27:16
|
LL | fn fn_ptr() -> impl Sized {
| ^^^^^^^^^^ expands to a recursive type
|
= note: expanded type is `fn() -> impl Sized`
| ^^^^^^^^^^ recursive opaque type
LL |
LL | fn_ptr as fn() -> _
| ------------------- returning here with type `fn() -> impl Sized`
error[E0720]: opaque type expands to a recursive type
error[E0720]: cannot resolve opaque type
--> $DIR/recursive-impl-trait-type-indirect.rs:32:25
|
LL | fn closure_capture() -> impl Sized {
| ^^^^^^^^^^ expands to a recursive type
|
= note: expanded type is `[closure@$DIR/recursive-impl-trait-type-indirect.rs:35:5: 37:6 x:impl Sized]`
LL | fn closure_capture() -> impl Sized {
| ^^^^^^^^^^ recursive opaque type
...
LL | / move || {
LL | | x;
LL | | }
| |_____- returning here with type `[closure@$DIR/recursive-impl-trait-type-indirect.rs:35:5: 37:6 x:impl Sized]`
error[E0720]: opaque type expands to a recursive type
error[E0720]: cannot resolve opaque type
--> $DIR/recursive-impl-trait-type-indirect.rs:40:29
|
LL | fn closure_ref_capture() -> impl Sized {
| ^^^^^^^^^^ expands to a recursive type
|
= note: expanded type is `[closure@$DIR/recursive-impl-trait-type-indirect.rs:43:5: 45:6 x:impl Sized]`
LL | fn closure_ref_capture() -> impl Sized {
| ^^^^^^^^^^ recursive opaque type
...
LL | / move || {
LL | | &x;
LL | | }
| |_____- returning here with type `[closure@$DIR/recursive-impl-trait-type-indirect.rs:43:5: 45:6 x:impl Sized]`
error[E0720]: opaque type expands to a recursive type
error[E0720]: cannot resolve opaque type
--> $DIR/recursive-impl-trait-type-indirect.rs:48:21
|
LL | fn closure_sig() -> impl Sized {
| ^^^^^^^^^^ expands to a recursive type
|
= note: expanded type is `[closure@$DIR/recursive-impl-trait-type-indirect.rs:50:5: 50:21]`
| ^^^^^^^^^^ recursive opaque type
LL |
LL | || closure_sig()
| ---------------- returning here with type `[closure@$DIR/recursive-impl-trait-type-indirect.rs:50:5: 50:21]`
error[E0720]: opaque type expands to a recursive type
error[E0720]: cannot resolve opaque type
--> $DIR/recursive-impl-trait-type-indirect.rs:53:23
|
LL | fn generator_sig() -> impl Sized {
| ^^^^^^^^^^ expands to a recursive type
|
= note: expanded type is `[closure@$DIR/recursive-impl-trait-type-indirect.rs:55:5: 55:23]`
| ^^^^^^^^^^ recursive opaque type
LL |
LL | || generator_sig()
| ------------------ returning here with type `[closure@$DIR/recursive-impl-trait-type-indirect.rs:55:5: 55:23]`
error[E0720]: opaque type expands to a recursive type
error[E0720]: cannot resolve opaque type
--> $DIR/recursive-impl-trait-type-indirect.rs:58:27
|
LL | fn generator_capture() -> impl Sized {
| ^^^^^^^^^^ expands to a recursive type
|
= note: expanded type is `[generator@$DIR/recursive-impl-trait-type-indirect.rs:61:5: 64:6 x:impl Sized {()}]`
LL | fn generator_capture() -> impl Sized {
| ^^^^^^^^^^ recursive opaque type
...
LL | / move || {
LL | | yield;
LL | | x;
LL | | }
| |_____- returning here with type `[generator@$DIR/recursive-impl-trait-type-indirect.rs:61:5: 64:6 x:impl Sized {()}]`
error[E0720]: opaque type expands to a recursive type
error[E0720]: cannot resolve opaque type
--> $DIR/recursive-impl-trait-type-indirect.rs:67:35
|
LL | fn substs_change<T: 'static>() -> impl Sized {
| ^^^^^^^^^^ expands to a recursive type
|
= note: expanded type is `(impl Sized,)`
| ^^^^^^^^^^ recursive opaque type
LL |
LL | (substs_change::<&T>(),)
| ------------------------ returning here with type `(impl Sized,)`
error[E0720]: opaque type expands to a recursive type
error[E0720]: cannot resolve opaque type
--> $DIR/recursive-impl-trait-type-indirect.rs:72:24
|
LL | fn generator_hold() -> impl Sized {
| ^^^^^^^^^^ expands to a recursive type
|
= note: expanded type is `[generator@$DIR/recursive-impl-trait-type-indirect.rs:74:5: 78:6 {impl Sized, ()}]`
LL | fn generator_hold() -> impl Sized {
| ^^^^^^^^^^ recursive opaque type
LL |
LL | / move || {
LL | | let x = generator_hold();
LL | | yield;
LL | | x;
LL | | }
| |_____- returning here with type `[generator@$DIR/recursive-impl-trait-type-indirect.rs:74:5: 78:6 {impl Sized, ()}]`
error[E0720]: opaque type expands to a recursive type
error[E0720]: cannot resolve opaque type
--> $DIR/recursive-impl-trait-type-indirect.rs:86:26
|
LL | fn mutual_recursion() -> impl Sync {
| ^^^^^^^^^ expands to a recursive type
|
= note: type resolves to itself
| ^^^^^^^^^ recursive opaque type
LL |
LL | mutual_recursion_b()
| -------------------- returning here with type `impl Sized`
...
LL | fn mutual_recursion_b() -> impl Sized {
| ---------- returning this opaque type `impl Sized`
error[E0720]: opaque type expands to a recursive type
error[E0720]: cannot resolve opaque type
--> $DIR/recursive-impl-trait-type-indirect.rs:91:28
|
LL | fn mutual_recursion() -> impl Sync {
| --------- returning this opaque type `impl std::marker::Sync`
...
LL | fn mutual_recursion_b() -> impl Sized {
| ^^^^^^^^^^ expands to a recursive type
|
= note: type resolves to itself
| ^^^^^^^^^^ recursive opaque type
LL |
LL | mutual_recursion()
| ------------------ returning here with type `impl std::marker::Sync`
error: aborting due to 14 previous errors

View File

@ -4,21 +4,21 @@
fn id<T>(t: T) -> impl Sized { t }
fn recursive_id() -> impl Sized { //~ ERROR opaque type expands to a recursive type
fn recursive_id() -> impl Sized { //~ ERROR cannot resolve opaque type
id(recursive_id2())
}
fn recursive_id2() -> impl Sized { //~ ERROR opaque type expands to a recursive type
fn recursive_id2() -> impl Sized { //~ ERROR cannot resolve opaque type
id(recursive_id())
}
fn wrap<T>(t: T) -> impl Sized { (t,) }
fn recursive_wrap() -> impl Sized { //~ ERROR opaque type expands to a recursive type
fn recursive_wrap() -> impl Sized { //~ ERROR cannot resolve opaque type
wrap(recursive_wrap2())
}
fn recursive_wrap2() -> impl Sized { //~ ERROR opaque type expands to a recursive type
fn recursive_wrap2() -> impl Sized { //~ ERROR cannot resolve opaque type
wrap(recursive_wrap())
}

View File

@ -1,34 +1,46 @@
error[E0720]: opaque type expands to a recursive type
error[E0720]: cannot resolve opaque type
--> $DIR/recursive-impl-trait-type-through-non-recursive.rs:7:22
|
LL | fn id<T>(t: T) -> impl Sized { t }
| ---------- returning this opaque type `impl Sized`
LL |
LL | fn recursive_id() -> impl Sized {
| ^^^^^^^^^^ expands to a recursive type
|
= note: type resolves to itself
| ^^^^^^^^^^ recursive opaque type
LL | id(recursive_id2())
| ------------------- returning here with type `impl Sized`
error[E0720]: opaque type expands to a recursive type
error[E0720]: cannot resolve opaque type
--> $DIR/recursive-impl-trait-type-through-non-recursive.rs:11:23
|
LL | fn id<T>(t: T) -> impl Sized { t }
| ---------- returning this opaque type `impl Sized`
...
LL | fn recursive_id2() -> impl Sized {
| ^^^^^^^^^^ expands to a recursive type
|
= note: type resolves to itself
| ^^^^^^^^^^ recursive opaque type
LL | id(recursive_id())
| ------------------ returning here with type `impl Sized`
error[E0720]: opaque type expands to a recursive type
error[E0720]: cannot resolve opaque type
--> $DIR/recursive-impl-trait-type-through-non-recursive.rs:17:24
|
LL | fn wrap<T>(t: T) -> impl Sized { (t,) }
| ---------- returning this opaque type `impl Sized`
LL |
LL | fn recursive_wrap() -> impl Sized {
| ^^^^^^^^^^ expands to a recursive type
|
= note: expanded type is `((impl Sized,),)`
| ^^^^^^^^^^ recursive opaque type
LL | wrap(recursive_wrap2())
| ----------------------- returning here with type `impl Sized`
error[E0720]: opaque type expands to a recursive type
error[E0720]: cannot resolve opaque type
--> $DIR/recursive-impl-trait-type-through-non-recursive.rs:21:25
|
LL | fn wrap<T>(t: T) -> impl Sized { (t,) }
| ---------- returning this opaque type `impl Sized`
...
LL | fn recursive_wrap2() -> impl Sized {
| ^^^^^^^^^^ expands to a recursive type
|
= note: expanded type is `((impl Sized,),)`
| ^^^^^^^^^^ recursive opaque type
LL | wrap(recursive_wrap())
| ---------------------- returning here with type `impl Sized`
error: aborting due to 4 previous errors

View File

@ -3,7 +3,6 @@
use std::fmt::Debug;
// Disallowed
fn in_adt_in_return() -> Vec<impl Debug> { panic!() }
//~^ ERROR opaque type expands to a recursive type
fn in_adt_in_return() -> Vec<impl Debug> { panic!() } //~ ERROR cannot resolve opaque type
fn main() {}

View File

@ -1,10 +1,12 @@
error[E0720]: opaque type expands to a recursive type
error[E0720]: cannot resolve opaque type
--> $DIR/where-allowed-2.rs:6:30
|
LL | fn in_adt_in_return() -> Vec<impl Debug> { panic!() }
| ^^^^^^^^^^ expands to a recursive type
| ^^^^^^^^^^ -------- this returned value is of `!` type
| |
| cannot resolve opaque type
|
= note: type resolves to itself
= help: this error will resolve once the item's body returns a concrete type
error: aborting due to previous error