Rollup merge of #120270 - compiler-errors:randos, r=lcnr
A bunch of random modifications r? oli-obk Kitchen sink of changes that I didn't know where to put elsewhere. Documentation tweaks mostly, but also removing some unreachable code and simplifying the pretty printing for closures/coroutines.
This commit is contained in:
commit
3b1c2eb44c
@ -12,7 +12,9 @@
|
|||||||
|
|
||||||
#[derive(Copy, Clone, Debug)]
|
#[derive(Copy, Clone, Debug)]
|
||||||
pub enum AutoderefKind {
|
pub enum AutoderefKind {
|
||||||
|
/// A true pointer type, such as `&T` and `*mut T`.
|
||||||
Builtin,
|
Builtin,
|
||||||
|
/// A type which must dispatch to a `Deref` implementation.
|
||||||
Overloaded,
|
Overloaded,
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -83,6 +85,7 @@ fn next(&mut self) -> Option<Self::Item> {
|
|||||||
(AutoderefKind::Builtin, ty)
|
(AutoderefKind::Builtin, ty)
|
||||||
}
|
}
|
||||||
} else if let Some(ty) = self.overloaded_deref_ty(self.state.cur_ty) {
|
} else if let Some(ty) = self.overloaded_deref_ty(self.state.cur_ty) {
|
||||||
|
// The overloaded deref check already normalizes the pointee type.
|
||||||
(AutoderefKind::Overloaded, ty)
|
(AutoderefKind::Overloaded, ty)
|
||||||
} else {
|
} else {
|
||||||
return None;
|
return None;
|
||||||
|
@ -254,7 +254,7 @@ fn compare_method_predicate_entailment<'tcx>(
|
|||||||
// checks. For the comparison to be valid, we need to
|
// checks. For the comparison to be valid, we need to
|
||||||
// normalize the associated types in the impl/trait methods
|
// normalize the associated types in the impl/trait methods
|
||||||
// first. However, because function types bind regions, just
|
// first. However, because function types bind regions, just
|
||||||
// calling `normalize_associated_types_in` would have no effect on
|
// calling `FnCtxt::normalize` would have no effect on
|
||||||
// any associated types appearing in the fn arguments or return
|
// any associated types appearing in the fn arguments or return
|
||||||
// type.
|
// type.
|
||||||
|
|
||||||
|
@ -746,11 +746,13 @@ fn assemble_inherent_impl_probe(&mut self, impl_def_id: DefId) {
|
|||||||
let (xform_self_ty, xform_ret_ty) = self.xform_self_ty(item, impl_ty, impl_args);
|
let (xform_self_ty, xform_ret_ty) = self.xform_self_ty(item, impl_ty, impl_args);
|
||||||
debug!("xform_self_ty: {:?}, xform_ret_ty: {:?}", xform_self_ty, xform_ret_ty);
|
debug!("xform_self_ty: {:?}, xform_ret_ty: {:?}", xform_self_ty, xform_ret_ty);
|
||||||
|
|
||||||
// We can't use normalize_associated_types_in as it will pollute the
|
// We can't use `FnCtxt::normalize` as it will pollute the
|
||||||
// fcx's fulfillment context after this probe is over.
|
// fcx's fulfillment context after this probe is over.
|
||||||
|
//
|
||||||
// Note: we only normalize `xform_self_ty` here since the normalization
|
// Note: we only normalize `xform_self_ty` here since the normalization
|
||||||
// of the return type can lead to inference results that prohibit
|
// of the return type can lead to inference results that prohibit
|
||||||
// valid candidates from being found, see issue #85671
|
// valid candidates from being found, see issue #85671
|
||||||
|
//
|
||||||
// FIXME Postponing the normalization of the return type likely only hides a deeper bug,
|
// FIXME Postponing the normalization of the return type likely only hides a deeper bug,
|
||||||
// which might be caused by the `param_env` itself. The clauses of the `param_env`
|
// which might be caused by the `param_env` itself. The clauses of the `param_env`
|
||||||
// maybe shouldn't include `Param`s, but rather fresh variables or be canonicalized,
|
// maybe shouldn't include `Param`s, but rather fresh variables or be canonicalized,
|
||||||
|
@ -804,17 +804,12 @@ fn pretty_print_type(&mut self, ty: Ty<'tcx>) -> Result<(), PrintError> {
|
|||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
p!(print_def_path(did, args));
|
p!(print_def_path(did, args));
|
||||||
p!(" upvar_tys=(");
|
p!(
|
||||||
if !args.as_coroutine().is_valid() {
|
" upvar_tys=",
|
||||||
p!("unavailable");
|
print(args.as_coroutine().tupled_upvars_ty()),
|
||||||
} else {
|
" witness=",
|
||||||
self.comma_sep(args.as_coroutine().upvar_tys().iter())?;
|
print(args.as_coroutine().witness())
|
||||||
}
|
);
|
||||||
p!(")");
|
|
||||||
|
|
||||||
if args.as_coroutine().is_valid() {
|
|
||||||
p!(" ", print(args.as_coroutine().witness()));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
p!("}}")
|
p!("}}")
|
||||||
@ -868,19 +863,14 @@ fn pretty_print_type(&mut self, ty: Ty<'tcx>) -> Result<(), PrintError> {
|
|||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
p!(print_def_path(did, args));
|
p!(print_def_path(did, args));
|
||||||
if !args.as_closure().is_valid() {
|
p!(
|
||||||
p!(" closure_args=(unavailable)");
|
" closure_kind_ty=",
|
||||||
p!(write(" args={}", args.print_as_list()));
|
print(args.as_closure().kind_ty()),
|
||||||
} else {
|
" closure_sig_as_fn_ptr_ty=",
|
||||||
p!(" closure_kind_ty=", print(args.as_closure().kind_ty()));
|
print(args.as_closure().sig_as_fn_ptr_ty()),
|
||||||
p!(
|
" upvar_tys=",
|
||||||
" closure_sig_as_fn_ptr_ty=",
|
print(args.as_closure().tupled_upvars_ty())
|
||||||
print(args.as_closure().sig_as_fn_ptr_ty())
|
);
|
||||||
);
|
|
||||||
p!(" upvar_tys=(");
|
|
||||||
self.comma_sep(args.as_closure().upvar_tys().iter())?;
|
|
||||||
p!(")");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
p!("}}");
|
p!("}}");
|
||||||
}
|
}
|
||||||
|
@ -242,9 +242,15 @@ pub struct ClosureArgs<'tcx> {
|
|||||||
|
|
||||||
/// Struct returned by `split()`.
|
/// Struct returned by `split()`.
|
||||||
pub struct ClosureArgsParts<'tcx> {
|
pub struct ClosureArgsParts<'tcx> {
|
||||||
|
/// This is the args of the typeck root.
|
||||||
pub parent_args: &'tcx [GenericArg<'tcx>],
|
pub parent_args: &'tcx [GenericArg<'tcx>],
|
||||||
|
/// Represents the maximum calling capability of the closure.
|
||||||
pub closure_kind_ty: Ty<'tcx>,
|
pub closure_kind_ty: Ty<'tcx>,
|
||||||
|
/// Captures the closure's signature. This closure signature is "tupled", and
|
||||||
|
/// thus has a peculiar signature of `extern "rust-call" fn((Args, ...)) -> Ty`.
|
||||||
pub closure_sig_as_fn_ptr_ty: Ty<'tcx>,
|
pub closure_sig_as_fn_ptr_ty: Ty<'tcx>,
|
||||||
|
/// The upvars captured by the closure. Remains an inference variable
|
||||||
|
/// until the upvar analysis, which happens late in HIR typeck.
|
||||||
pub tupled_upvars_ty: Ty<'tcx>,
|
pub tupled_upvars_ty: Ty<'tcx>,
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -277,15 +283,6 @@ fn split(self) -> ClosureArgsParts<'tcx> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns `true` only if enough of the synthetic types are known to
|
|
||||||
/// allow using all of the methods on `ClosureArgs` without panicking.
|
|
||||||
///
|
|
||||||
/// Used primarily by `ty::print::pretty` to be able to handle closure
|
|
||||||
/// types that haven't had their synthetic types substituted in.
|
|
||||||
pub fn is_valid(self) -> bool {
|
|
||||||
self.args.len() >= 3 && matches!(self.split().tupled_upvars_ty.kind(), Tuple(_))
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Returns the substitutions of the closure's parent.
|
/// Returns the substitutions of the closure's parent.
|
||||||
pub fn parent_args(self) -> &'tcx [GenericArg<'tcx>] {
|
pub fn parent_args(self) -> &'tcx [GenericArg<'tcx>] {
|
||||||
self.split().parent_args
|
self.split().parent_args
|
||||||
@ -296,9 +293,9 @@ pub fn parent_args(self) -> &'tcx [GenericArg<'tcx>] {
|
|||||||
/// empty iterator is returned.
|
/// empty iterator is returned.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn upvar_tys(self) -> &'tcx List<Ty<'tcx>> {
|
pub fn upvar_tys(self) -> &'tcx List<Ty<'tcx>> {
|
||||||
match self.tupled_upvars_ty().kind() {
|
match *self.tupled_upvars_ty().kind() {
|
||||||
TyKind::Error(_) => ty::List::empty(),
|
TyKind::Error(_) => ty::List::empty(),
|
||||||
TyKind::Tuple(..) => self.tupled_upvars_ty().tuple_fields(),
|
TyKind::Tuple(tys) => tys,
|
||||||
TyKind::Infer(_) => bug!("upvar_tys called before capture types are inferred"),
|
TyKind::Infer(_) => bug!("upvar_tys called before capture types are inferred"),
|
||||||
ty => bug!("Unexpected representation of upvar types tuple {:?}", ty),
|
ty => bug!("Unexpected representation of upvar types tuple {:?}", ty),
|
||||||
}
|
}
|
||||||
@ -337,10 +334,9 @@ pub fn kind(self) -> ty::ClosureKind {
|
|||||||
|
|
||||||
/// Extracts the signature from the closure.
|
/// Extracts the signature from the closure.
|
||||||
pub fn sig(self) -> ty::PolyFnSig<'tcx> {
|
pub fn sig(self) -> ty::PolyFnSig<'tcx> {
|
||||||
let ty = self.sig_as_fn_ptr_ty();
|
match *self.sig_as_fn_ptr_ty().kind() {
|
||||||
match ty.kind() {
|
ty::FnPtr(sig) => sig,
|
||||||
ty::FnPtr(sig) => *sig,
|
ty => bug!("closure_sig_as_fn_ptr_ty is not a fn-ptr: {ty:?}"),
|
||||||
_ => bug!("closure_sig_as_fn_ptr_ty is not a fn-ptr: {:?}", ty.kind()),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -356,11 +352,17 @@ pub struct CoroutineArgs<'tcx> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub struct CoroutineArgsParts<'tcx> {
|
pub struct CoroutineArgsParts<'tcx> {
|
||||||
|
/// This is the args of the typeck root.
|
||||||
pub parent_args: &'tcx [GenericArg<'tcx>],
|
pub parent_args: &'tcx [GenericArg<'tcx>],
|
||||||
pub resume_ty: Ty<'tcx>,
|
pub resume_ty: Ty<'tcx>,
|
||||||
pub yield_ty: Ty<'tcx>,
|
pub yield_ty: Ty<'tcx>,
|
||||||
pub return_ty: Ty<'tcx>,
|
pub return_ty: Ty<'tcx>,
|
||||||
|
/// The interior type of the coroutine.
|
||||||
|
/// Represents all types that are stored in locals
|
||||||
|
/// in the coroutine's body.
|
||||||
pub witness: Ty<'tcx>,
|
pub witness: Ty<'tcx>,
|
||||||
|
/// The upvars captured by the closure. Remains an inference variable
|
||||||
|
/// until the upvar analysis, which happens late in HIR typeck.
|
||||||
pub tupled_upvars_ty: Ty<'tcx>,
|
pub tupled_upvars_ty: Ty<'tcx>,
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -397,15 +399,6 @@ fn split(self) -> CoroutineArgsParts<'tcx> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns `true` only if enough of the synthetic types are known to
|
|
||||||
/// allow using all of the methods on `CoroutineArgs` without panicking.
|
|
||||||
///
|
|
||||||
/// Used primarily by `ty::print::pretty` to be able to handle coroutine
|
|
||||||
/// types that haven't had their synthetic types substituted in.
|
|
||||||
pub fn is_valid(self) -> bool {
|
|
||||||
self.args.len() >= 5 && matches!(self.split().tupled_upvars_ty.kind(), Tuple(_))
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Returns the substitutions of the coroutine's parent.
|
/// Returns the substitutions of the coroutine's parent.
|
||||||
pub fn parent_args(self) -> &'tcx [GenericArg<'tcx>] {
|
pub fn parent_args(self) -> &'tcx [GenericArg<'tcx>] {
|
||||||
self.split().parent_args
|
self.split().parent_args
|
||||||
@ -425,9 +418,9 @@ pub fn witness(self) -> Ty<'tcx> {
|
|||||||
/// empty iterator is returned.
|
/// empty iterator is returned.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn upvar_tys(self) -> &'tcx List<Ty<'tcx>> {
|
pub fn upvar_tys(self) -> &'tcx List<Ty<'tcx>> {
|
||||||
match self.tupled_upvars_ty().kind() {
|
match *self.tupled_upvars_ty().kind() {
|
||||||
TyKind::Error(_) => ty::List::empty(),
|
TyKind::Error(_) => ty::List::empty(),
|
||||||
TyKind::Tuple(..) => self.tupled_upvars_ty().tuple_fields(),
|
TyKind::Tuple(tys) => tys,
|
||||||
TyKind::Infer(_) => bug!("upvar_tys called before capture types are inferred"),
|
TyKind::Infer(_) => bug!("upvar_tys called before capture types are inferred"),
|
||||||
ty => bug!("Unexpected representation of upvar types tuple {:?}", ty),
|
ty => bug!("Unexpected representation of upvar types tuple {:?}", ty),
|
||||||
}
|
}
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
//! Computes a normalizes-to (projection) goal for inherent associated types,
|
//! Computes a normalizes-to (projection) goal for inherent associated types,
|
||||||
//! `#![feature(lazy_type_alias)]` and `#![feature(type_alias_impl_trait)]`.
|
//! `#![feature(lazy_type_alias)]` and `#![feature(type_alias_impl_trait)]`.
|
||||||
//!
|
//!
|
||||||
//! Since a weak alias is not ambiguous, this just computes the `type_of` of
|
//! Since a weak alias is never ambiguous, this just computes the `type_of` of
|
||||||
//! the alias and registers the where-clauses of the type alias.
|
//! the alias and registers the where-clauses of the type alias.
|
||||||
use rustc_middle::traits::solve::{Certainty, Goal, GoalSource, QueryResult};
|
use rustc_middle::traits::solve::{Certainty, Goal, GoalSource, QueryResult};
|
||||||
use rustc_middle::ty;
|
use rustc_middle::ty;
|
||||||
|
@ -232,32 +232,12 @@ pub fn dtorck_constraint_for_ty_inner<'tcx>(
|
|||||||
Ok::<_, NoSolution>(())
|
Ok::<_, NoSolution>(())
|
||||||
})?,
|
})?,
|
||||||
|
|
||||||
ty::Closure(_, args) => {
|
ty::Closure(_, args) => rustc_data_structures::stack::ensure_sufficient_stack(|| {
|
||||||
if !args.as_closure().is_valid() {
|
for ty in args.as_closure().upvar_tys() {
|
||||||
// By the time this code runs, all type variables ought to
|
dtorck_constraint_for_ty_inner(tcx, param_env, span, depth + 1, ty, constraints)?;
|
||||||
// be fully resolved.
|
|
||||||
|
|
||||||
tcx.dcx().span_delayed_bug(
|
|
||||||
span,
|
|
||||||
format!("upvar_tys for closure not found. Expected capture information for closure {ty}",),
|
|
||||||
);
|
|
||||||
return Err(NoSolution);
|
|
||||||
}
|
}
|
||||||
|
Ok::<_, NoSolution>(())
|
||||||
rustc_data_structures::stack::ensure_sufficient_stack(|| {
|
})?,
|
||||||
for ty in args.as_closure().upvar_tys() {
|
|
||||||
dtorck_constraint_for_ty_inner(
|
|
||||||
tcx,
|
|
||||||
param_env,
|
|
||||||
span,
|
|
||||||
depth + 1,
|
|
||||||
ty,
|
|
||||||
constraints,
|
|
||||||
)?;
|
|
||||||
}
|
|
||||||
Ok::<_, NoSolution>(())
|
|
||||||
})?
|
|
||||||
}
|
|
||||||
|
|
||||||
ty::Coroutine(_, args) => {
|
ty::Coroutine(_, args) => {
|
||||||
// rust-lang/rust#49918: types can be constructed, stored
|
// rust-lang/rust#49918: types can be constructed, stored
|
||||||
@ -283,15 +263,6 @@ pub fn dtorck_constraint_for_ty_inner<'tcx>(
|
|||||||
// derived from lifetimes attached to the upvars and resume
|
// derived from lifetimes attached to the upvars and resume
|
||||||
// argument, and we *do* incorporate those here.
|
// argument, and we *do* incorporate those here.
|
||||||
let args = args.as_coroutine();
|
let args = args.as_coroutine();
|
||||||
if !args.is_valid() {
|
|
||||||
// By the time this code runs, all type variables ought to
|
|
||||||
// be fully resolved.
|
|
||||||
tcx.dcx().span_delayed_bug(
|
|
||||||
span,
|
|
||||||
format!("upvar_tys for coroutine not found. Expected capture information for coroutine {ty}",),
|
|
||||||
);
|
|
||||||
return Err(NoSolution);
|
|
||||||
}
|
|
||||||
|
|
||||||
// While we conservatively assume that all coroutines require drop
|
// While we conservatively assume that all coroutines require drop
|
||||||
// to avoid query cycles during MIR building, we can check the actual
|
// to avoid query cycles during MIR building, we can check the actual
|
||||||
|
@ -141,6 +141,13 @@ fn fully_perform(
|
|||||||
infcx: &InferCtxt<'tcx>,
|
infcx: &InferCtxt<'tcx>,
|
||||||
span: Span,
|
span: Span,
|
||||||
) -> Result<TypeOpOutput<'tcx, Self>, ErrorGuaranteed> {
|
) -> Result<TypeOpOutput<'tcx, Self>, ErrorGuaranteed> {
|
||||||
|
// In the new trait solver, query type ops are performed locally. This
|
||||||
|
// is because query type ops currently use the old canonicalizer, and
|
||||||
|
// that doesn't preserve things like opaques which have been registered
|
||||||
|
// during MIR typeck. Even after the old canonicalizer is gone, it's
|
||||||
|
// probably worthwhile just keeping this run-locally logic, since we
|
||||||
|
// probably don't gain much from caching here given the new solver does
|
||||||
|
// caching internally.
|
||||||
if infcx.next_trait_solver() {
|
if infcx.next_trait_solver() {
|
||||||
return Ok(scrape_region_constraints(
|
return Ok(scrape_region_constraints(
|
||||||
infcx,
|
infcx,
|
||||||
|
@ -9,7 +9,7 @@ LL | let c1 : () = c;
|
|||||||
| expected due to this
|
| expected due to this
|
||||||
|
|
|
|
||||||
= note: expected unit type `()`
|
= note: expected unit type `()`
|
||||||
found closure `{mod1::f<T>::{closure#0} closure_args=(unavailable) args=[T, ?8t, extern "rust-call" fn(()), ?7t]}`
|
found closure `{mod1::f<T>::{closure#0} closure_kind_ty=?8t closure_sig_as_fn_ptr_ty=extern "rust-call" fn(()) upvar_tys=?7t}`
|
||||||
help: use parentheses to call this closure
|
help: use parentheses to call this closure
|
||||||
|
|
|
|
||||||
LL | let c1 : () = c();
|
LL | let c1 : () = c();
|
||||||
|
@ -9,7 +9,7 @@ LL | let c1 : () = c;
|
|||||||
| expected due to this
|
| expected due to this
|
||||||
|
|
|
|
||||||
= note: expected unit type `()`
|
= note: expected unit type `()`
|
||||||
found closure `{f<T>::{closure#0} closure_args=(unavailable) args=[T, ?8t, extern "rust-call" fn(()), ?7t]}`
|
found closure `{f<T>::{closure#0} closure_kind_ty=?8t closure_sig_as_fn_ptr_ty=extern "rust-call" fn(()) upvar_tys=?7t}`
|
||||||
help: use parentheses to call this closure
|
help: use parentheses to call this closure
|
||||||
|
|
|
|
||||||
LL | let c1 : () = c();
|
LL | let c1 : () = c();
|
||||||
|
@ -7,7 +7,7 @@ LL | let foo: fn(u8) -> u8 = |v: u8| { a += v; a };
|
|||||||
| expected due to this
|
| expected due to this
|
||||||
|
|
|
|
||||||
= note: expected fn pointer `fn(u8) -> u8`
|
= note: expected fn pointer `fn(u8) -> u8`
|
||||||
found closure `{main::{closure#0} closure_args=(unavailable) args=[i8, extern "rust-call" fn((u8,)) -> u8, ?4t]}`
|
found closure `{main::{closure#0} closure_kind_ty=i8 closure_sig_as_fn_ptr_ty=extern "rust-call" fn((u8,)) -> u8 upvar_tys=?4t}`
|
||||||
note: closures can only be coerced to `fn` types if they do not capture any variables
|
note: closures can only be coerced to `fn` types if they do not capture any variables
|
||||||
--> $DIR/closure-print-verbose.rs:10:39
|
--> $DIR/closure-print-verbose.rs:10:39
|
||||||
|
|
|
|
||||||
|
@ -4,7 +4,7 @@ error: coroutine cannot be shared between threads safely
|
|||||||
LL | assert_sync(|| {
|
LL | assert_sync(|| {
|
||||||
| ^^^^^^^^^^^ coroutine is not `Sync`
|
| ^^^^^^^^^^^ coroutine is not `Sync`
|
||||||
|
|
|
|
||||||
= help: within `{main::{closure#0} upvar_tys=() {main::{closure#0}}}`, the trait `Sync` is not implemented for `NotSync`
|
= help: within `{main::{closure#0} upvar_tys=() witness={main::{closure#0}}}`, the trait `Sync` is not implemented for `NotSync`
|
||||||
note: coroutine is not `Sync` as this value is used across a yield
|
note: coroutine is not `Sync` as this value is used across a yield
|
||||||
--> $DIR/coroutine-print-verbose-2.rs:20:9
|
--> $DIR/coroutine-print-verbose-2.rs:20:9
|
||||||
|
|
|
|
||||||
@ -24,7 +24,7 @@ error: coroutine cannot be sent between threads safely
|
|||||||
LL | assert_send(|| {
|
LL | assert_send(|| {
|
||||||
| ^^^^^^^^^^^ coroutine is not `Send`
|
| ^^^^^^^^^^^ coroutine is not `Send`
|
||||||
|
|
|
|
||||||
= help: within `{main::{closure#1} upvar_tys=() {main::{closure#1}}}`, the trait `Send` is not implemented for `NotSend`
|
= help: within `{main::{closure#1} upvar_tys=() witness={main::{closure#1}}}`, the trait `Send` is not implemented for `NotSend`
|
||||||
note: coroutine is not `Send` as this value is used across a yield
|
note: coroutine is not `Send` as this value is used across a yield
|
||||||
--> $DIR/coroutine-print-verbose-2.rs:27:9
|
--> $DIR/coroutine-print-verbose-2.rs:27:9
|
||||||
|
|
|
|
||||||
|
@ -12,7 +12,7 @@ LL | | };
|
|||||||
| |_____^ expected `()`, found coroutine
|
| |_____^ expected `()`, found coroutine
|
||||||
|
|
|
|
||||||
= note: expected unit type `()`
|
= note: expected unit type `()`
|
||||||
found coroutine `{main::{closure#0} upvar_tys=(unavailable)}`
|
found coroutine `{main::{closure#0} upvar_tys=?4t witness=?6t}`
|
||||||
|
|
||||||
error: aborting due to 1 previous error
|
error: aborting due to 1 previous error
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user