Keep info on pre-desugaring expression for better "incorrect .await
" suggestion
Keep the `HirId` of `.await`ed expressions so in the case of a `fn` call on on a sync `fn`, we can suggest maybe turning it into an `async fn`.
This commit is contained in:
parent
d45e030c04
commit
f640438b40
14 changed files with 138 additions and 36 deletions
|
@ -479,8 +479,12 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
||||||
expr: &'hir hir::Expr<'hir>,
|
expr: &'hir hir::Expr<'hir>,
|
||||||
overall_span: Span,
|
overall_span: Span,
|
||||||
) -> &'hir hir::Expr<'hir> {
|
) -> &'hir hir::Expr<'hir> {
|
||||||
let constructor =
|
let constructor = self.arena.alloc(self.expr_lang_item_path(
|
||||||
self.arena.alloc(self.expr_lang_item_path(method_span, lang_item, ThinVec::new()));
|
method_span,
|
||||||
|
lang_item,
|
||||||
|
ThinVec::new(),
|
||||||
|
None,
|
||||||
|
));
|
||||||
self.expr_call(overall_span, constructor, std::slice::from_ref(expr))
|
self.expr_call(overall_span, constructor, std::slice::from_ref(expr))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -584,8 +588,12 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
||||||
// `future::from_generator`:
|
// `future::from_generator`:
|
||||||
let unstable_span =
|
let unstable_span =
|
||||||
self.mark_span_with_reason(DesugaringKind::Async, span, self.allow_gen_future.clone());
|
self.mark_span_with_reason(DesugaringKind::Async, span, self.allow_gen_future.clone());
|
||||||
let gen_future =
|
let gen_future = self.expr_lang_item_path(
|
||||||
self.expr_lang_item_path(unstable_span, hir::LangItem::FromGenerator, ThinVec::new());
|
unstable_span,
|
||||||
|
hir::LangItem::FromGenerator,
|
||||||
|
ThinVec::new(),
|
||||||
|
None,
|
||||||
|
);
|
||||||
|
|
||||||
// `future::from_generator(generator)`:
|
// `future::from_generator(generator)`:
|
||||||
hir::ExprKind::Call(self.arena.alloc(gen_future), arena_vec![self; generator])
|
hir::ExprKind::Call(self.arena.alloc(gen_future), arena_vec![self; generator])
|
||||||
|
@ -657,16 +665,19 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
||||||
span,
|
span,
|
||||||
hir::LangItem::PinNewUnchecked,
|
hir::LangItem::PinNewUnchecked,
|
||||||
arena_vec![self; ref_mut_pinned],
|
arena_vec![self; ref_mut_pinned],
|
||||||
|
Some(expr.hir_id),
|
||||||
);
|
);
|
||||||
let get_context = self.expr_call_lang_item_fn_mut(
|
let get_context = self.expr_call_lang_item_fn_mut(
|
||||||
gen_future_span,
|
gen_future_span,
|
||||||
hir::LangItem::GetContext,
|
hir::LangItem::GetContext,
|
||||||
arena_vec![self; task_context],
|
arena_vec![self; task_context],
|
||||||
|
Some(expr.hir_id),
|
||||||
);
|
);
|
||||||
let call = self.expr_call_lang_item_fn(
|
let call = self.expr_call_lang_item_fn(
|
||||||
span,
|
span,
|
||||||
hir::LangItem::FuturePoll,
|
hir::LangItem::FuturePoll,
|
||||||
arena_vec![self; new_unchecked, get_context],
|
arena_vec![self; new_unchecked, get_context],
|
||||||
|
Some(expr.hir_id),
|
||||||
);
|
);
|
||||||
self.arena.alloc(self.expr_unsafe(call))
|
self.arena.alloc(self.expr_unsafe(call))
|
||||||
};
|
};
|
||||||
|
@ -679,7 +690,12 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
||||||
let (x_pat, x_pat_hid) = self.pat_ident(span, x_ident);
|
let (x_pat, x_pat_hid) = self.pat_ident(span, x_ident);
|
||||||
let x_expr = self.expr_ident(span, x_ident, x_pat_hid);
|
let x_expr = self.expr_ident(span, x_ident, x_pat_hid);
|
||||||
let ready_field = self.single_pat_field(span, x_pat);
|
let ready_field = self.single_pat_field(span, x_pat);
|
||||||
let ready_pat = self.pat_lang_item_variant(span, hir::LangItem::PollReady, ready_field);
|
let ready_pat = self.pat_lang_item_variant(
|
||||||
|
span,
|
||||||
|
hir::LangItem::PollReady,
|
||||||
|
ready_field,
|
||||||
|
Some(expr.hir_id),
|
||||||
|
);
|
||||||
let break_x = self.with_loop_scope(loop_node_id, move |this| {
|
let break_x = self.with_loop_scope(loop_node_id, move |this| {
|
||||||
let expr_break =
|
let expr_break =
|
||||||
hir::ExprKind::Break(this.lower_loop_destination(None), Some(x_expr));
|
hir::ExprKind::Break(this.lower_loop_destination(None), Some(x_expr));
|
||||||
|
@ -690,7 +706,12 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
||||||
|
|
||||||
// `::std::task::Poll::Pending => {}`
|
// `::std::task::Poll::Pending => {}`
|
||||||
let pending_arm = {
|
let pending_arm = {
|
||||||
let pending_pat = self.pat_lang_item_variant(span, hir::LangItem::PollPending, &[]);
|
let pending_pat = self.pat_lang_item_variant(
|
||||||
|
span,
|
||||||
|
hir::LangItem::PollPending,
|
||||||
|
&[],
|
||||||
|
Some(expr.hir_id),
|
||||||
|
);
|
||||||
let empty_block = self.expr_block_empty(span);
|
let empty_block = self.expr_block_empty(span);
|
||||||
self.arm(pending_pat, empty_block)
|
self.arm(pending_pat, empty_block)
|
||||||
};
|
};
|
||||||
|
@ -1161,7 +1182,8 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
||||||
fn lower_expr_range_closed(&mut self, span: Span, e1: &Expr, e2: &Expr) -> hir::ExprKind<'hir> {
|
fn lower_expr_range_closed(&mut self, span: Span, e1: &Expr, e2: &Expr) -> hir::ExprKind<'hir> {
|
||||||
let e1 = self.lower_expr_mut(e1);
|
let e1 = self.lower_expr_mut(e1);
|
||||||
let e2 = self.lower_expr_mut(e2);
|
let e2 = self.lower_expr_mut(e2);
|
||||||
let fn_path = hir::QPath::LangItem(hir::LangItem::RangeInclusiveNew, self.lower_span(span));
|
let fn_path =
|
||||||
|
hir::QPath::LangItem(hir::LangItem::RangeInclusiveNew, self.lower_span(span), None);
|
||||||
let fn_expr =
|
let fn_expr =
|
||||||
self.arena.alloc(self.expr(span, hir::ExprKind::Path(fn_path), ThinVec::new()));
|
self.arena.alloc(self.expr(span, hir::ExprKind::Path(fn_path), ThinVec::new()));
|
||||||
hir::ExprKind::Call(fn_expr, arena_vec![self; e1, e2])
|
hir::ExprKind::Call(fn_expr, arena_vec![self; e1, e2])
|
||||||
|
@ -1195,7 +1217,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
||||||
);
|
);
|
||||||
|
|
||||||
hir::ExprKind::Struct(
|
hir::ExprKind::Struct(
|
||||||
self.arena.alloc(hir::QPath::LangItem(lang_item, self.lower_span(span))),
|
self.arena.alloc(hir::QPath::LangItem(lang_item, self.lower_span(span), None)),
|
||||||
fields,
|
fields,
|
||||||
None,
|
None,
|
||||||
)
|
)
|
||||||
|
@ -1390,6 +1412,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
||||||
head_span,
|
head_span,
|
||||||
hir::LangItem::IteratorNext,
|
hir::LangItem::IteratorNext,
|
||||||
arena_vec![self; ref_mut_iter],
|
arena_vec![self; ref_mut_iter],
|
||||||
|
None,
|
||||||
);
|
);
|
||||||
let arms = arena_vec![self; none_arm, some_arm];
|
let arms = arena_vec![self; none_arm, some_arm];
|
||||||
|
|
||||||
|
@ -1418,6 +1441,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
||||||
head_span,
|
head_span,
|
||||||
hir::LangItem::IntoIterIntoIter,
|
hir::LangItem::IntoIterIntoIter,
|
||||||
arena_vec![self; head],
|
arena_vec![self; head],
|
||||||
|
None,
|
||||||
)
|
)
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -1473,6 +1497,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
||||||
unstable_span,
|
unstable_span,
|
||||||
hir::LangItem::TryTraitBranch,
|
hir::LangItem::TryTraitBranch,
|
||||||
arena_vec![self; sub_expr],
|
arena_vec![self; sub_expr],
|
||||||
|
None,
|
||||||
)
|
)
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -1629,8 +1654,10 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
||||||
span: Span,
|
span: Span,
|
||||||
lang_item: hir::LangItem,
|
lang_item: hir::LangItem,
|
||||||
args: &'hir [hir::Expr<'hir>],
|
args: &'hir [hir::Expr<'hir>],
|
||||||
|
hir_id: Option<hir::HirId>,
|
||||||
) -> hir::Expr<'hir> {
|
) -> hir::Expr<'hir> {
|
||||||
let path = self.arena.alloc(self.expr_lang_item_path(span, lang_item, ThinVec::new()));
|
let path =
|
||||||
|
self.arena.alloc(self.expr_lang_item_path(span, lang_item, ThinVec::new(), hir_id));
|
||||||
self.expr_call_mut(span, path, args)
|
self.expr_call_mut(span, path, args)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1639,8 +1666,9 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
||||||
span: Span,
|
span: Span,
|
||||||
lang_item: hir::LangItem,
|
lang_item: hir::LangItem,
|
||||||
args: &'hir [hir::Expr<'hir>],
|
args: &'hir [hir::Expr<'hir>],
|
||||||
|
hir_id: Option<hir::HirId>,
|
||||||
) -> &'hir hir::Expr<'hir> {
|
) -> &'hir hir::Expr<'hir> {
|
||||||
self.arena.alloc(self.expr_call_lang_item_fn_mut(span, lang_item, args))
|
self.arena.alloc(self.expr_call_lang_item_fn_mut(span, lang_item, args, hir_id))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn expr_lang_item_path(
|
fn expr_lang_item_path(
|
||||||
|
@ -1648,10 +1676,11 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
||||||
span: Span,
|
span: Span,
|
||||||
lang_item: hir::LangItem,
|
lang_item: hir::LangItem,
|
||||||
attrs: AttrVec,
|
attrs: AttrVec,
|
||||||
|
hir_id: Option<hir::HirId>,
|
||||||
) -> hir::Expr<'hir> {
|
) -> hir::Expr<'hir> {
|
||||||
self.expr(
|
self.expr(
|
||||||
span,
|
span,
|
||||||
hir::ExprKind::Path(hir::QPath::LangItem(lang_item, self.lower_span(span))),
|
hir::ExprKind::Path(hir::QPath::LangItem(lang_item, self.lower_span(span), hir_id)),
|
||||||
attrs,
|
attrs,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
|
@ -2127,21 +2127,21 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
||||||
|
|
||||||
fn pat_cf_continue(&mut self, span: Span, pat: &'hir hir::Pat<'hir>) -> &'hir hir::Pat<'hir> {
|
fn pat_cf_continue(&mut self, span: Span, pat: &'hir hir::Pat<'hir>) -> &'hir hir::Pat<'hir> {
|
||||||
let field = self.single_pat_field(span, pat);
|
let field = self.single_pat_field(span, pat);
|
||||||
self.pat_lang_item_variant(span, hir::LangItem::ControlFlowContinue, field)
|
self.pat_lang_item_variant(span, hir::LangItem::ControlFlowContinue, field, None)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn pat_cf_break(&mut self, span: Span, pat: &'hir hir::Pat<'hir>) -> &'hir hir::Pat<'hir> {
|
fn pat_cf_break(&mut self, span: Span, pat: &'hir hir::Pat<'hir>) -> &'hir hir::Pat<'hir> {
|
||||||
let field = self.single_pat_field(span, pat);
|
let field = self.single_pat_field(span, pat);
|
||||||
self.pat_lang_item_variant(span, hir::LangItem::ControlFlowBreak, field)
|
self.pat_lang_item_variant(span, hir::LangItem::ControlFlowBreak, field, None)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn pat_some(&mut self, span: Span, pat: &'hir hir::Pat<'hir>) -> &'hir hir::Pat<'hir> {
|
fn pat_some(&mut self, span: Span, pat: &'hir hir::Pat<'hir>) -> &'hir hir::Pat<'hir> {
|
||||||
let field = self.single_pat_field(span, pat);
|
let field = self.single_pat_field(span, pat);
|
||||||
self.pat_lang_item_variant(span, hir::LangItem::OptionSome, field)
|
self.pat_lang_item_variant(span, hir::LangItem::OptionSome, field, None)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn pat_none(&mut self, span: Span) -> &'hir hir::Pat<'hir> {
|
fn pat_none(&mut self, span: Span) -> &'hir hir::Pat<'hir> {
|
||||||
self.pat_lang_item_variant(span, hir::LangItem::OptionNone, &[])
|
self.pat_lang_item_variant(span, hir::LangItem::OptionNone, &[], None)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn single_pat_field(
|
fn single_pat_field(
|
||||||
|
@ -2164,8 +2164,9 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
||||||
span: Span,
|
span: Span,
|
||||||
lang_item: hir::LangItem,
|
lang_item: hir::LangItem,
|
||||||
fields: &'hir [hir::PatField<'hir>],
|
fields: &'hir [hir::PatField<'hir>],
|
||||||
|
hir_id: Option<hir::HirId>,
|
||||||
) -> &'hir hir::Pat<'hir> {
|
) -> &'hir hir::Pat<'hir> {
|
||||||
let qpath = hir::QPath::LangItem(lang_item, self.lower_span(span));
|
let qpath = hir::QPath::LangItem(lang_item, self.lower_span(span), hir_id);
|
||||||
self.pat(span, hir::PatKind::Struct(qpath, fields, false))
|
self.pat(span, hir::PatKind::Struct(qpath, fields, false))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1627,13 +1627,13 @@ pub fn is_range_literal(expr: &Expr<'_>) -> bool {
|
||||||
| LangItem::RangeFrom
|
| LangItem::RangeFrom
|
||||||
| LangItem::RangeFull
|
| LangItem::RangeFull
|
||||||
| LangItem::RangeToInclusive,
|
| LangItem::RangeToInclusive,
|
||||||
_,
|
..
|
||||||
)
|
)
|
||||||
),
|
),
|
||||||
|
|
||||||
// `..=` desugars into `::std::ops::RangeInclusive::new(...)`.
|
// `..=` desugars into `::std::ops::RangeInclusive::new(...)`.
|
||||||
ExprKind::Call(ref func, _) => {
|
ExprKind::Call(ref func, _) => {
|
||||||
matches!(func.kind, ExprKind::Path(QPath::LangItem(LangItem::RangeInclusiveNew, _)))
|
matches!(func.kind, ExprKind::Path(QPath::LangItem(LangItem::RangeInclusiveNew, ..)))
|
||||||
}
|
}
|
||||||
|
|
||||||
_ => false,
|
_ => false,
|
||||||
|
@ -1788,8 +1788,8 @@ pub enum QPath<'hir> {
|
||||||
/// the `X` and `Y` nodes each being a `TyKind::Path(QPath::TypeRelative(..))`.
|
/// the `X` and `Y` nodes each being a `TyKind::Path(QPath::TypeRelative(..))`.
|
||||||
TypeRelative(&'hir Ty<'hir>, &'hir PathSegment<'hir>),
|
TypeRelative(&'hir Ty<'hir>, &'hir PathSegment<'hir>),
|
||||||
|
|
||||||
/// Reference to a `#[lang = "foo"]` item.
|
/// Reference to a `#[lang = "foo"]` item. `HirId` of the inner expr.
|
||||||
LangItem(LangItem, Span),
|
LangItem(LangItem, Span, Option<HirId>),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'hir> QPath<'hir> {
|
impl<'hir> QPath<'hir> {
|
||||||
|
@ -1798,7 +1798,7 @@ impl<'hir> QPath<'hir> {
|
||||||
match *self {
|
match *self {
|
||||||
QPath::Resolved(_, path) => path.span,
|
QPath::Resolved(_, path) => path.span,
|
||||||
QPath::TypeRelative(qself, ps) => qself.span.to(ps.ident.span),
|
QPath::TypeRelative(qself, ps) => qself.span.to(ps.ident.span),
|
||||||
QPath::LangItem(_, span) => span,
|
QPath::LangItem(_, span, _) => span,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1808,7 +1808,7 @@ impl<'hir> QPath<'hir> {
|
||||||
match *self {
|
match *self {
|
||||||
QPath::Resolved(_, path) => path.span,
|
QPath::Resolved(_, path) => path.span,
|
||||||
QPath::TypeRelative(qself, _) => qself.span,
|
QPath::TypeRelative(qself, _) => qself.span,
|
||||||
QPath::LangItem(_, span) => span,
|
QPath::LangItem(_, span, _) => span,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1818,7 +1818,7 @@ impl<'hir> QPath<'hir> {
|
||||||
match *self {
|
match *self {
|
||||||
QPath::Resolved(_, path) => path.segments.last().unwrap().ident.span,
|
QPath::Resolved(_, path) => path.segments.last().unwrap().ident.span,
|
||||||
QPath::TypeRelative(_, segment) => segment.ident.span,
|
QPath::TypeRelative(_, segment) => segment.ident.span,
|
||||||
QPath::LangItem(_, span) => span,
|
QPath::LangItem(_, span, _) => span,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1731,7 +1731,7 @@ impl<'a> State<'a> {
|
||||||
colons_before_params,
|
colons_before_params,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
hir::QPath::LangItem(lang_item, span) => {
|
hir::QPath::LangItem(lang_item, span, _) => {
|
||||||
self.word("#[lang = \"");
|
self.word("#[lang = \"");
|
||||||
self.print_ident(Ident::new(lang_item.name(), span));
|
self.print_ident(Ident::new(lang_item.name(), span));
|
||||||
self.word("\"]");
|
self.word("\"]");
|
||||||
|
|
|
@ -52,7 +52,7 @@ impl<'tcx> LateLintPass<'tcx> for ArrayIntoIter {
|
||||||
if let hir::ExprKind::Call(path, [arg]) = &arg.kind {
|
if let hir::ExprKind::Call(path, [arg]) = &arg.kind {
|
||||||
if let hir::ExprKind::Path(hir::QPath::LangItem(
|
if let hir::ExprKind::Path(hir::QPath::LangItem(
|
||||||
hir::LangItem::IntoIterIntoIter,
|
hir::LangItem::IntoIterIntoIter,
|
||||||
_,
|
..,
|
||||||
)) = &path.kind
|
)) = &path.kind
|
||||||
{
|
{
|
||||||
self.for_expr_span = arg.span;
|
self.for_expr_span = arg.span;
|
||||||
|
|
|
@ -348,7 +348,7 @@ pub enum ObligationCauseCode<'tcx> {
|
||||||
/// If `X` is the concrete type of an opaque type `impl Y`, then `X` must implement `Y`
|
/// If `X` is the concrete type of an opaque type `impl Y`, then `X` must implement `Y`
|
||||||
OpaqueType,
|
OpaqueType,
|
||||||
|
|
||||||
AwaitableExpr,
|
AwaitableExpr(Option<hir::HirId>),
|
||||||
|
|
||||||
ForLoopIterator,
|
ForLoopIterator,
|
||||||
|
|
||||||
|
|
|
@ -286,7 +286,7 @@ impl<'hir> Sig for hir::Ty<'hir> {
|
||||||
refs: vec![SigElement { id, start, end }],
|
refs: vec![SigElement { id, start, end }],
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
hir::TyKind::Path(hir::QPath::LangItem(lang_item, _)) => {
|
hir::TyKind::Path(hir::QPath::LangItem(lang_item, _, _)) => {
|
||||||
Ok(text_sig(format!("#[lang = \"{}\"]", lang_item.name())))
|
Ok(text_sig(format!("#[lang = \"{}\"]", lang_item.name())))
|
||||||
}
|
}
|
||||||
hir::TyKind::TraitObject(bounds, ..) => {
|
hir::TyKind::TraitObject(bounds, ..) => {
|
||||||
|
|
|
@ -886,7 +886,7 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
|
||||||
) {
|
) {
|
||||||
let span = obligation.cause.span;
|
let span = obligation.cause.span;
|
||||||
|
|
||||||
if let ObligationCauseCode::AwaitableExpr = obligation.cause.code {
|
if let ObligationCauseCode::AwaitableExpr(hir_id) = obligation.cause.code {
|
||||||
// FIXME: use `obligation.predicate.kind()...trait_ref.self_ty()` to see if we have `()`
|
// FIXME: use `obligation.predicate.kind()...trait_ref.self_ty()` to see if we have `()`
|
||||||
// and if not maybe suggest doing something else? If we kept the expression around we
|
// and if not maybe suggest doing something else? If we kept the expression around we
|
||||||
// could also check if it is an fn call (very likely) and suggest changing *that*, if
|
// could also check if it is an fn call (very likely) and suggest changing *that*, if
|
||||||
|
@ -897,6 +897,40 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
|
||||||
String::new(),
|
String::new(),
|
||||||
Applicability::MachineApplicable,
|
Applicability::MachineApplicable,
|
||||||
);
|
);
|
||||||
|
// FIXME: account for associated `async fn`s.
|
||||||
|
let hir = self.tcx.hir();
|
||||||
|
if let Some(node) = hir_id.and_then(|hir_id| hir.find(hir_id)) {
|
||||||
|
if let hir::Node::Expr(hir::Expr {
|
||||||
|
span, kind: hir::ExprKind::Call(base, _), ..
|
||||||
|
}) = node
|
||||||
|
{
|
||||||
|
if let ty::PredicateKind::Trait(pred) =
|
||||||
|
obligation.predicate.kind().skip_binder()
|
||||||
|
{
|
||||||
|
err.span_label(*span, &format!("this call returns `{}`", pred.self_ty()));
|
||||||
|
}
|
||||||
|
if let Some(typeck_results) =
|
||||||
|
self.in_progress_typeck_results.map(|t| t.borrow())
|
||||||
|
{
|
||||||
|
let ty = typeck_results.expr_ty_adjusted(base);
|
||||||
|
if let ty::FnDef(def_id, _substs) = ty.kind() {
|
||||||
|
if let Some(hir::Node::Item(hir::Item { span, ident, .. })) =
|
||||||
|
hir.get_if_local(*def_id)
|
||||||
|
{
|
||||||
|
err.span_suggestion_verbose(
|
||||||
|
span.shrink_to_lo(),
|
||||||
|
&format!(
|
||||||
|
"alternatively, consider making `fn {}` asynchronous",
|
||||||
|
ident
|
||||||
|
),
|
||||||
|
"async ".to_string(),
|
||||||
|
Applicability::MaybeIncorrect,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1962,7 +1996,7 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
|
||||||
| ObligationCauseCode::ReturnType
|
| ObligationCauseCode::ReturnType
|
||||||
| ObligationCauseCode::ReturnValue(_)
|
| ObligationCauseCode::ReturnValue(_)
|
||||||
| ObligationCauseCode::BlockTailExpression(_)
|
| ObligationCauseCode::BlockTailExpression(_)
|
||||||
| ObligationCauseCode::AwaitableExpr
|
| ObligationCauseCode::AwaitableExpr(_)
|
||||||
| ObligationCauseCode::ForLoopIterator
|
| ObligationCauseCode::ForLoopIterator
|
||||||
| ObligationCauseCode::QuestionMark
|
| ObligationCauseCode::QuestionMark
|
||||||
| ObligationCauseCode::LetElse => {}
|
| ObligationCauseCode::LetElse => {}
|
||||||
|
|
|
@ -2362,7 +2362,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
|
||||||
.map(|(ty, _, _)| ty)
|
.map(|(ty, _, _)| ty)
|
||||||
.unwrap_or_else(|_| tcx.ty_error())
|
.unwrap_or_else(|_| tcx.ty_error())
|
||||||
}
|
}
|
||||||
hir::TyKind::Path(hir::QPath::LangItem(lang_item, span)) => {
|
hir::TyKind::Path(hir::QPath::LangItem(lang_item, span, _)) => {
|
||||||
let def_id = tcx.require_lang_item(lang_item, Some(span));
|
let def_id = tcx.require_lang_item(lang_item, Some(span));
|
||||||
let (substs, _) = self.create_substs_for_ast_path(
|
let (substs, _) = self.create_substs_for_ast_path(
|
||||||
span,
|
span,
|
||||||
|
|
|
@ -277,8 +277,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||||
ExprKind::AddrOf(kind, mutbl, oprnd) => {
|
ExprKind::AddrOf(kind, mutbl, oprnd) => {
|
||||||
self.check_expr_addr_of(kind, mutbl, oprnd, expected, expr)
|
self.check_expr_addr_of(kind, mutbl, oprnd, expected, expr)
|
||||||
}
|
}
|
||||||
ExprKind::Path(QPath::LangItem(lang_item, _)) => {
|
ExprKind::Path(QPath::LangItem(lang_item, _, hir_id)) => {
|
||||||
self.check_lang_item_path(lang_item, expr)
|
self.check_lang_item_path(lang_item, expr, hir_id)
|
||||||
}
|
}
|
||||||
ExprKind::Path(ref qpath) => self.check_expr_path(qpath, expr, &[]),
|
ExprKind::Path(ref qpath) => self.check_expr_path(qpath, expr, &[]),
|
||||||
ExprKind::InlineAsm(asm) => self.check_expr_asm(asm),
|
ExprKind::InlineAsm(asm) => self.check_expr_asm(asm),
|
||||||
|
@ -498,8 +498,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||||
&self,
|
&self,
|
||||||
lang_item: hir::LangItem,
|
lang_item: hir::LangItem,
|
||||||
expr: &'tcx hir::Expr<'tcx>,
|
expr: &'tcx hir::Expr<'tcx>,
|
||||||
|
hir_id: Option<hir::HirId>,
|
||||||
) -> Ty<'tcx> {
|
) -> Ty<'tcx> {
|
||||||
self.resolve_lang_item_path(lang_item, expr.span, expr.hir_id).1
|
self.resolve_lang_item_path(lang_item, expr.span, expr.hir_id, hir_id).1
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn check_expr_path(
|
pub(crate) fn check_expr_path(
|
||||||
|
|
|
@ -791,6 +791,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||||
lang_item: hir::LangItem,
|
lang_item: hir::LangItem,
|
||||||
span: Span,
|
span: Span,
|
||||||
hir_id: hir::HirId,
|
hir_id: hir::HirId,
|
||||||
|
expr_hir_id: Option<hir::HirId>,
|
||||||
) -> (Res, Ty<'tcx>) {
|
) -> (Res, Ty<'tcx>) {
|
||||||
let def_id = self.tcx.require_lang_item(lang_item, Some(span));
|
let def_id = self.tcx.require_lang_item(lang_item, Some(span));
|
||||||
let def_kind = self.tcx.def_kind(def_id);
|
let def_kind = self.tcx.def_kind(def_id);
|
||||||
|
@ -809,7 +810,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||||
def_id,
|
def_id,
|
||||||
&substs,
|
&substs,
|
||||||
match lang_item {
|
match lang_item {
|
||||||
hir::LangItem::FuturePoll => ObligationCauseCode::AwaitableExpr,
|
hir::LangItem::FuturePoll => ObligationCauseCode::AwaitableExpr(expr_hir_id),
|
||||||
hir::LangItem::IteratorNext | hir::LangItem::IntoIterIntoIter => {
|
hir::LangItem::IteratorNext | hir::LangItem::IntoIterIntoIter => {
|
||||||
ObligationCauseCode::ForLoopIterator
|
ObligationCauseCode::ForLoopIterator
|
||||||
}
|
}
|
||||||
|
|
|
@ -938,8 +938,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||||
|
|
||||||
(result.map_or(Res::Err, |(kind, def_id)| Res::Def(kind, def_id)), ty)
|
(result.map_or(Res::Err, |(kind, def_id)| Res::Def(kind, def_id)), ty)
|
||||||
}
|
}
|
||||||
QPath::LangItem(lang_item, span) => {
|
QPath::LangItem(lang_item, span, id) => {
|
||||||
self.resolve_lang_item_path(lang_item, span, hir_id)
|
self.resolve_lang_item_path(lang_item, span, hir_id, id)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
14
src/test/ui/async-await/unnecessary-await.rs
Normal file
14
src/test/ui/async-await/unnecessary-await.rs
Normal file
|
@ -0,0 +1,14 @@
|
||||||
|
// edition:2018
|
||||||
|
|
||||||
|
async fn foo () { }
|
||||||
|
fn bar () -> impl std::future::Future { async {} }
|
||||||
|
fn boo () {}
|
||||||
|
|
||||||
|
async fn baz() -> std::io::Result<()> {
|
||||||
|
foo().await;
|
||||||
|
boo().await; //~ ERROR `()` is not a future
|
||||||
|
bar().await;
|
||||||
|
std::io::Result::Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {}
|
22
src/test/ui/async-await/unnecessary-await.stderr
Normal file
22
src/test/ui/async-await/unnecessary-await.stderr
Normal file
|
@ -0,0 +1,22 @@
|
||||||
|
error[E0277]: `()` is not a future
|
||||||
|
--> $DIR/unnecessary-await.rs:9:10
|
||||||
|
|
|
||||||
|
LL | boo().await;
|
||||||
|
| -----^^^^^^ `()` is not a future
|
||||||
|
| |
|
||||||
|
| this call returns `()`
|
||||||
|
|
|
||||||
|
= help: the trait `Future` is not implemented for `()`
|
||||||
|
help: do not `.await` the expression
|
||||||
|
|
|
||||||
|
LL - boo().await;
|
||||||
|
LL + boo();
|
||||||
|
|
|
||||||
|
help: alternatively, consider making `fn boo` asynchronous
|
||||||
|
|
|
||||||
|
LL | async fn boo () {}
|
||||||
|
| +++++
|
||||||
|
|
||||||
|
error: aborting due to previous error
|
||||||
|
|
||||||
|
For more information about this error, try `rustc --explain E0277`.
|
Loading…
Add table
Add a link
Reference in a new issue