Skip to content

Commit f640438

Browse files
committed
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`.
1 parent d45e030 commit f640438

File tree

14 files changed

+138
-36
lines changed

14 files changed

+138
-36
lines changed

compiler/rustc_ast_lowering/src/expr.rs

Lines changed: 40 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -479,8 +479,12 @@ impl<'hir> LoweringContext<'_, 'hir> {
479479
expr: &'hir hir::Expr<'hir>,
480480
overall_span: Span,
481481
) -> &'hir hir::Expr<'hir> {
482-
let constructor =
483-
self.arena.alloc(self.expr_lang_item_path(method_span, lang_item, ThinVec::new()));
482+
let constructor = self.arena.alloc(self.expr_lang_item_path(
483+
method_span,
484+
lang_item,
485+
ThinVec::new(),
486+
None,
487+
));
484488
self.expr_call(overall_span, constructor, std::slice::from_ref(expr))
485489
}
486490

@@ -584,8 +588,12 @@ impl<'hir> LoweringContext<'_, 'hir> {
584588
// `future::from_generator`:
585589
let unstable_span =
586590
self.mark_span_with_reason(DesugaringKind::Async, span, self.allow_gen_future.clone());
587-
let gen_future =
588-
self.expr_lang_item_path(unstable_span, hir::LangItem::FromGenerator, ThinVec::new());
591+
let gen_future = self.expr_lang_item_path(
592+
unstable_span,
593+
hir::LangItem::FromGenerator,
594+
ThinVec::new(),
595+
None,
596+
);
589597

590598
// `future::from_generator(generator)`:
591599
hir::ExprKind::Call(self.arena.alloc(gen_future), arena_vec![self; generator])
@@ -657,16 +665,19 @@ impl<'hir> LoweringContext<'_, 'hir> {
657665
span,
658666
hir::LangItem::PinNewUnchecked,
659667
arena_vec![self; ref_mut_pinned],
668+
Some(expr.hir_id),
660669
);
661670
let get_context = self.expr_call_lang_item_fn_mut(
662671
gen_future_span,
663672
hir::LangItem::GetContext,
664673
arena_vec![self; task_context],
674+
Some(expr.hir_id),
665675
);
666676
let call = self.expr_call_lang_item_fn(
667677
span,
668678
hir::LangItem::FuturePoll,
669679
arena_vec![self; new_unchecked, get_context],
680+
Some(expr.hir_id),
670681
);
671682
self.arena.alloc(self.expr_unsafe(call))
672683
};
@@ -679,7 +690,12 @@ impl<'hir> LoweringContext<'_, 'hir> {
679690
let (x_pat, x_pat_hid) = self.pat_ident(span, x_ident);
680691
let x_expr = self.expr_ident(span, x_ident, x_pat_hid);
681692
let ready_field = self.single_pat_field(span, x_pat);
682-
let ready_pat = self.pat_lang_item_variant(span, hir::LangItem::PollReady, ready_field);
693+
let ready_pat = self.pat_lang_item_variant(
694+
span,
695+
hir::LangItem::PollReady,
696+
ready_field,
697+
Some(expr.hir_id),
698+
);
683699
let break_x = self.with_loop_scope(loop_node_id, move |this| {
684700
let expr_break =
685701
hir::ExprKind::Break(this.lower_loop_destination(None), Some(x_expr));
@@ -690,7 +706,12 @@ impl<'hir> LoweringContext<'_, 'hir> {
690706

691707
// `::std::task::Poll::Pending => {}`
692708
let pending_arm = {
693-
let pending_pat = self.pat_lang_item_variant(span, hir::LangItem::PollPending, &[]);
709+
let pending_pat = self.pat_lang_item_variant(
710+
span,
711+
hir::LangItem::PollPending,
712+
&[],
713+
Some(expr.hir_id),
714+
);
694715
let empty_block = self.expr_block_empty(span);
695716
self.arm(pending_pat, empty_block)
696717
};
@@ -1161,7 +1182,8 @@ impl<'hir> LoweringContext<'_, 'hir> {
11611182
fn lower_expr_range_closed(&mut self, span: Span, e1: &Expr, e2: &Expr) -> hir::ExprKind<'hir> {
11621183
let e1 = self.lower_expr_mut(e1);
11631184
let e2 = self.lower_expr_mut(e2);
1164-
let fn_path = hir::QPath::LangItem(hir::LangItem::RangeInclusiveNew, self.lower_span(span));
1185+
let fn_path =
1186+
hir::QPath::LangItem(hir::LangItem::RangeInclusiveNew, self.lower_span(span), None);
11651187
let fn_expr =
11661188
self.arena.alloc(self.expr(span, hir::ExprKind::Path(fn_path), ThinVec::new()));
11671189
hir::ExprKind::Call(fn_expr, arena_vec![self; e1, e2])
@@ -1195,7 +1217,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
11951217
);
11961218

11971219
hir::ExprKind::Struct(
1198-
self.arena.alloc(hir::QPath::LangItem(lang_item, self.lower_span(span))),
1220+
self.arena.alloc(hir::QPath::LangItem(lang_item, self.lower_span(span), None)),
11991221
fields,
12001222
None,
12011223
)
@@ -1390,6 +1412,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
13901412
head_span,
13911413
hir::LangItem::IteratorNext,
13921414
arena_vec![self; ref_mut_iter],
1415+
None,
13931416
);
13941417
let arms = arena_vec![self; none_arm, some_arm];
13951418

@@ -1418,6 +1441,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
14181441
head_span,
14191442
hir::LangItem::IntoIterIntoIter,
14201443
arena_vec![self; head],
1444+
None,
14211445
)
14221446
};
14231447

@@ -1473,6 +1497,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
14731497
unstable_span,
14741498
hir::LangItem::TryTraitBranch,
14751499
arena_vec![self; sub_expr],
1500+
None,
14761501
)
14771502
};
14781503

@@ -1629,8 +1654,10 @@ impl<'hir> LoweringContext<'_, 'hir> {
16291654
span: Span,
16301655
lang_item: hir::LangItem,
16311656
args: &'hir [hir::Expr<'hir>],
1657+
hir_id: Option<hir::HirId>,
16321658
) -> hir::Expr<'hir> {
1633-
let path = self.arena.alloc(self.expr_lang_item_path(span, lang_item, ThinVec::new()));
1659+
let path =
1660+
self.arena.alloc(self.expr_lang_item_path(span, lang_item, ThinVec::new(), hir_id));
16341661
self.expr_call_mut(span, path, args)
16351662
}
16361663

@@ -1639,19 +1666,21 @@ impl<'hir> LoweringContext<'_, 'hir> {
16391666
span: Span,
16401667
lang_item: hir::LangItem,
16411668
args: &'hir [hir::Expr<'hir>],
1669+
hir_id: Option<hir::HirId>,
16421670
) -> &'hir hir::Expr<'hir> {
1643-
self.arena.alloc(self.expr_call_lang_item_fn_mut(span, lang_item, args))
1671+
self.arena.alloc(self.expr_call_lang_item_fn_mut(span, lang_item, args, hir_id))
16441672
}
16451673

16461674
fn expr_lang_item_path(
16471675
&mut self,
16481676
span: Span,
16491677
lang_item: hir::LangItem,
16501678
attrs: AttrVec,
1679+
hir_id: Option<hir::HirId>,
16511680
) -> hir::Expr<'hir> {
16521681
self.expr(
16531682
span,
1654-
hir::ExprKind::Path(hir::QPath::LangItem(lang_item, self.lower_span(span))),
1683+
hir::ExprKind::Path(hir::QPath::LangItem(lang_item, self.lower_span(span), hir_id)),
16551684
attrs,
16561685
)
16571686
}

compiler/rustc_ast_lowering/src/lib.rs

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2127,21 +2127,21 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
21272127

21282128
fn pat_cf_continue(&mut self, span: Span, pat: &'hir hir::Pat<'hir>) -> &'hir hir::Pat<'hir> {
21292129
let field = self.single_pat_field(span, pat);
2130-
self.pat_lang_item_variant(span, hir::LangItem::ControlFlowContinue, field)
2130+
self.pat_lang_item_variant(span, hir::LangItem::ControlFlowContinue, field, None)
21312131
}
21322132

21332133
fn pat_cf_break(&mut self, span: Span, pat: &'hir hir::Pat<'hir>) -> &'hir hir::Pat<'hir> {
21342134
let field = self.single_pat_field(span, pat);
2135-
self.pat_lang_item_variant(span, hir::LangItem::ControlFlowBreak, field)
2135+
self.pat_lang_item_variant(span, hir::LangItem::ControlFlowBreak, field, None)
21362136
}
21372137

21382138
fn pat_some(&mut self, span: Span, pat: &'hir hir::Pat<'hir>) -> &'hir hir::Pat<'hir> {
21392139
let field = self.single_pat_field(span, pat);
2140-
self.pat_lang_item_variant(span, hir::LangItem::OptionSome, field)
2140+
self.pat_lang_item_variant(span, hir::LangItem::OptionSome, field, None)
21412141
}
21422142

21432143
fn pat_none(&mut self, span: Span) -> &'hir hir::Pat<'hir> {
2144-
self.pat_lang_item_variant(span, hir::LangItem::OptionNone, &[])
2144+
self.pat_lang_item_variant(span, hir::LangItem::OptionNone, &[], None)
21452145
}
21462146

21472147
fn single_pat_field(
@@ -2164,8 +2164,9 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
21642164
span: Span,
21652165
lang_item: hir::LangItem,
21662166
fields: &'hir [hir::PatField<'hir>],
2167+
hir_id: Option<hir::HirId>,
21672168
) -> &'hir hir::Pat<'hir> {
2168-
let qpath = hir::QPath::LangItem(lang_item, self.lower_span(span));
2169+
let qpath = hir::QPath::LangItem(lang_item, self.lower_span(span), hir_id);
21692170
self.pat(span, hir::PatKind::Struct(qpath, fields, false))
21702171
}
21712172

compiler/rustc_hir/src/hir.rs

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1627,13 +1627,13 @@ pub fn is_range_literal(expr: &Expr<'_>) -> bool {
16271627
| LangItem::RangeFrom
16281628
| LangItem::RangeFull
16291629
| LangItem::RangeToInclusive,
1630-
_,
1630+
..
16311631
)
16321632
),
16331633

16341634
// `..=` desugars into `::std::ops::RangeInclusive::new(...)`.
16351635
ExprKind::Call(ref func, _) => {
1636-
matches!(func.kind, ExprKind::Path(QPath::LangItem(LangItem::RangeInclusiveNew, _)))
1636+
matches!(func.kind, ExprKind::Path(QPath::LangItem(LangItem::RangeInclusiveNew, ..)))
16371637
}
16381638

16391639
_ => false,
@@ -1788,8 +1788,8 @@ pub enum QPath<'hir> {
17881788
/// the `X` and `Y` nodes each being a `TyKind::Path(QPath::TypeRelative(..))`.
17891789
TypeRelative(&'hir Ty<'hir>, &'hir PathSegment<'hir>),
17901790

1791-
/// Reference to a `#[lang = "foo"]` item.
1792-
LangItem(LangItem, Span),
1791+
/// Reference to a `#[lang = "foo"]` item. `HirId` of the inner expr.
1792+
LangItem(LangItem, Span, Option<HirId>),
17931793
}
17941794

17951795
impl<'hir> QPath<'hir> {
@@ -1798,7 +1798,7 @@ impl<'hir> QPath<'hir> {
17981798
match *self {
17991799
QPath::Resolved(_, path) => path.span,
18001800
QPath::TypeRelative(qself, ps) => qself.span.to(ps.ident.span),
1801-
QPath::LangItem(_, span) => span,
1801+
QPath::LangItem(_, span, _) => span,
18021802
}
18031803
}
18041804

@@ -1808,7 +1808,7 @@ impl<'hir> QPath<'hir> {
18081808
match *self {
18091809
QPath::Resolved(_, path) => path.span,
18101810
QPath::TypeRelative(qself, _) => qself.span,
1811-
QPath::LangItem(_, span) => span,
1811+
QPath::LangItem(_, span, _) => span,
18121812
}
18131813
}
18141814

@@ -1818,7 +1818,7 @@ impl<'hir> QPath<'hir> {
18181818
match *self {
18191819
QPath::Resolved(_, path) => path.segments.last().unwrap().ident.span,
18201820
QPath::TypeRelative(_, segment) => segment.ident.span,
1821-
QPath::LangItem(_, span) => span,
1821+
QPath::LangItem(_, span, _) => span,
18221822
}
18231823
}
18241824
}

compiler/rustc_hir_pretty/src/lib.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1731,7 +1731,7 @@ impl<'a> State<'a> {
17311731
colons_before_params,
17321732
)
17331733
}
1734-
hir::QPath::LangItem(lang_item, span) => {
1734+
hir::QPath::LangItem(lang_item, span, _) => {
17351735
self.word("#[lang = \"");
17361736
self.print_ident(Ident::new(lang_item.name(), span));
17371737
self.word("\"]");

compiler/rustc_lint/src/array_into_iter.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@ impl<'tcx> LateLintPass<'tcx> for ArrayIntoIter {
5252
if let hir::ExprKind::Call(path, [arg]) = &arg.kind {
5353
if let hir::ExprKind::Path(hir::QPath::LangItem(
5454
hir::LangItem::IntoIterIntoIter,
55-
_,
55+
..,
5656
)) = &path.kind
5757
{
5858
self.for_expr_span = arg.span;

compiler/rustc_middle/src/traits/mod.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -348,7 +348,7 @@ pub enum ObligationCauseCode<'tcx> {
348348
/// If `X` is the concrete type of an opaque type `impl Y`, then `X` must implement `Y`
349349
OpaqueType,
350350

351-
AwaitableExpr,
351+
AwaitableExpr(Option<hir::HirId>),
352352

353353
ForLoopIterator,
354354

compiler/rustc_save_analysis/src/sig.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -286,7 +286,7 @@ impl<'hir> Sig for hir::Ty<'hir> {
286286
refs: vec![SigElement { id, start, end }],
287287
})
288288
}
289-
hir::TyKind::Path(hir::QPath::LangItem(lang_item, _)) => {
289+
hir::TyKind::Path(hir::QPath::LangItem(lang_item, _, _)) => {
290290
Ok(text_sig(format!("#[lang = \"{}\"]", lang_item.name())))
291291
}
292292
hir::TyKind::TraitObject(bounds, ..) => {

compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs

Lines changed: 36 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -886,7 +886,7 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
886886
) {
887887
let span = obligation.cause.span;
888888

889-
if let ObligationCauseCode::AwaitableExpr = obligation.cause.code {
889+
if let ObligationCauseCode::AwaitableExpr(hir_id) = obligation.cause.code {
890890
// FIXME: use `obligation.predicate.kind()...trait_ref.self_ty()` to see if we have `()`
891891
// and if not maybe suggest doing something else? If we kept the expression around we
892892
// 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> {
897897
String::new(),
898898
Applicability::MachineApplicable,
899899
);
900+
// FIXME: account for associated `async fn`s.
901+
let hir = self.tcx.hir();
902+
if let Some(node) = hir_id.and_then(|hir_id| hir.find(hir_id)) {
903+
if let hir::Node::Expr(hir::Expr {
904+
span, kind: hir::ExprKind::Call(base, _), ..
905+
}) = node
906+
{
907+
if let ty::PredicateKind::Trait(pred) =
908+
obligation.predicate.kind().skip_binder()
909+
{
910+
err.span_label(*span, &format!("this call returns `{}`", pred.self_ty()));
911+
}
912+
if let Some(typeck_results) =
913+
self.in_progress_typeck_results.map(|t| t.borrow())
914+
{
915+
let ty = typeck_results.expr_ty_adjusted(base);
916+
if let ty::FnDef(def_id, _substs) = ty.kind() {
917+
if let Some(hir::Node::Item(hir::Item { span, ident, .. })) =
918+
hir.get_if_local(*def_id)
919+
{
920+
err.span_suggestion_verbose(
921+
span.shrink_to_lo(),
922+
&format!(
923+
"alternatively, consider making `fn {}` asynchronous",
924+
ident
925+
),
926+
"async ".to_string(),
927+
Applicability::MaybeIncorrect,
928+
);
929+
}
930+
}
931+
}
932+
}
933+
}
900934
}
901935
}
902936

@@ -1962,7 +1996,7 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
19621996
| ObligationCauseCode::ReturnType
19631997
| ObligationCauseCode::ReturnValue(_)
19641998
| ObligationCauseCode::BlockTailExpression(_)
1965-
| ObligationCauseCode::AwaitableExpr
1999+
| ObligationCauseCode::AwaitableExpr(_)
19662000
| ObligationCauseCode::ForLoopIterator
19672001
| ObligationCauseCode::QuestionMark
19682002
| ObligationCauseCode::LetElse => {}

compiler/rustc_typeck/src/astconv/mod.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2362,7 +2362,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
23622362
.map(|(ty, _, _)| ty)
23632363
.unwrap_or_else(|_| tcx.ty_error())
23642364
}
2365-
hir::TyKind::Path(hir::QPath::LangItem(lang_item, span)) => {
2365+
hir::TyKind::Path(hir::QPath::LangItem(lang_item, span, _)) => {
23662366
let def_id = tcx.require_lang_item(lang_item, Some(span));
23672367
let (substs, _) = self.create_substs_for_ast_path(
23682368
span,

compiler/rustc_typeck/src/check/expr.rs

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -277,8 +277,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
277277
ExprKind::AddrOf(kind, mutbl, oprnd) => {
278278
self.check_expr_addr_of(kind, mutbl, oprnd, expected, expr)
279279
}
280-
ExprKind::Path(QPath::LangItem(lang_item, _)) => {
281-
self.check_lang_item_path(lang_item, expr)
280+
ExprKind::Path(QPath::LangItem(lang_item, _, hir_id)) => {
281+
self.check_lang_item_path(lang_item, expr, hir_id)
282282
}
283283
ExprKind::Path(ref qpath) => self.check_expr_path(qpath, expr, &[]),
284284
ExprKind::InlineAsm(asm) => self.check_expr_asm(asm),
@@ -498,8 +498,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
498498
&self,
499499
lang_item: hir::LangItem,
500500
expr: &'tcx hir::Expr<'tcx>,
501+
hir_id: Option<hir::HirId>,
501502
) -> Ty<'tcx> {
502-
self.resolve_lang_item_path(lang_item, expr.span, expr.hir_id).1
503+
self.resolve_lang_item_path(lang_item, expr.span, expr.hir_id, hir_id).1
503504
}
504505

505506
pub(crate) fn check_expr_path(

compiler/rustc_typeck/src/check/fn_ctxt/_impl.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -791,6 +791,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
791791
lang_item: hir::LangItem,
792792
span: Span,
793793
hir_id: hir::HirId,
794+
expr_hir_id: Option<hir::HirId>,
794795
) -> (Res, Ty<'tcx>) {
795796
let def_id = self.tcx.require_lang_item(lang_item, Some(span));
796797
let def_kind = self.tcx.def_kind(def_id);
@@ -809,7 +810,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
809810
def_id,
810811
&substs,
811812
match lang_item {
812-
hir::LangItem::FuturePoll => ObligationCauseCode::AwaitableExpr,
813+
hir::LangItem::FuturePoll => ObligationCauseCode::AwaitableExpr(expr_hir_id),
813814
hir::LangItem::IteratorNext | hir::LangItem::IntoIterIntoIter => {
814815
ObligationCauseCode::ForLoopIterator
815816
}

0 commit comments

Comments
 (0)