Properly handle async
blocks and fn
s in if
exprs without else
When encountering a tail expression in the then arm of an `if` expression without an `else` arm, account for `async fn` and `async` blocks to suggest `return`ing the value and pointing at the return type of the `async fn`. We now also account for AFIT when looking for the return type to point at. Fix #115405.
This commit is contained in:
parent
bdc15928c8
commit
37d2ea2fa0
12 changed files with 250 additions and 61 deletions
|
@ -92,14 +92,17 @@ impl<'a, 'tcx> Deref for Coerce<'a, 'tcx> {
|
||||||
|
|
||||||
type CoerceResult<'tcx> = InferResult<'tcx, (Vec<Adjustment<'tcx>>, Ty<'tcx>)>;
|
type CoerceResult<'tcx> = InferResult<'tcx, (Vec<Adjustment<'tcx>>, Ty<'tcx>)>;
|
||||||
|
|
||||||
struct CollectRetsVisitor<'tcx> {
|
pub struct CollectRetsVisitor<'tcx> {
|
||||||
ret_exprs: Vec<&'tcx hir::Expr<'tcx>>,
|
pub ret_exprs: Vec<&'tcx hir::Expr<'tcx>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'tcx> Visitor<'tcx> for CollectRetsVisitor<'tcx> {
|
impl<'tcx> Visitor<'tcx> for CollectRetsVisitor<'tcx> {
|
||||||
fn visit_expr(&mut self, expr: &'tcx Expr<'tcx>) {
|
fn visit_expr(&mut self, expr: &'tcx Expr<'tcx>) {
|
||||||
if let hir::ExprKind::Ret(_) = expr.kind {
|
match expr.kind {
|
||||||
self.ret_exprs.push(expr);
|
hir::ExprKind::Ret(_) => self.ret_exprs.push(expr),
|
||||||
|
// `return` in closures does not return from the outer function
|
||||||
|
hir::ExprKind::Closure(_) => return,
|
||||||
|
_ => {}
|
||||||
}
|
}
|
||||||
intravisit::walk_expr(self, expr);
|
intravisit::walk_expr(self, expr);
|
||||||
}
|
}
|
||||||
|
@ -1845,13 +1848,31 @@ impl<'tcx, 'exprs, E: AsCoercionSite> CoerceMany<'tcx, 'exprs, E> {
|
||||||
}
|
}
|
||||||
|
|
||||||
let parent_id = fcx.tcx.hir().get_parent_item(id);
|
let parent_id = fcx.tcx.hir().get_parent_item(id);
|
||||||
let parent_item = fcx.tcx.hir_node_by_def_id(parent_id.def_id);
|
let mut parent_item = fcx.tcx.hir_node_by_def_id(parent_id.def_id);
|
||||||
|
// When suggesting return, we need to account for closures and async blocks, not just items.
|
||||||
|
for (_, node) in fcx.tcx.hir().parent_iter(id) {
|
||||||
|
match node {
|
||||||
|
hir::Node::Expr(&hir::Expr {
|
||||||
|
kind: hir::ExprKind::Closure(hir::Closure { .. }),
|
||||||
|
..
|
||||||
|
}) => {
|
||||||
|
parent_item = node;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
hir::Node::Item(_) | hir::Node::TraitItem(_) | hir::Node::ImplItem(_) => break,
|
||||||
|
_ => {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if let (Some(expr), Some(_), Some((fn_id, fn_decl, _, _))) =
|
if let (Some(expr), Some(_), Some(fn_decl)) = (expression, blk_id, parent_item.fn_decl()) {
|
||||||
(expression, blk_id, fcx.get_node_fn_decl(parent_item))
|
|
||||||
{
|
|
||||||
fcx.suggest_missing_break_or_return_expr(
|
fcx.suggest_missing_break_or_return_expr(
|
||||||
&mut err, expr, fn_decl, expected, found, id, fn_id,
|
&mut err,
|
||||||
|
expr,
|
||||||
|
fn_decl,
|
||||||
|
expected,
|
||||||
|
found,
|
||||||
|
id,
|
||||||
|
parent_id.into(),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -963,14 +963,35 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||||
owner_id,
|
owner_id,
|
||||||
..
|
..
|
||||||
}) => Some((hir::HirId::make_owner(owner_id.def_id), &sig.decl, ident, false)),
|
}) => Some((hir::HirId::make_owner(owner_id.def_id), &sig.decl, ident, false)),
|
||||||
Node::Expr(&hir::Expr { hir_id, kind: hir::ExprKind::Closure(..), .. })
|
Node::Expr(&hir::Expr {
|
||||||
if let Node::Item(&hir::Item {
|
hir_id,
|
||||||
ident,
|
kind:
|
||||||
kind: hir::ItemKind::Fn(ref sig, ..),
|
hir::ExprKind::Closure(hir::Closure {
|
||||||
owner_id,
|
kind: hir::ClosureKind::Coroutine(..), ..
|
||||||
..
|
}),
|
||||||
}) = self.tcx.parent_hir_node(hir_id) =>
|
..
|
||||||
{
|
}) => {
|
||||||
|
let (ident, sig, owner_id) = match self.tcx.parent_hir_node(hir_id) {
|
||||||
|
Node::Item(&hir::Item {
|
||||||
|
ident,
|
||||||
|
kind: hir::ItemKind::Fn(ref sig, ..),
|
||||||
|
owner_id,
|
||||||
|
..
|
||||||
|
}) => (ident, sig, owner_id),
|
||||||
|
Node::TraitItem(&hir::TraitItem {
|
||||||
|
ident,
|
||||||
|
kind: hir::TraitItemKind::Fn(ref sig, ..),
|
||||||
|
owner_id,
|
||||||
|
..
|
||||||
|
}) => (ident, sig, owner_id),
|
||||||
|
Node::ImplItem(&hir::ImplItem {
|
||||||
|
ident,
|
||||||
|
kind: hir::ImplItemKind::Fn(ref sig, ..),
|
||||||
|
owner_id,
|
||||||
|
..
|
||||||
|
}) => (ident, sig, owner_id),
|
||||||
|
_ => return None,
|
||||||
|
};
|
||||||
Some((
|
Some((
|
||||||
hir::HirId::make_owner(owner_id.def_id),
|
hir::HirId::make_owner(owner_id.def_id),
|
||||||
&sig.decl,
|
&sig.decl,
|
||||||
|
|
|
@ -1726,7 +1726,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Given a function block's `HirId`, returns its `FnDecl` if it exists, or `None` otherwise.
|
/// Given a function block's `HirId`, returns its `FnDecl` if it exists, or `None` otherwise.
|
||||||
fn get_parent_fn_decl(&self, blk_id: hir::HirId) -> Option<(&'tcx hir::FnDecl<'tcx>, Ident)> {
|
pub(crate) fn get_parent_fn_decl(
|
||||||
|
&self,
|
||||||
|
blk_id: hir::HirId,
|
||||||
|
) -> Option<(&'tcx hir::FnDecl<'tcx>, Ident)> {
|
||||||
let parent = self.tcx.hir_node_by_def_id(self.tcx.hir().get_parent_item(blk_id).def_id);
|
let parent = self.tcx.hir_node_by_def_id(self.tcx.hir().get_parent_item(blk_id).def_id);
|
||||||
self.get_node_fn_decl(parent).map(|(_, fn_decl, ident, _)| (fn_decl, ident))
|
self.get_node_fn_decl(parent).map(|(_, fn_decl, ident, _)| (fn_decl, ident))
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
use super::FnCtxt;
|
use super::FnCtxt;
|
||||||
|
|
||||||
|
use crate::coercion::CollectRetsVisitor;
|
||||||
use crate::errors;
|
use crate::errors;
|
||||||
use crate::fluent_generated as fluent;
|
use crate::fluent_generated as fluent;
|
||||||
use crate::fn_ctxt::rustc_span::BytePos;
|
use crate::fn_ctxt::rustc_span::BytePos;
|
||||||
|
@ -16,6 +17,7 @@ use rustc_errors::{Applicability, Diagnostic, MultiSpan};
|
||||||
use rustc_hir as hir;
|
use rustc_hir as hir;
|
||||||
use rustc_hir::def::Res;
|
use rustc_hir::def::Res;
|
||||||
use rustc_hir::def::{CtorKind, CtorOf, DefKind};
|
use rustc_hir::def::{CtorKind, CtorOf, DefKind};
|
||||||
|
use rustc_hir::intravisit::{Map, Visitor};
|
||||||
use rustc_hir::lang_items::LangItem;
|
use rustc_hir::lang_items::LangItem;
|
||||||
use rustc_hir::{
|
use rustc_hir::{
|
||||||
CoroutineDesugaring, CoroutineKind, CoroutineSource, Expr, ExprKind, GenericBound, HirId, Node,
|
CoroutineDesugaring, CoroutineKind, CoroutineSource, Expr, ExprKind, GenericBound, HirId, Node,
|
||||||
|
@ -827,6 +829,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||||
}
|
}
|
||||||
hir::FnRetTy::Return(hir_ty) => {
|
hir::FnRetTy::Return(hir_ty) => {
|
||||||
if let hir::TyKind::OpaqueDef(item_id, ..) = hir_ty.kind
|
if let hir::TyKind::OpaqueDef(item_id, ..) = hir_ty.kind
|
||||||
|
// FIXME: account for RPITIT.
|
||||||
&& let hir::Node::Item(hir::Item {
|
&& let hir::Node::Item(hir::Item {
|
||||||
kind: hir::ItemKind::OpaqueTy(op_ty), ..
|
kind: hir::ItemKind::OpaqueTy(op_ty), ..
|
||||||
}) = self.tcx.hir_node(item_id.hir_id())
|
}) = self.tcx.hir_node(item_id.hir_id())
|
||||||
|
@ -1038,33 +1041,81 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if let hir::FnRetTy::Return(ty) = fn_decl.output {
|
let in_closure = matches!(
|
||||||
let ty = self.astconv().ast_ty_to_ty(ty);
|
self.tcx
|
||||||
let bound_vars = self.tcx.late_bound_vars(fn_id);
|
.hir()
|
||||||
let ty = self
|
.parent_iter(id)
|
||||||
.tcx
|
.filter(|(_, node)| {
|
||||||
.instantiate_bound_regions_with_erased(Binder::bind_with_vars(ty, bound_vars));
|
matches!(
|
||||||
let ty = match self.tcx.asyncness(fn_id.owner) {
|
node,
|
||||||
ty::Asyncness::Yes => self.get_impl_future_output_ty(ty).unwrap_or_else(|| {
|
Node::Expr(Expr { kind: ExprKind::Closure(..), .. })
|
||||||
span_bug!(fn_decl.output.span(), "failed to get output type of async function")
|
| Node::Item(_)
|
||||||
}),
|
| Node::TraitItem(_)
|
||||||
ty::Asyncness::No => ty,
|
| Node::ImplItem(_)
|
||||||
};
|
)
|
||||||
let ty = self.normalize(expr.span, ty);
|
})
|
||||||
if self.can_coerce(found, ty) {
|
.next(),
|
||||||
if let Some(owner_node) = self.tcx.hir_node(fn_id).as_owner()
|
Some((_, Node::Expr(Expr { kind: ExprKind::Closure(..), .. })))
|
||||||
&& let Some(span) = expr.span.find_ancestor_inside(*owner_node.span())
|
);
|
||||||
{
|
|
||||||
err.multipart_suggestion(
|
let can_return = match fn_decl.output {
|
||||||
"you might have meant to return this value",
|
hir::FnRetTy::Return(ty) => {
|
||||||
vec![
|
let ty = self.astconv().ast_ty_to_ty(ty);
|
||||||
(span.shrink_to_lo(), "return ".to_string()),
|
let bound_vars = self.tcx.late_bound_vars(fn_id);
|
||||||
(span.shrink_to_hi(), ";".to_string()),
|
let ty = self
|
||||||
],
|
.tcx
|
||||||
Applicability::MaybeIncorrect,
|
.instantiate_bound_regions_with_erased(Binder::bind_with_vars(ty, bound_vars));
|
||||||
);
|
let ty = match self.tcx.asyncness(fn_id.owner) {
|
||||||
}
|
ty::Asyncness::Yes => self.get_impl_future_output_ty(ty).unwrap_or_else(|| {
|
||||||
|
span_bug!(
|
||||||
|
fn_decl.output.span(),
|
||||||
|
"failed to get output type of async function"
|
||||||
|
)
|
||||||
|
}),
|
||||||
|
ty::Asyncness::No => ty,
|
||||||
|
};
|
||||||
|
let ty = self.normalize(expr.span, ty);
|
||||||
|
self.can_coerce(found, ty)
|
||||||
}
|
}
|
||||||
|
hir::FnRetTy::DefaultReturn(_) if in_closure => {
|
||||||
|
let mut rets = vec![];
|
||||||
|
if let Some(ret_coercion) = self.ret_coercion.as_ref() {
|
||||||
|
let ret_ty = ret_coercion.borrow().expected_ty();
|
||||||
|
rets.push(ret_ty);
|
||||||
|
}
|
||||||
|
let mut visitor = CollectRetsVisitor { ret_exprs: vec![] };
|
||||||
|
if let Some(item) = self.tcx.hir().find(id)
|
||||||
|
&& let Node::Expr(expr) = item
|
||||||
|
{
|
||||||
|
visitor.visit_expr(expr);
|
||||||
|
for expr in visitor.ret_exprs {
|
||||||
|
if let Some(ty) = self.typeck_results.borrow().node_type_opt(expr.hir_id) {
|
||||||
|
rets.push(ty);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if let hir::ExprKind::Block(hir::Block { expr: Some(expr), .. }, _) = expr.kind
|
||||||
|
{
|
||||||
|
if let Some(ty) = self.typeck_results.borrow().node_type_opt(expr.hir_id) {
|
||||||
|
rets.push(ty);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
rets.into_iter().all(|ty| self.can_coerce(found, ty))
|
||||||
|
}
|
||||||
|
_ => false,
|
||||||
|
};
|
||||||
|
if can_return
|
||||||
|
&& let Some(owner_node) = self.tcx.hir_node(fn_id).as_owner()
|
||||||
|
&& let Some(span) = expr.span.find_ancestor_inside(owner_node.span())
|
||||||
|
{
|
||||||
|
err.multipart_suggestion(
|
||||||
|
"you might have meant to return this value",
|
||||||
|
vec![
|
||||||
|
(span.shrink_to_lo(), "return ".to_string()),
|
||||||
|
(span.shrink_to_hi(), ";".to_string()),
|
||||||
|
],
|
||||||
|
Applicability::MaybeIncorrect,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -617,7 +617,7 @@ impl<'hir> Map<'hir> {
|
||||||
Node::Item(_)
|
Node::Item(_)
|
||||||
| Node::ForeignItem(_)
|
| Node::ForeignItem(_)
|
||||||
| Node::TraitItem(_)
|
| Node::TraitItem(_)
|
||||||
| Node::Expr(Expr { kind: ExprKind::Closure { .. }, .. })
|
| Node::Expr(Expr { kind: ExprKind::Closure(_), .. })
|
||||||
| Node::ImplItem(_)
|
| Node::ImplItem(_)
|
||||||
// The input node `id` must be enclosed in the method's body as opposed
|
// The input node `id` must be enclosed in the method's body as opposed
|
||||||
// to some other place such as its return type (fixes #114918).
|
// to some other place such as its return type (fixes #114918).
|
||||||
|
|
|
@ -900,7 +900,7 @@ impl<'a> Parser<'a> {
|
||||||
// fn foo() -> Foo {
|
// fn foo() -> Foo {
|
||||||
// field: value,
|
// field: value,
|
||||||
// }
|
// }
|
||||||
info!(?maybe_struct_name, ?self.token);
|
debug!(?maybe_struct_name, ?self.token);
|
||||||
let mut snapshot = self.create_snapshot_for_diagnostic();
|
let mut snapshot = self.create_snapshot_for_diagnostic();
|
||||||
let path = Path {
|
let path = Path {
|
||||||
segments: ThinVec::new(),
|
segments: ThinVec::new(),
|
||||||
|
|
22
tests/ui/async-await/missing-return-in-async-block.fixed
Normal file
22
tests/ui/async-await/missing-return-in-async-block.fixed
Normal file
|
@ -0,0 +1,22 @@
|
||||||
|
// run-rustfix
|
||||||
|
// edition:2021
|
||||||
|
use std::future::Future;
|
||||||
|
use std::pin::Pin;
|
||||||
|
pub struct S;
|
||||||
|
pub fn foo() {
|
||||||
|
let _ = Box::pin(async move {
|
||||||
|
if true {
|
||||||
|
return Ok(S); //~ ERROR mismatched types
|
||||||
|
}
|
||||||
|
Err(())
|
||||||
|
});
|
||||||
|
}
|
||||||
|
pub fn bar() -> Pin<Box<dyn Future<Output = Result<S, ()>> + 'static>> {
|
||||||
|
Box::pin(async move {
|
||||||
|
if true {
|
||||||
|
return Ok(S); //~ ERROR mismatched types
|
||||||
|
}
|
||||||
|
Err(())
|
||||||
|
})
|
||||||
|
}
|
||||||
|
fn main() {}
|
22
tests/ui/async-await/missing-return-in-async-block.rs
Normal file
22
tests/ui/async-await/missing-return-in-async-block.rs
Normal file
|
@ -0,0 +1,22 @@
|
||||||
|
// run-rustfix
|
||||||
|
// edition:2021
|
||||||
|
use std::future::Future;
|
||||||
|
use std::pin::Pin;
|
||||||
|
pub struct S;
|
||||||
|
pub fn foo() {
|
||||||
|
let _ = Box::pin(async move {
|
||||||
|
if true {
|
||||||
|
Ok(S) //~ ERROR mismatched types
|
||||||
|
}
|
||||||
|
Err(())
|
||||||
|
});
|
||||||
|
}
|
||||||
|
pub fn bar() -> Pin<Box<dyn Future<Output = Result<S, ()>> + 'static>> {
|
||||||
|
Box::pin(async move {
|
||||||
|
if true {
|
||||||
|
Ok(S) //~ ERROR mismatched types
|
||||||
|
}
|
||||||
|
Err(())
|
||||||
|
})
|
||||||
|
}
|
||||||
|
fn main() {}
|
35
tests/ui/async-await/missing-return-in-async-block.stderr
Normal file
35
tests/ui/async-await/missing-return-in-async-block.stderr
Normal file
|
@ -0,0 +1,35 @@
|
||||||
|
error[E0308]: mismatched types
|
||||||
|
--> $DIR/missing-return-in-async-block.rs:9:13
|
||||||
|
|
|
||||||
|
LL | / if true {
|
||||||
|
LL | | Ok(S)
|
||||||
|
| | ^^^^^ expected `()`, found `Result<S, _>`
|
||||||
|
LL | | }
|
||||||
|
| |_________- expected this to be `()`
|
||||||
|
|
|
||||||
|
= note: expected unit type `()`
|
||||||
|
found enum `Result<S, _>`
|
||||||
|
help: you might have meant to return this value
|
||||||
|
|
|
||||||
|
LL | return Ok(S);
|
||||||
|
| ++++++ +
|
||||||
|
|
||||||
|
error[E0308]: mismatched types
|
||||||
|
--> $DIR/missing-return-in-async-block.rs:17:13
|
||||||
|
|
|
||||||
|
LL | / if true {
|
||||||
|
LL | | Ok(S)
|
||||||
|
| | ^^^^^ expected `()`, found `Result<S, _>`
|
||||||
|
LL | | }
|
||||||
|
| |_________- expected this to be `()`
|
||||||
|
|
|
||||||
|
= note: expected unit type `()`
|
||||||
|
found enum `Result<S, _>`
|
||||||
|
help: you might have meant to return this value
|
||||||
|
|
|
||||||
|
LL | return Ok(S);
|
||||||
|
| ++++++ +
|
||||||
|
|
||||||
|
error: aborting due to 2 previous errors
|
||||||
|
|
||||||
|
For more information about this error, try `rustc --explain E0308`.
|
|
@ -1,6 +1,8 @@
|
||||||
error[E0308]: mismatched types
|
error[E0308]: mismatched types
|
||||||
--> $DIR/default-body-type-err-2.rs:7:9
|
--> $DIR/default-body-type-err-2.rs:7:9
|
||||||
|
|
|
|
||||||
|
LL | async fn woopsie_async(&self) -> String {
|
||||||
|
| ------ expected `String` because of return type
|
||||||
LL | 42
|
LL | 42
|
||||||
| ^^- help: try using a conversion method: `.to_string()`
|
| ^^- help: try using a conversion method: `.to_string()`
|
||||||
| |
|
| |
|
||||||
|
|
|
@ -8,6 +8,7 @@ fn closure() {
|
||||||
if true {
|
if true {
|
||||||
Err(1)
|
Err(1)
|
||||||
//~^ ERROR mismatched types
|
//~^ ERROR mismatched types
|
||||||
|
//~| HELP you might have meant to return this value
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
|
@ -21,6 +22,7 @@ fn async_block() {
|
||||||
if true {
|
if true {
|
||||||
Err(1)
|
Err(1)
|
||||||
//~^ ERROR mismatched types
|
//~^ ERROR mismatched types
|
||||||
|
//~| HELP you might have meant to return this value
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
|
|
|
@ -5,14 +5,37 @@ LL | / if true {
|
||||||
LL | | Err(1)
|
LL | | Err(1)
|
||||||
| | ^^^^^^ expected `()`, found `Result<_, {integer}>`
|
| | ^^^^^^ expected `()`, found `Result<_, {integer}>`
|
||||||
LL | |
|
LL | |
|
||||||
|
LL | |
|
||||||
LL | | }
|
LL | | }
|
||||||
| |_____________- expected this to be `()`
|
| |_____________- expected this to be `()`
|
||||||
|
|
|
|
||||||
= note: expected unit type `()`
|
= note: expected unit type `()`
|
||||||
found enum `Result<_, {integer}>`
|
found enum `Result<_, {integer}>`
|
||||||
|
help: you might have meant to return this value
|
||||||
|
|
|
||||||
|
LL | return Err(1);
|
||||||
|
| ++++++ +
|
||||||
|
|
||||||
error[E0308]: mismatched types
|
error[E0308]: mismatched types
|
||||||
--> $DIR/dont-suggest-break-thru-item.rs:22:17
|
--> $DIR/dont-suggest-break-thru-item.rs:23:17
|
||||||
|
|
|
||||||
|
LL | / if true {
|
||||||
|
LL | | Err(1)
|
||||||
|
| | ^^^^^^ expected `()`, found `Result<_, {integer}>`
|
||||||
|
LL | |
|
||||||
|
LL | |
|
||||||
|
LL | | }
|
||||||
|
| |_____________- expected this to be `()`
|
||||||
|
|
|
||||||
|
= note: expected unit type `()`
|
||||||
|
found enum `Result<_, {integer}>`
|
||||||
|
help: you might have meant to return this value
|
||||||
|
|
|
||||||
|
LL | return Err(1);
|
||||||
|
| ++++++ +
|
||||||
|
|
||||||
|
error[E0308]: mismatched types
|
||||||
|
--> $DIR/dont-suggest-break-thru-item.rs:37:17
|
||||||
|
|
|
|
||||||
LL | / if true {
|
LL | / if true {
|
||||||
LL | | Err(1)
|
LL | | Err(1)
|
||||||
|
@ -25,20 +48,7 @@ LL | | }
|
||||||
found enum `Result<_, {integer}>`
|
found enum `Result<_, {integer}>`
|
||||||
|
|
||||||
error[E0308]: mismatched types
|
error[E0308]: mismatched types
|
||||||
--> $DIR/dont-suggest-break-thru-item.rs:35:17
|
--> $DIR/dont-suggest-break-thru-item.rs:49:17
|
||||||
|
|
|
||||||
LL | / if true {
|
|
||||||
LL | | Err(1)
|
|
||||||
| | ^^^^^^ expected `()`, found `Result<_, {integer}>`
|
|
||||||
LL | |
|
|
||||||
LL | | }
|
|
||||||
| |_____________- expected this to be `()`
|
|
||||||
|
|
|
||||||
= note: expected unit type `()`
|
|
||||||
found enum `Result<_, {integer}>`
|
|
||||||
|
|
||||||
error[E0308]: mismatched types
|
|
||||||
--> $DIR/dont-suggest-break-thru-item.rs:47:17
|
|
||||||
|
|
|
|
||||||
LL | / if true {
|
LL | / if true {
|
||||||
LL | | Err(1)
|
LL | | Err(1)
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue