Make closures carry their own ClosureKind, rather than deducing what it is from movability
This commit is contained in:
parent
981fc6e174
commit
909dd864f1
@ -669,11 +669,10 @@ pub(super) fn make_async_expr(
|
||||
};
|
||||
let params = arena_vec![self; param];
|
||||
|
||||
let coroutine_kind =
|
||||
hir::CoroutineKind::Desugared(hir::CoroutineDesugaring::Async, async_coroutine_source);
|
||||
let body = self.lower_body(move |this| {
|
||||
this.coroutine_kind = Some(hir::CoroutineKind::Desugared(
|
||||
hir::CoroutineDesugaring::Async,
|
||||
async_coroutine_source,
|
||||
));
|
||||
this.coroutine_kind = Some(coroutine_kind);
|
||||
|
||||
let old_ctx = this.task_context;
|
||||
this.task_context = Some(task_context_hid);
|
||||
@ -692,7 +691,7 @@ pub(super) fn make_async_expr(
|
||||
body,
|
||||
fn_decl_span: self.lower_span(span),
|
||||
fn_arg_span: None,
|
||||
movability: Some(hir::Movability::Static),
|
||||
kind: hir::ClosureKind::Coroutine(coroutine_kind, Movability::Static),
|
||||
constness: hir::Constness::NotConst,
|
||||
}))
|
||||
}
|
||||
@ -726,11 +725,10 @@ pub(super) fn make_gen_expr(
|
||||
lifetime_elision_allowed: false,
|
||||
});
|
||||
|
||||
let coroutine_kind =
|
||||
hir::CoroutineKind::Desugared(hir::CoroutineDesugaring::Gen, coroutine_source);
|
||||
let body = self.lower_body(move |this| {
|
||||
this.coroutine_kind = Some(hir::CoroutineKind::Desugared(
|
||||
hir::CoroutineDesugaring::Gen,
|
||||
coroutine_source,
|
||||
));
|
||||
this.coroutine_kind = Some(coroutine_kind);
|
||||
|
||||
let res = body(this);
|
||||
(&[], res)
|
||||
@ -746,7 +744,7 @@ pub(super) fn make_gen_expr(
|
||||
body,
|
||||
fn_decl_span: self.lower_span(span),
|
||||
fn_arg_span: None,
|
||||
movability: Some(Movability::Movable),
|
||||
kind: hir::ClosureKind::Coroutine(coroutine_kind, Movability::Movable),
|
||||
constness: hir::Constness::NotConst,
|
||||
}))
|
||||
}
|
||||
@ -807,11 +805,12 @@ pub(super) fn make_async_gen_expr(
|
||||
};
|
||||
let params = arena_vec![self; param];
|
||||
|
||||
let coroutine_kind = hir::CoroutineKind::Desugared(
|
||||
hir::CoroutineDesugaring::AsyncGen,
|
||||
async_coroutine_source,
|
||||
);
|
||||
let body = self.lower_body(move |this| {
|
||||
this.coroutine_kind = Some(hir::CoroutineKind::Desugared(
|
||||
hir::CoroutineDesugaring::AsyncGen,
|
||||
async_coroutine_source,
|
||||
));
|
||||
this.coroutine_kind = Some(coroutine_kind);
|
||||
|
||||
let old_ctx = this.task_context;
|
||||
this.task_context = Some(task_context_hid);
|
||||
@ -830,7 +829,7 @@ pub(super) fn make_async_gen_expr(
|
||||
body,
|
||||
fn_decl_span: self.lower_span(span),
|
||||
fn_arg_span: None,
|
||||
movability: Some(hir::Movability::Static),
|
||||
kind: hir::ClosureKind::Coroutine(coroutine_kind, Movability::Static),
|
||||
constness: hir::Constness::NotConst,
|
||||
}))
|
||||
}
|
||||
@ -1087,7 +1086,7 @@ fn lower_expr_closure(
|
||||
) -> hir::ExprKind<'hir> {
|
||||
let (binder_clause, generic_params) = self.lower_closure_binder(binder);
|
||||
|
||||
let (body_id, coroutine_option) = self.with_new_scopes(fn_decl_span, move |this| {
|
||||
let (body_id, closure_kind) = self.with_new_scopes(fn_decl_span, move |this| {
|
||||
let mut coroutine_kind = None;
|
||||
let body_id = this.lower_fn_body(decl, |this| {
|
||||
let e = this.lower_expr_mut(body);
|
||||
@ -1095,7 +1094,7 @@ fn lower_expr_closure(
|
||||
e
|
||||
});
|
||||
let coroutine_option =
|
||||
this.coroutine_movability_for_fn(decl, fn_decl_span, coroutine_kind, movability);
|
||||
this.closure_movability_for_fn(decl, fn_decl_span, coroutine_kind, movability);
|
||||
(body_id, coroutine_option)
|
||||
});
|
||||
|
||||
@ -1112,26 +1111,26 @@ fn lower_expr_closure(
|
||||
body: body_id,
|
||||
fn_decl_span: self.lower_span(fn_decl_span),
|
||||
fn_arg_span: Some(self.lower_span(fn_arg_span)),
|
||||
movability: coroutine_option,
|
||||
kind: closure_kind,
|
||||
constness: self.lower_constness(constness),
|
||||
});
|
||||
|
||||
hir::ExprKind::Closure(c)
|
||||
}
|
||||
|
||||
fn coroutine_movability_for_fn(
|
||||
fn closure_movability_for_fn(
|
||||
&mut self,
|
||||
decl: &FnDecl,
|
||||
fn_decl_span: Span,
|
||||
coroutine_kind: Option<hir::CoroutineKind>,
|
||||
movability: Movability,
|
||||
) -> Option<hir::Movability> {
|
||||
) -> hir::ClosureKind {
|
||||
match coroutine_kind {
|
||||
Some(hir::CoroutineKind::Coroutine) => {
|
||||
if decl.inputs.len() > 1 {
|
||||
self.tcx.sess.emit_err(CoroutineTooManyParameters { fn_decl_span });
|
||||
}
|
||||
Some(movability)
|
||||
hir::ClosureKind::Coroutine(hir::CoroutineKind::Coroutine, movability)
|
||||
}
|
||||
Some(
|
||||
hir::CoroutineKind::Desugared(hir::CoroutineDesugaring::Gen, _)
|
||||
@ -1144,7 +1143,7 @@ fn coroutine_movability_for_fn(
|
||||
if movability == Movability::Static {
|
||||
self.tcx.sess.emit_err(ClosureCannotBeStatic { fn_decl_span });
|
||||
}
|
||||
None
|
||||
hir::ClosureKind::Closure
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1236,7 +1235,7 @@ fn lower_expr_coroutine_closure(
|
||||
body,
|
||||
fn_decl_span: self.lower_span(fn_decl_span),
|
||||
fn_arg_span: Some(self.lower_span(fn_arg_span)),
|
||||
movability: None,
|
||||
kind: hir::ClosureKind::Closure,
|
||||
constness: hir::Constness::NotConst,
|
||||
});
|
||||
hir::ExprKind::Closure(c)
|
||||
|
@ -952,11 +952,7 @@ fn record_body(
|
||||
params: &'hir [hir::Param<'hir>],
|
||||
value: hir::Expr<'hir>,
|
||||
) -> hir::BodyId {
|
||||
let body = hir::Body {
|
||||
coroutine_kind: self.coroutine_kind,
|
||||
params,
|
||||
value: self.arena.alloc(value),
|
||||
};
|
||||
let body = hir::Body { params, value: self.arena.alloc(value) };
|
||||
let id = body.id();
|
||||
debug_assert_eq!(id.hir_id.owner, self.current_hir_id_owner);
|
||||
self.bodies.push((id.hir_id.local_id, self.arena.alloc(body)));
|
||||
|
@ -848,8 +848,8 @@ pub(crate) fn report_move_out_while_borrowed(
|
||||
move_spans.var_subdiag(None, &mut err, None, |kind, var_span| {
|
||||
use crate::session_diagnostics::CaptureVarCause::*;
|
||||
match kind {
|
||||
Some(_) => MoveUseInCoroutine { var_span },
|
||||
None => MoveUseInClosure { var_span },
|
||||
hir::ClosureKind::Coroutine(_, _) => MoveUseInCoroutine { var_span },
|
||||
hir::ClosureKind::Closure => MoveUseInClosure { var_span },
|
||||
}
|
||||
});
|
||||
|
||||
@ -893,10 +893,12 @@ pub(crate) fn report_use_while_mutably_borrowed(
|
||||
let place = &borrow.borrowed_place;
|
||||
let desc_place = self.describe_any_place(place.as_ref());
|
||||
match kind {
|
||||
Some(_) => {
|
||||
hir::ClosureKind::Coroutine(_, _) => {
|
||||
BorrowUsePlaceCoroutine { place: desc_place, var_span, is_single_var: true }
|
||||
}
|
||||
None => BorrowUsePlaceClosure { place: desc_place, var_span, is_single_var: true },
|
||||
hir::ClosureKind::Closure => {
|
||||
BorrowUsePlaceClosure { place: desc_place, var_span, is_single_var: true }
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
@ -1040,12 +1042,12 @@ pub(crate) fn report_conflicting_borrow(
|
||||
|kind, var_span| {
|
||||
use crate::session_diagnostics::CaptureVarCause::*;
|
||||
match kind {
|
||||
Some(_) => BorrowUsePlaceCoroutine {
|
||||
hir::ClosureKind::Coroutine(_, _) => BorrowUsePlaceCoroutine {
|
||||
place: desc_place,
|
||||
var_span,
|
||||
is_single_var: true,
|
||||
},
|
||||
None => BorrowUsePlaceClosure {
|
||||
hir::ClosureKind::Closure => BorrowUsePlaceClosure {
|
||||
place: desc_place,
|
||||
var_span,
|
||||
is_single_var: true,
|
||||
@ -1124,12 +1126,12 @@ pub(crate) fn report_conflicting_borrow(
|
||||
borrow_spans.var_subdiag(None, &mut err, Some(gen_borrow_kind), |kind, var_span| {
|
||||
use crate::session_diagnostics::CaptureVarCause::*;
|
||||
match kind {
|
||||
Some(_) => BorrowUsePlaceCoroutine {
|
||||
hir::ClosureKind::Coroutine(_, _) => BorrowUsePlaceCoroutine {
|
||||
place: desc_place,
|
||||
var_span,
|
||||
is_single_var: false,
|
||||
},
|
||||
None => {
|
||||
hir::ClosureKind::Closure => {
|
||||
BorrowUsePlaceClosure { place: desc_place, var_span, is_single_var: false }
|
||||
}
|
||||
}
|
||||
@ -1144,10 +1146,12 @@ pub(crate) fn report_conflicting_borrow(
|
||||
let borrow_place = &issued_borrow.borrowed_place;
|
||||
let borrow_place_desc = self.describe_any_place(borrow_place.as_ref());
|
||||
match kind {
|
||||
Some(_) => {
|
||||
hir::ClosureKind::Coroutine(_, _) => {
|
||||
FirstBorrowUsePlaceCoroutine { place: borrow_place_desc, var_span }
|
||||
}
|
||||
None => FirstBorrowUsePlaceClosure { place: borrow_place_desc, var_span },
|
||||
hir::ClosureKind::Closure => {
|
||||
FirstBorrowUsePlaceClosure { place: borrow_place_desc, var_span }
|
||||
}
|
||||
}
|
||||
},
|
||||
);
|
||||
@ -1159,8 +1163,12 @@ pub(crate) fn report_conflicting_borrow(
|
||||
|kind, var_span| {
|
||||
use crate::session_diagnostics::CaptureVarCause::*;
|
||||
match kind {
|
||||
Some(_) => SecondBorrowUsePlaceCoroutine { place: desc_place, var_span },
|
||||
None => SecondBorrowUsePlaceClosure { place: desc_place, var_span },
|
||||
hir::ClosureKind::Coroutine(_, _) => {
|
||||
SecondBorrowUsePlaceCoroutine { place: desc_place, var_span }
|
||||
}
|
||||
hir::ClosureKind::Closure => {
|
||||
SecondBorrowUsePlaceClosure { place: desc_place, var_span }
|
||||
}
|
||||
}
|
||||
},
|
||||
);
|
||||
@ -1651,7 +1659,7 @@ impl<'hir> Visitor<'hir> for ExpressionFinder<'hir> {
|
||||
fn visit_expr(&mut self, e: &'hir hir::Expr<'hir>) {
|
||||
if e.span.contains(self.capture_span) {
|
||||
if let hir::ExprKind::Closure(&hir::Closure {
|
||||
movability: None,
|
||||
kind: hir::ClosureKind::Closure,
|
||||
body,
|
||||
fn_arg_span,
|
||||
fn_decl: hir::FnDecl { inputs, .. },
|
||||
@ -1686,7 +1694,11 @@ fn visit_local(&mut self, local: &'hir hir::Local<'hir>) {
|
||||
&& let Some(init) = local.init
|
||||
{
|
||||
if let hir::Expr {
|
||||
kind: hir::ExprKind::Closure(&hir::Closure { movability: None, .. }),
|
||||
kind:
|
||||
hir::ExprKind::Closure(&hir::Closure {
|
||||
kind: hir::ClosureKind::Closure,
|
||||
..
|
||||
}),
|
||||
..
|
||||
} = init
|
||||
&& init.span.contains(self.capture_span)
|
||||
@ -2838,8 +2850,8 @@ pub(crate) fn report_illegal_mutation_of_borrowed(
|
||||
loan_spans.var_subdiag(None, &mut err, Some(loan.kind), |kind, var_span| {
|
||||
use crate::session_diagnostics::CaptureVarCause::*;
|
||||
match kind {
|
||||
Some(_) => BorrowUseInCoroutine { var_span },
|
||||
None => BorrowUseInClosure { var_span },
|
||||
hir::ClosureKind::Coroutine(_, _) => BorrowUseInCoroutine { var_span },
|
||||
hir::ClosureKind::Closure => BorrowUseInClosure { var_span },
|
||||
}
|
||||
});
|
||||
|
||||
@ -2854,8 +2866,8 @@ pub(crate) fn report_illegal_mutation_of_borrowed(
|
||||
loan_spans.var_subdiag(None, &mut err, Some(loan.kind), |kind, var_span| {
|
||||
use crate::session_diagnostics::CaptureVarCause::*;
|
||||
match kind {
|
||||
Some(_) => BorrowUseInCoroutine { var_span },
|
||||
None => BorrowUseInClosure { var_span },
|
||||
hir::ClosureKind::Coroutine(_, _) => BorrowUseInCoroutine { var_span },
|
||||
hir::ClosureKind::Closure => BorrowUseInClosure { var_span },
|
||||
}
|
||||
});
|
||||
|
||||
|
@ -505,7 +505,7 @@ pub(super) enum UseSpans<'tcx> {
|
||||
/// The access is caused by capturing a variable for a closure.
|
||||
ClosureUse {
|
||||
/// This is true if the captured variable was from a coroutine.
|
||||
coroutine_kind: Option<CoroutineKind>,
|
||||
closure_kind: hir::ClosureKind,
|
||||
/// The span of the args of the closure, including the `move` keyword if
|
||||
/// it's present.
|
||||
args_span: Span,
|
||||
@ -572,9 +572,13 @@ pub(super) fn var_or_use(self) -> Span {
|
||||
}
|
||||
}
|
||||
|
||||
// FIXME(coroutines): Make this just return the `ClosureKind` directly?
|
||||
pub(super) fn coroutine_kind(self) -> Option<CoroutineKind> {
|
||||
match self {
|
||||
UseSpans::ClosureUse { coroutine_kind, .. } => coroutine_kind,
|
||||
UseSpans::ClosureUse {
|
||||
closure_kind: hir::ClosureKind::Coroutine(coroutine_kind, _),
|
||||
..
|
||||
} => Some(coroutine_kind),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
@ -599,9 +603,9 @@ pub(super) fn var_path_only_subdiag(
|
||||
) {
|
||||
use crate::InitializationRequiringAction::*;
|
||||
use CaptureVarPathUseCause::*;
|
||||
if let UseSpans::ClosureUse { coroutine_kind, path_span, .. } = self {
|
||||
match coroutine_kind {
|
||||
Some(_) => {
|
||||
if let UseSpans::ClosureUse { closure_kind, path_span, .. } = self {
|
||||
match closure_kind {
|
||||
hir::ClosureKind::Coroutine(_, _) => {
|
||||
err.subdiagnostic(match action {
|
||||
Borrow => BorrowInCoroutine { path_span },
|
||||
MatchOn | Use => UseInCoroutine { path_span },
|
||||
@ -609,7 +613,7 @@ pub(super) fn var_path_only_subdiag(
|
||||
PartialAssignment => AssignPartInCoroutine { path_span },
|
||||
});
|
||||
}
|
||||
None => {
|
||||
hir::ClosureKind::Closure => {
|
||||
err.subdiagnostic(match action {
|
||||
Borrow => BorrowInClosure { path_span },
|
||||
MatchOn | Use => UseInClosure { path_span },
|
||||
@ -627,9 +631,9 @@ pub(super) fn var_subdiag(
|
||||
dcx: Option<&rustc_errors::DiagCtxt>,
|
||||
err: &mut Diagnostic,
|
||||
kind: Option<rustc_middle::mir::BorrowKind>,
|
||||
f: impl FnOnce(Option<CoroutineKind>, Span) -> CaptureVarCause,
|
||||
f: impl FnOnce(hir::ClosureKind, Span) -> CaptureVarCause,
|
||||
) {
|
||||
if let UseSpans::ClosureUse { coroutine_kind, capture_kind_span, path_span, .. } = self {
|
||||
if let UseSpans::ClosureUse { closure_kind, capture_kind_span, path_span, .. } = self {
|
||||
if capture_kind_span != path_span {
|
||||
err.subdiagnostic(match kind {
|
||||
Some(kd) => match kd {
|
||||
@ -645,7 +649,7 @@ pub(super) fn var_subdiag(
|
||||
None => CaptureVarKind::Move { kind_span: capture_kind_span },
|
||||
});
|
||||
};
|
||||
let diag = f(coroutine_kind, path_span);
|
||||
let diag = f(closure_kind, path_span);
|
||||
match dcx {
|
||||
Some(hd) => err.eager_subdiagnostic(hd, diag),
|
||||
None => err.subdiagnostic(diag),
|
||||
@ -656,7 +660,9 @@ pub(super) fn var_subdiag(
|
||||
/// Returns `false` if this place is not used in a closure.
|
||||
pub(super) fn for_closure(&self) -> bool {
|
||||
match *self {
|
||||
UseSpans::ClosureUse { coroutine_kind, .. } => coroutine_kind.is_none(),
|
||||
UseSpans::ClosureUse { closure_kind, .. } => {
|
||||
matches!(closure_kind, hir::ClosureKind::Closure)
|
||||
}
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
@ -664,7 +670,10 @@ pub(super) fn for_closure(&self) -> bool {
|
||||
/// Returns `false` if this place is not used in a coroutine.
|
||||
pub(super) fn for_coroutine(&self) -> bool {
|
||||
match *self {
|
||||
UseSpans::ClosureUse { coroutine_kind, .. } => coroutine_kind.is_some(),
|
||||
// FIXME(coroutines): Do we want this to apply to synthetic coroutines?
|
||||
UseSpans::ClosureUse { closure_kind, .. } => {
|
||||
matches!(closure_kind, hir::ClosureKind::Coroutine(..))
|
||||
}
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
@ -788,10 +797,10 @@ pub(super) fn move_spans(
|
||||
{
|
||||
debug!("move_spans: def_id={:?} places={:?}", def_id, places);
|
||||
let def_id = def_id.expect_local();
|
||||
if let Some((args_span, coroutine_kind, capture_kind_span, path_span)) =
|
||||
if let Some((args_span, closure_kind, capture_kind_span, path_span)) =
|
||||
self.closure_span(def_id, moved_place, places)
|
||||
{
|
||||
return ClosureUse { coroutine_kind, args_span, capture_kind_span, path_span };
|
||||
return ClosureUse { closure_kind, args_span, capture_kind_span, path_span };
|
||||
}
|
||||
}
|
||||
|
||||
@ -803,11 +812,11 @@ pub(super) fn move_spans(
|
||||
| FakeReadCause::ForLet(Some(closure_def_id)) => {
|
||||
debug!("move_spans: def_id={:?} place={:?}", closure_def_id, place);
|
||||
let places = &[Operand::Move(place)];
|
||||
if let Some((args_span, coroutine_kind, capture_kind_span, path_span)) =
|
||||
if let Some((args_span, closure_kind, capture_kind_span, path_span)) =
|
||||
self.closure_span(closure_def_id, moved_place, IndexSlice::from_raw(places))
|
||||
{
|
||||
return ClosureUse {
|
||||
coroutine_kind,
|
||||
closure_kind,
|
||||
args_span,
|
||||
capture_kind_span,
|
||||
path_span,
|
||||
@ -928,10 +937,10 @@ pub(super) fn borrow_spans(&self, use_span: Span, location: Location) -> UseSpan
|
||||
"borrow_spans: def_id={:?} is_coroutine={:?} places={:?}",
|
||||
def_id, is_coroutine, places
|
||||
);
|
||||
if let Some((args_span, coroutine_kind, capture_kind_span, path_span)) =
|
||||
if let Some((args_span, closure_kind, capture_kind_span, path_span)) =
|
||||
self.closure_span(def_id, Place::from(target).as_ref(), places)
|
||||
{
|
||||
return ClosureUse { coroutine_kind, args_span, capture_kind_span, path_span };
|
||||
return ClosureUse { closure_kind, args_span, capture_kind_span, path_span };
|
||||
} else {
|
||||
return OtherUse(use_span);
|
||||
}
|
||||
@ -953,7 +962,7 @@ fn closure_span(
|
||||
def_id: LocalDefId,
|
||||
target_place: PlaceRef<'tcx>,
|
||||
places: &IndexSlice<FieldIdx, Operand<'tcx>>,
|
||||
) -> Option<(Span, Option<CoroutineKind>, Span, Span)> {
|
||||
) -> Option<(Span, hir::ClosureKind, Span, Span)> {
|
||||
debug!(
|
||||
"closure_span: def_id={:?} target_place={:?} places={:?}",
|
||||
def_id, target_place, places
|
||||
@ -961,7 +970,7 @@ fn closure_span(
|
||||
let hir_id = self.infcx.tcx.local_def_id_to_hir_id(def_id);
|
||||
let expr = &self.infcx.tcx.hir().expect_expr(hir_id).kind;
|
||||
debug!("closure_span: hir_id={:?} expr={:?}", hir_id, expr);
|
||||
if let hir::ExprKind::Closure(&hir::Closure { body, fn_decl_span, .. }) = expr {
|
||||
if let hir::ExprKind::Closure(&hir::Closure { kind, fn_decl_span, .. }) = expr {
|
||||
for (captured_place, place) in
|
||||
self.infcx.tcx.closure_captures(def_id).iter().zip(places)
|
||||
{
|
||||
@ -970,12 +979,9 @@ fn closure_span(
|
||||
if target_place == place.as_ref() =>
|
||||
{
|
||||
debug!("closure_span: found captured local {:?}", place);
|
||||
let body = self.infcx.tcx.hir().body(body);
|
||||
let coroutine_kind = body.coroutine_kind();
|
||||
|
||||
return Some((
|
||||
fn_decl_span,
|
||||
coroutine_kind,
|
||||
kind,
|
||||
captured_place.get_capture_kind_span(self.infcx.tcx),
|
||||
captured_place.get_path_span(self.infcx.tcx),
|
||||
));
|
||||
@ -1242,8 +1248,12 @@ fn explain_captures(
|
||||
// another message for the same span
|
||||
if !is_loop_message {
|
||||
move_spans.var_subdiag(None, err, None, |kind, var_span| match kind {
|
||||
Some(_) => CaptureVarCause::PartialMoveUseInCoroutine { var_span, is_partial },
|
||||
None => CaptureVarCause::PartialMoveUseInClosure { var_span, is_partial },
|
||||
hir::ClosureKind::Coroutine(_, _) => {
|
||||
CaptureVarCause::PartialMoveUseInCoroutine { var_span, is_partial }
|
||||
}
|
||||
hir::ClosureKind::Closure => {
|
||||
CaptureVarCause::PartialMoveUseInClosure { var_span, is_partial }
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
@ -1030,8 +1030,7 @@ fn suggest_using_iter_mut(&self, err: &mut DiagnosticBuilder<'_>) {
|
||||
let hir = self.infcx.tcx.hir();
|
||||
if let InstanceDef::Item(def_id) = source.instance
|
||||
&& let Some(Node::Expr(hir::Expr { hir_id, kind, .. })) = hir.get_if_local(def_id)
|
||||
&& let ExprKind::Closure(closure) = kind
|
||||
&& closure.movability == None
|
||||
&& let ExprKind::Closure(hir::Closure { kind: hir::ClosureKind::Closure, .. }) = kind
|
||||
&& let Some(Node::Expr(expr)) = hir.find_parent(*hir_id)
|
||||
{
|
||||
let mut cur_expr = expr;
|
||||
|
@ -1042,13 +1042,15 @@ fn suggest_move_on_borrowing_closure(&self, diag: &mut Diagnostic) {
|
||||
}
|
||||
hir::ExprKind::Closure(hir::Closure {
|
||||
capture_clause: hir::CaptureBy::Ref,
|
||||
body,
|
||||
kind,
|
||||
..
|
||||
}) => {
|
||||
let body = map.body(*body);
|
||||
if !matches!(
|
||||
body.coroutine_kind,
|
||||
Some(hir::CoroutineKind::Desugared(hir::CoroutineDesugaring::Async, _))
|
||||
kind,
|
||||
hir::ClosureKind::Coroutine(
|
||||
hir::CoroutineKind::Desugared(hir::CoroutineDesugaring::Async, _),
|
||||
_
|
||||
)
|
||||
) {
|
||||
closure_span = Some(expr.span.shrink_to_lo());
|
||||
}
|
||||
|
@ -674,7 +674,7 @@ fn give_name_if_anonymous_region_appears_in_output(&self, fr: RegionVid) -> Opti
|
||||
|
||||
let (return_span, mir_description, hir_ty) = match tcx.hir_node(mir_hir_id) {
|
||||
hir::Node::Expr(hir::Expr {
|
||||
kind: hir::ExprKind::Closure(&hir::Closure { fn_decl, body, fn_decl_span, .. }),
|
||||
kind: hir::ExprKind::Closure(&hir::Closure { fn_decl, kind, fn_decl_span, .. }),
|
||||
..
|
||||
}) => {
|
||||
let (mut span, mut hir_ty) = match fn_decl.output {
|
||||
@ -683,47 +683,49 @@ fn give_name_if_anonymous_region_appears_in_output(&self, fr: RegionVid) -> Opti
|
||||
}
|
||||
hir::FnRetTy::Return(hir_ty) => (fn_decl.output.span(), Some(hir_ty)),
|
||||
};
|
||||
let mir_description = match hir.body(body).coroutine_kind {
|
||||
Some(hir::CoroutineKind::Desugared(hir::CoroutineDesugaring::Async, src)) => {
|
||||
match src {
|
||||
hir::CoroutineSource::Block => " of async block",
|
||||
hir::CoroutineSource::Closure => " of async closure",
|
||||
hir::CoroutineSource::Fn => {
|
||||
let parent_item =
|
||||
tcx.hir_node_by_def_id(hir.get_parent_item(mir_hir_id).def_id);
|
||||
let output = &parent_item
|
||||
.fn_decl()
|
||||
.expect("coroutine lowered from async fn should be in fn")
|
||||
.output;
|
||||
span = output.span();
|
||||
if let hir::FnRetTy::Return(ret) = output {
|
||||
hir_ty = Some(self.get_future_inner_return_ty(*ret));
|
||||
}
|
||||
" of async function"
|
||||
let mir_description = match kind {
|
||||
hir::ClosureKind::Coroutine(
|
||||
hir::CoroutineKind::Desugared(hir::CoroutineDesugaring::Async, src),
|
||||
_,
|
||||
) => match src {
|
||||
hir::CoroutineSource::Block => " of async block",
|
||||
hir::CoroutineSource::Closure => " of async closure",
|
||||
hir::CoroutineSource::Fn => {
|
||||
let parent_item =
|
||||
tcx.hir_node_by_def_id(hir.get_parent_item(mir_hir_id).def_id);
|
||||
let output = &parent_item
|
||||
.fn_decl()
|
||||
.expect("coroutine lowered from async fn should be in fn")
|
||||
.output;
|
||||
span = output.span();
|
||||
if let hir::FnRetTy::Return(ret) = output {
|
||||
hir_ty = Some(self.get_future_inner_return_ty(*ret));
|
||||
}
|
||||
" of async function"
|
||||
}
|
||||
}
|
||||
Some(hir::CoroutineKind::Desugared(hir::CoroutineDesugaring::Gen, src)) => {
|
||||
match src {
|
||||
hir::CoroutineSource::Block => " of gen block",
|
||||
hir::CoroutineSource::Closure => " of gen closure",
|
||||
hir::CoroutineSource::Fn => {
|
||||
let parent_item =
|
||||
tcx.hir_node_by_def_id(hir.get_parent_item(mir_hir_id).def_id);
|
||||
let output = &parent_item
|
||||
.fn_decl()
|
||||
.expect("coroutine lowered from gen fn should be in fn")
|
||||
.output;
|
||||
span = output.span();
|
||||
" of gen function"
|
||||
}
|
||||
},
|
||||
hir::ClosureKind::Coroutine(
|
||||
hir::CoroutineKind::Desugared(hir::CoroutineDesugaring::Gen, src),
|
||||
_,
|
||||
) => match src {
|
||||
hir::CoroutineSource::Block => " of gen block",
|
||||
hir::CoroutineSource::Closure => " of gen closure",
|
||||
hir::CoroutineSource::Fn => {
|
||||
let parent_item =
|
||||
tcx.hir_node_by_def_id(hir.get_parent_item(mir_hir_id).def_id);
|
||||
let output = &parent_item
|
||||
.fn_decl()
|
||||
.expect("coroutine lowered from gen fn should be in fn")
|
||||
.output;
|
||||
span = output.span();
|
||||
" of gen function"
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
Some(hir::CoroutineKind::Desugared(
|
||||
hir::CoroutineDesugaring::AsyncGen,
|
||||
src,
|
||||
)) => match src {
|
||||
hir::ClosureKind::Coroutine(
|
||||
hir::CoroutineKind::Desugared(hir::CoroutineDesugaring::AsyncGen, src),
|
||||
_,
|
||||
) => match src {
|
||||
hir::CoroutineSource::Block => " of async gen block",
|
||||
hir::CoroutineSource::Closure => " of async gen closure",
|
||||
hir::CoroutineSource::Fn => {
|
||||
@ -737,8 +739,10 @@ fn give_name_if_anonymous_region_appears_in_output(&self, fr: RegionVid) -> Opti
|
||||
" of async gen function"
|
||||
}
|
||||
},
|
||||
Some(hir::CoroutineKind::Coroutine) => " of coroutine",
|
||||
None => " of closure",
|
||||
hir::ClosureKind::Coroutine(hir::CoroutineKind::Coroutine, _) => {
|
||||
" of coroutine"
|
||||
}
|
||||
hir::ClosureKind::Closure => " of closure",
|
||||
};
|
||||
(span, mir_description, hir_ty)
|
||||
}
|
||||
|
@ -945,7 +945,21 @@ pub struct Closure<'hir> {
|
||||
pub fn_decl_span: Span,
|
||||
/// The span of the argument block `|...|`
|
||||
pub fn_arg_span: Option<Span>,
|
||||
pub movability: Option<Movability>,
|
||||
pub kind: ClosureKind,
|
||||
}
|
||||
|
||||
#[derive(Clone, PartialEq, Eq, Debug, Copy, Hash, HashStable_Generic, Encodable, Decodable)]
|
||||
pub enum ClosureKind {
|
||||
/// This is a plain closure expression.
|
||||
Closure,
|
||||
/// This is a coroutine expression -- i.e. a closure expression in which
|
||||
/// we've found a `yield`. These can arise either from "plain" coroutine
|
||||
/// usage (e.g. `let x = || { yield (); }`) or from a desugared expression
|
||||
/// (e.g. `async` and `gen` blocks).
|
||||
// FIXME(coroutines): We could probably remove movability here -- it can be deduced
|
||||
// from the `CoroutineKind` in all cases (except for "plain" coroutines, which could
|
||||
// carry the movability in the variant).
|
||||
Coroutine(CoroutineKind, Movability),
|
||||
}
|
||||
|
||||
/// A block of statements `{ .. }`, which may have a label (in this case the
|
||||
@ -1335,17 +1349,12 @@ pub struct BodyId {
|
||||
pub struct Body<'hir> {
|
||||
pub params: &'hir [Param<'hir>],
|
||||
pub value: &'hir Expr<'hir>,
|
||||
pub coroutine_kind: Option<CoroutineKind>,
|
||||
}
|
||||
|
||||
impl<'hir> Body<'hir> {
|
||||
pub fn id(&self) -> BodyId {
|
||||
BodyId { hir_id: self.value.hir_id }
|
||||
}
|
||||
|
||||
pub fn coroutine_kind(&self) -> Option<CoroutineKind> {
|
||||
self.coroutine_kind
|
||||
}
|
||||
}
|
||||
|
||||
/// The type of source expression that caused this coroutine to be created.
|
||||
@ -3661,7 +3670,7 @@ mod size_asserts {
|
||||
use super::*;
|
||||
// tidy-alphabetical-start
|
||||
static_assert_size!(Block<'_>, 48);
|
||||
static_assert_size!(Body<'_>, 32);
|
||||
static_assert_size!(Body<'_>, 24);
|
||||
static_assert_size!(Expr<'_>, 64);
|
||||
static_assert_size!(ExprKind<'_>, 48);
|
||||
static_assert_size!(FnDecl<'_>, 40);
|
||||
|
@ -757,7 +757,7 @@ pub fn walk_expr<'v, V: Visitor<'v>>(visitor: &mut V, expression: &'v Expr<'v>)
|
||||
capture_clause: _,
|
||||
fn_decl_span: _,
|
||||
fn_arg_span: _,
|
||||
movability: _,
|
||||
kind: _,
|
||||
constness: _,
|
||||
}) => {
|
||||
walk_list!(visitor, visit_generic_param, bound_generic_params);
|
||||
|
@ -1551,10 +1551,14 @@ fn compute_sig_of_foreign_fn_decl<'tcx>(
|
||||
|
||||
fn coroutine_kind(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Option<hir::CoroutineKind> {
|
||||
match tcx.hir_node_by_def_id(def_id) {
|
||||
Node::Expr(&rustc_hir::Expr {
|
||||
kind: rustc_hir::ExprKind::Closure(&rustc_hir::Closure { body, .. }),
|
||||
Node::Expr(&hir::Expr {
|
||||
kind:
|
||||
hir::ExprKind::Closure(&rustc_hir::Closure {
|
||||
kind: hir::ClosureKind::Coroutine(kind, _),
|
||||
..
|
||||
}),
|
||||
..
|
||||
}) => tcx.hir().body(body).coroutine_kind(),
|
||||
}) => Some(kind),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
@ -338,14 +338,14 @@ enum Defaults {
|
||||
// cares about anything but the length is instantiation,
|
||||
// and we don't do that for closures.
|
||||
if let Node::Expr(&hir::Expr {
|
||||
kind: hir::ExprKind::Closure(hir::Closure { movability: gen, .. }),
|
||||
..
|
||||
kind: hir::ExprKind::Closure(hir::Closure { kind, .. }), ..
|
||||
}) = node
|
||||
{
|
||||
let dummy_args = if gen.is_some() {
|
||||
&["<resume_ty>", "<yield_ty>", "<return_ty>", "<witness>", "<upvars>"][..]
|
||||
} else {
|
||||
&["<closure_kind>", "<closure_signature>", "<upvars>"][..]
|
||||
let dummy_args = match kind {
|
||||
ClosureKind::Closure => &["<closure_kind>", "<closure_signature>", "<upvars>"][..],
|
||||
ClosureKind::Coroutine(_, _) => {
|
||||
&["<resume_ty>", "<yield_ty>", "<return_ty>", "<witness>", "<upvars>"][..]
|
||||
}
|
||||
};
|
||||
|
||||
params.extend(dummy_args.iter().map(|&arg| ty::GenericParamDef {
|
||||
|
@ -1407,7 +1407,7 @@ fn print_expr(&mut self, expr: &hir::Expr<'_>) {
|
||||
body,
|
||||
fn_decl_span: _,
|
||||
fn_arg_span: _,
|
||||
movability: _,
|
||||
kind: _,
|
||||
def_id: _,
|
||||
}) => {
|
||||
self.print_closure_binder(binder, bound_generic_params);
|
||||
|
@ -298,17 +298,22 @@ fn identify_bad_closure_def_and_call(
|
||||
let parent_node = self.tcx.hir_node(parent_hir_id);
|
||||
if let (
|
||||
hir::Node::Expr(hir::Expr {
|
||||
kind: hir::ExprKind::Closure(&hir::Closure { fn_decl_span, body, .. }),
|
||||
kind: hir::ExprKind::Closure(&hir::Closure { fn_decl_span, kind, .. }),
|
||||
..
|
||||
}),
|
||||
hir::ExprKind::Block(..),
|
||||
) = (parent_node, callee_node)
|
||||
{
|
||||
let fn_decl_span = if hir.body(body).coroutine_kind
|
||||
== Some(hir::CoroutineKind::Desugared(
|
||||
hir::CoroutineDesugaring::Async,
|
||||
hir::CoroutineSource::Closure,
|
||||
)) {
|
||||
let fn_decl_span = if matches!(
|
||||
kind,
|
||||
hir::ClosureKind::Coroutine(
|
||||
hir::CoroutineKind::Desugared(
|
||||
hir::CoroutineDesugaring::Async,
|
||||
hir::CoroutineSource::Closure
|
||||
),
|
||||
_
|
||||
)
|
||||
) {
|
||||
// Actually need to unwrap one more layer of HIR to get to
|
||||
// the _real_ closure...
|
||||
let async_closure = hir.parent_id(parent_hir_id);
|
||||
|
@ -31,7 +31,7 @@ pub(super) fn check_fn<'a, 'tcx>(
|
||||
decl: &'tcx hir::FnDecl<'tcx>,
|
||||
fn_def_id: LocalDefId,
|
||||
body: &'tcx hir::Body<'tcx>,
|
||||
can_be_coroutine: Option<hir::Movability>,
|
||||
closure_kind: Option<hir::ClosureKind>,
|
||||
params_can_be_unsized: bool,
|
||||
) -> Option<CoroutineTypes<'tcx>> {
|
||||
let fn_id = fcx.tcx.local_def_id_to_hir_id(fn_def_id);
|
||||
@ -55,9 +55,7 @@ pub(super) fn check_fn<'a, 'tcx>(
|
||||
|
||||
forbid_intrinsic_abi(tcx, span, fn_sig.abi);
|
||||
|
||||
if let Some(kind) = body.coroutine_kind
|
||||
&& can_be_coroutine.is_some()
|
||||
{
|
||||
if let Some(hir::ClosureKind::Coroutine(kind, _)) = closure_kind {
|
||||
let yield_ty = match kind {
|
||||
hir::CoroutineKind::Desugared(hir::CoroutineDesugaring::Gen, _)
|
||||
| hir::CoroutineKind::Coroutine => {
|
||||
@ -151,8 +149,8 @@ pub(super) fn check_fn<'a, 'tcx>(
|
||||
// We insert the deferred_coroutine_interiors entry after visiting the body.
|
||||
// This ensures that all nested coroutines appear before the entry of this coroutine.
|
||||
// resolve_coroutine_interiors relies on this property.
|
||||
let coroutine_ty = if let (Some(_), Some(coroutine_kind)) =
|
||||
(can_be_coroutine, body.coroutine_kind)
|
||||
let coroutine_ty = if let Some(hir::ClosureKind::Coroutine(coroutine_kind, movability)) =
|
||||
closure_kind
|
||||
{
|
||||
let interior = fcx
|
||||
.next_ty_var(TypeVariableOrigin { kind: TypeVariableOriginKind::MiscVariable, span });
|
||||
@ -164,12 +162,7 @@ pub(super) fn check_fn<'a, 'tcx>(
|
||||
));
|
||||
|
||||
let (resume_ty, yield_ty) = fcx.resume_yield_tys.unwrap();
|
||||
Some(CoroutineTypes {
|
||||
resume_ty,
|
||||
yield_ty,
|
||||
interior,
|
||||
movability: can_be_coroutine.unwrap(),
|
||||
})
|
||||
Some(CoroutineTypes { resume_ty, yield_ty, interior, movability: movability })
|
||||
} else {
|
||||
None
|
||||
};
|
||||
|
@ -79,7 +79,7 @@ fn check_closure(
|
||||
debug!(?expr_def_id);
|
||||
|
||||
let ClosureSignatures { bound_sig, liberated_sig } =
|
||||
self.sig_of_closure(expr_def_id, closure.fn_decl, body.coroutine_kind, expected_sig);
|
||||
self.sig_of_closure(expr_def_id, closure.fn_decl, closure.kind, expected_sig);
|
||||
|
||||
debug!(?bound_sig, ?liberated_sig);
|
||||
|
||||
@ -90,7 +90,7 @@ fn check_closure(
|
||||
closure.fn_decl,
|
||||
expr_def_id,
|
||||
body,
|
||||
closure.movability,
|
||||
Some(closure.kind),
|
||||
// Closure "rust-call" ABI doesn't support unsized params
|
||||
false,
|
||||
);
|
||||
@ -352,13 +352,13 @@ fn sig_of_closure(
|
||||
&self,
|
||||
expr_def_id: LocalDefId,
|
||||
decl: &hir::FnDecl<'_>,
|
||||
coroutine_kind: Option<hir::CoroutineKind>,
|
||||
closure_kind: hir::ClosureKind,
|
||||
expected_sig: Option<ExpectedSig<'tcx>>,
|
||||
) -> ClosureSignatures<'tcx> {
|
||||
if let Some(e) = expected_sig {
|
||||
self.sig_of_closure_with_expectation(expr_def_id, decl, coroutine_kind, e)
|
||||
self.sig_of_closure_with_expectation(expr_def_id, decl, closure_kind, e)
|
||||
} else {
|
||||
self.sig_of_closure_no_expectation(expr_def_id, decl, coroutine_kind)
|
||||
self.sig_of_closure_no_expectation(expr_def_id, decl, closure_kind)
|
||||
}
|
||||
}
|
||||
|
||||
@ -369,9 +369,9 @@ fn sig_of_closure_no_expectation(
|
||||
&self,
|
||||
expr_def_id: LocalDefId,
|
||||
decl: &hir::FnDecl<'_>,
|
||||
coroutine_kind: Option<hir::CoroutineKind>,
|
||||
closure_kind: hir::ClosureKind,
|
||||
) -> ClosureSignatures<'tcx> {
|
||||
let bound_sig = self.supplied_sig_of_closure(expr_def_id, decl, coroutine_kind);
|
||||
let bound_sig = self.supplied_sig_of_closure(expr_def_id, decl, closure_kind);
|
||||
|
||||
self.closure_sigs(expr_def_id, bound_sig)
|
||||
}
|
||||
@ -428,14 +428,14 @@ fn sig_of_closure_with_expectation(
|
||||
&self,
|
||||
expr_def_id: LocalDefId,
|
||||
decl: &hir::FnDecl<'_>,
|
||||
coroutine_kind: Option<hir::CoroutineKind>,
|
||||
closure_kind: hir::ClosureKind,
|
||||
expected_sig: ExpectedSig<'tcx>,
|
||||
) -> ClosureSignatures<'tcx> {
|
||||
// Watch out for some surprises and just ignore the
|
||||
// expectation if things don't see to match up with what we
|
||||
// expect.
|
||||
if expected_sig.sig.c_variadic() != decl.c_variadic {
|
||||
return self.sig_of_closure_no_expectation(expr_def_id, decl, coroutine_kind);
|
||||
return self.sig_of_closure_no_expectation(expr_def_id, decl, closure_kind);
|
||||
} else if expected_sig.sig.skip_binder().inputs_and_output.len() != decl.inputs.len() + 1 {
|
||||
return self.sig_of_closure_with_mismatched_number_of_arguments(
|
||||
expr_def_id,
|
||||
@ -473,11 +473,11 @@ fn sig_of_closure_with_expectation(
|
||||
match self.merge_supplied_sig_with_expectation(
|
||||
expr_def_id,
|
||||
decl,
|
||||
coroutine_kind,
|
||||
closure_kind,
|
||||
closure_sigs,
|
||||
) {
|
||||
Ok(infer_ok) => self.register_infer_ok_obligations(infer_ok),
|
||||
Err(_) => self.sig_of_closure_no_expectation(expr_def_id, decl, coroutine_kind),
|
||||
Err(_) => self.sig_of_closure_no_expectation(expr_def_id, decl, closure_kind),
|
||||
}
|
||||
}
|
||||
|
||||
@ -526,14 +526,14 @@ fn merge_supplied_sig_with_expectation(
|
||||
&self,
|
||||
expr_def_id: LocalDefId,
|
||||
decl: &hir::FnDecl<'_>,
|
||||
coroutine_kind: Option<hir::CoroutineKind>,
|
||||
closure_kind: hir::ClosureKind,
|
||||
mut expected_sigs: ClosureSignatures<'tcx>,
|
||||
) -> InferResult<'tcx, ClosureSignatures<'tcx>> {
|
||||
// Get the signature S that the user gave.
|
||||
//
|
||||
// (See comment on `sig_of_closure_with_expectation` for the
|
||||
// meaning of these letters.)
|
||||
let supplied_sig = self.supplied_sig_of_closure(expr_def_id, decl, coroutine_kind);
|
||||
let supplied_sig = self.supplied_sig_of_closure(expr_def_id, decl, closure_kind);
|
||||
|
||||
debug!(?supplied_sig);
|
||||
|
||||
@ -620,12 +620,12 @@ fn supplied_sig_of_closure(
|
||||
&self,
|
||||
expr_def_id: LocalDefId,
|
||||
decl: &hir::FnDecl<'_>,
|
||||
coroutine_kind: Option<hir::CoroutineKind>,
|
||||
closure_kind: hir::ClosureKind,
|
||||
) -> ty::PolyFnSig<'tcx> {
|
||||
let astconv: &dyn AstConv<'_> = self;
|
||||
|
||||
trace!("decl = {:#?}", decl);
|
||||
debug!(?coroutine_kind);
|
||||
debug!(?closure_kind);
|
||||
|
||||
let hir_id = self.tcx.local_def_id_to_hir_id(expr_def_id);
|
||||
let bound_vars = self.tcx.late_bound_vars(hir_id);
|
||||
@ -634,14 +634,17 @@ fn supplied_sig_of_closure(
|
||||
let supplied_arguments = decl.inputs.iter().map(|a| astconv.ast_ty_to_ty(a));
|
||||
let supplied_return = match decl.output {
|
||||
hir::FnRetTy::Return(ref output) => astconv.ast_ty_to_ty(output),
|
||||
hir::FnRetTy::DefaultReturn(_) => match coroutine_kind {
|
||||
hir::FnRetTy::DefaultReturn(_) => match closure_kind {
|
||||
// In the case of the async block that we create for a function body,
|
||||
// we expect the return type of the block to match that of the enclosing
|
||||
// function.
|
||||
Some(hir::CoroutineKind::Desugared(
|
||||
hir::CoroutineDesugaring::Async,
|
||||
hir::CoroutineSource::Fn,
|
||||
)) => {
|
||||
hir::ClosureKind::Coroutine(
|
||||
hir::CoroutineKind::Desugared(
|
||||
hir::CoroutineDesugaring::Async,
|
||||
hir::CoroutineSource::Fn,
|
||||
),
|
||||
_,
|
||||
) => {
|
||||
debug!("closure is async fn body");
|
||||
self.deduce_future_output_from_obligations(expr_def_id).unwrap_or_else(|| {
|
||||
// AFAIK, deducing the future output
|
||||
@ -655,12 +658,21 @@ fn supplied_sig_of_closure(
|
||||
})
|
||||
}
|
||||
// All `gen {}` and `async gen {}` must return unit.
|
||||
Some(
|
||||
hir::ClosureKind::Coroutine(
|
||||
hir::CoroutineKind::Desugared(hir::CoroutineDesugaring::Gen, _)
|
||||
| hir::CoroutineKind::Desugared(hir::CoroutineDesugaring::AsyncGen, _),
|
||||
_,
|
||||
) => self.tcx.types.unit,
|
||||
|
||||
_ => astconv.ty_infer(None, decl.output.span()),
|
||||
// For async blocks, we just fall back to `_` here.
|
||||
// For closures/coroutines, we know nothing about the return
|
||||
// type unless it was supplied.
|
||||
hir::ClosureKind::Coroutine(
|
||||
hir::CoroutineKind::Desugared(hir::CoroutineDesugaring::Async, _),
|
||||
_,
|
||||
)
|
||||
| hir::ClosureKind::Coroutine(hir::CoroutineKind::Coroutine, _)
|
||||
| hir::ClosureKind::Closure => astconv.ty_infer(None, decl.output.span()),
|
||||
},
|
||||
};
|
||||
|
||||
|
@ -3,7 +3,7 @@
|
||||
use rustc_hir as hir;
|
||||
use rustc_hir::def_id::{LocalDefId, LocalModDefId};
|
||||
use rustc_hir::intravisit::{self, Visitor};
|
||||
use rustc_hir::{Destination, Movability, Node};
|
||||
use rustc_hir::{Destination, Node};
|
||||
use rustc_middle::hir::nested_filter;
|
||||
use rustc_middle::query::Providers;
|
||||
use rustc_middle::ty::TyCtxt;
|
||||
@ -86,16 +86,18 @@ fn visit_expr(&mut self, e: &'hir hir::Expr<'hir>) {
|
||||
self.with_context(Loop(source), |v| v.visit_block(b));
|
||||
}
|
||||
hir::ExprKind::Closure(&hir::Closure {
|
||||
ref fn_decl,
|
||||
body,
|
||||
fn_decl_span,
|
||||
movability,
|
||||
..
|
||||
ref fn_decl, body, fn_decl_span, kind, ..
|
||||
}) => {
|
||||
let cx = if let Some(Movability::Static) = movability {
|
||||
AsyncClosure(fn_decl_span)
|
||||
} else {
|
||||
Closure(fn_decl_span)
|
||||
// FIXME(coroutines): This doesn't handle coroutines correctly
|
||||
let cx = match kind {
|
||||
hir::ClosureKind::Coroutine(
|
||||
hir::CoroutineKind::Desugared(
|
||||
hir::CoroutineDesugaring::Async,
|
||||
hir::CoroutineSource::Block,
|
||||
),
|
||||
_,
|
||||
) => AsyncClosure(fn_decl_span),
|
||||
_ => Closure(fn_decl_span),
|
||||
};
|
||||
self.visit_fn_decl(fn_decl);
|
||||
self.with_context(cx, |v| v.visit_nested_body(body));
|
||||
|
@ -8,7 +8,7 @@
|
||||
use rustc_data_structures::fx::FxHashMap;
|
||||
use rustc_errors::{struct_span_err, ErrorGuaranteed};
|
||||
use rustc_hir as hir;
|
||||
use rustc_hir::def_id::DefId;
|
||||
use rustc_hir::def_id::{DefId, LocalDefId};
|
||||
use rustc_middle::ty::GenericArgsRef;
|
||||
use rustc_middle::ty::{self, GenericParamDefKind, TyCtxt};
|
||||
use rustc_parse_format::{ParseMode, Parser, Piece, Position};
|
||||
@ -32,7 +32,7 @@ fn impl_similar_to(
|
||||
) -> Option<(DefId, GenericArgsRef<'tcx>)>;
|
||||
|
||||
/*private*/
|
||||
fn describe_enclosure(&self, hir_id: hir::HirId) -> Option<&'static str>;
|
||||
fn describe_enclosure(&self, def_id: LocalDefId) -> Option<&'static str>;
|
||||
|
||||
fn on_unimplemented_note(
|
||||
&self,
|
||||
@ -101,43 +101,19 @@ fn impl_similar_to(
|
||||
|
||||
/// Used to set on_unimplemented's `ItemContext`
|
||||
/// to be the enclosing (async) block/function/closure
|
||||
fn describe_enclosure(&self, hir_id: hir::HirId) -> Option<&'static str> {
|
||||
let hir = self.tcx.hir();
|
||||
let node = self.tcx.opt_hir_node(hir_id)?;
|
||||
match &node {
|
||||
hir::Node::Item(hir::Item { kind: hir::ItemKind::Fn(sig, _, body_id), .. }) => {
|
||||
self.describe_coroutine(*body_id).or_else(|| {
|
||||
Some(match sig.header {
|
||||
hir::FnHeader { asyncness: hir::IsAsync::Async(_), .. } => {
|
||||
"an async function"
|
||||
}
|
||||
_ => "a function",
|
||||
})
|
||||
})
|
||||
fn describe_enclosure(&self, def_id: LocalDefId) -> Option<&'static str> {
|
||||
match self.tcx.opt_hir_node_by_def_id(def_id)? {
|
||||
hir::Node::Item(hir::Item { kind: hir::ItemKind::Fn(..), .. }) => Some("a function"),
|
||||
hir::Node::TraitItem(hir::TraitItem { kind: hir::TraitItemKind::Fn(..), .. }) => {
|
||||
Some("a trait method")
|
||||
}
|
||||
hir::Node::ImplItem(hir::ImplItem { kind: hir::ImplItemKind::Fn(..), .. }) => {
|
||||
Some("a method")
|
||||
}
|
||||
hir::Node::TraitItem(hir::TraitItem {
|
||||
kind: hir::TraitItemKind::Fn(_, hir::TraitFn::Provided(body_id)),
|
||||
..
|
||||
}) => self.describe_coroutine(*body_id).or_else(|| Some("a trait method")),
|
||||
hir::Node::ImplItem(hir::ImplItem {
|
||||
kind: hir::ImplItemKind::Fn(sig, body_id),
|
||||
..
|
||||
}) => self.describe_coroutine(*body_id).or_else(|| {
|
||||
Some(match sig.header {
|
||||
hir::FnHeader { asyncness: hir::IsAsync::Async(_), .. } => "an async method",
|
||||
_ => "a method",
|
||||
})
|
||||
}),
|
||||
hir::Node::Expr(hir::Expr {
|
||||
kind: hir::ExprKind::Closure(hir::Closure { body, movability, .. }),
|
||||
kind: hir::ExprKind::Closure(hir::Closure { kind, .. }),
|
||||
..
|
||||
}) => self.describe_coroutine(*body).or_else(|| {
|
||||
Some(if movability.is_some() { "an async closure" } else { "a closure" })
|
||||
}),
|
||||
hir::Node::Expr(hir::Expr { .. }) => {
|
||||
let parent_hid = hir.parent_id(hir_id);
|
||||
if parent_hid != hir_id { self.describe_enclosure(parent_hid) } else { None }
|
||||
}
|
||||
}) => Some(self.describe_closure(*kind)),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
@ -156,12 +132,7 @@ fn on_unimplemented_note(
|
||||
// FIXME(-Zlower-impl-trait-in-trait-to-assoc-ty): HIR is not present for RPITITs,
|
||||
// but I guess we could synthesize one here. We don't see any errors that rely on
|
||||
// that yet, though.
|
||||
let enclosure =
|
||||
if let Some(body_hir) = self.tcx.opt_local_def_id_to_hir_id(obligation.cause.body_id) {
|
||||
self.describe_enclosure(body_hir).map(|s| s.to_owned())
|
||||
} else {
|
||||
None
|
||||
};
|
||||
let enclosure = self.describe_enclosure(obligation.cause.body_id).map(|t| t.to_owned());
|
||||
flags.push((sym::ItemContext, enclosure));
|
||||
|
||||
match obligation.cause.code() {
|
||||
|
@ -3564,55 +3564,52 @@ fn suggest_await_before_try(
|
||||
trait_pred: ty::PolyTraitPredicate<'tcx>,
|
||||
span: Span,
|
||||
) {
|
||||
if let Some(body_id) = self.tcx.hir().maybe_body_owned_by(obligation.cause.body_id) {
|
||||
let body = self.tcx.hir().body(body_id);
|
||||
if let Some(hir::CoroutineKind::Desugared(hir::CoroutineDesugaring::Async, _)) =
|
||||
body.coroutine_kind
|
||||
if let Some(hir::CoroutineKind::Desugared(hir::CoroutineDesugaring::Async, _)) =
|
||||
self.tcx.coroutine_kind(obligation.cause.body_id)
|
||||
{
|
||||
let future_trait = self.tcx.require_lang_item(LangItem::Future, None);
|
||||
|
||||
let self_ty = self.resolve_vars_if_possible(trait_pred.self_ty());
|
||||
let impls_future = self.type_implements_trait(
|
||||
future_trait,
|
||||
[self.tcx.instantiate_bound_regions_with_erased(self_ty)],
|
||||
obligation.param_env,
|
||||
);
|
||||
if !impls_future.must_apply_modulo_regions() {
|
||||
return;
|
||||
}
|
||||
|
||||
let item_def_id = self.tcx.associated_item_def_ids(future_trait)[0];
|
||||
// `<T as Future>::Output`
|
||||
let projection_ty = trait_pred.map_bound(|trait_pred| {
|
||||
Ty::new_projection(
|
||||
self.tcx,
|
||||
item_def_id,
|
||||
// Future::Output has no args
|
||||
[trait_pred.self_ty()],
|
||||
)
|
||||
});
|
||||
let InferOk { value: projection_ty, .. } =
|
||||
self.at(&obligation.cause, obligation.param_env).normalize(projection_ty);
|
||||
|
||||
debug!(
|
||||
normalized_projection_type = ?self.resolve_vars_if_possible(projection_ty)
|
||||
);
|
||||
let try_obligation = self.mk_trait_obligation_with_new_self_ty(
|
||||
obligation.param_env,
|
||||
trait_pred.map_bound(|trait_pred| (trait_pred, projection_ty.skip_binder())),
|
||||
);
|
||||
debug!(try_trait_obligation = ?try_obligation);
|
||||
if self.predicate_may_hold(&try_obligation)
|
||||
&& let Ok(snippet) = self.tcx.sess.source_map().span_to_snippet(span)
|
||||
&& snippet.ends_with('?')
|
||||
{
|
||||
let future_trait = self.tcx.require_lang_item(LangItem::Future, None);
|
||||
|
||||
let self_ty = self.resolve_vars_if_possible(trait_pred.self_ty());
|
||||
let impls_future = self.type_implements_trait(
|
||||
future_trait,
|
||||
[self.tcx.instantiate_bound_regions_with_erased(self_ty)],
|
||||
obligation.param_env,
|
||||
err.span_suggestion_verbose(
|
||||
span.with_hi(span.hi() - BytePos(1)).shrink_to_hi(),
|
||||
"consider `await`ing on the `Future`",
|
||||
".await",
|
||||
Applicability::MaybeIncorrect,
|
||||
);
|
||||
if !impls_future.must_apply_modulo_regions() {
|
||||
return;
|
||||
}
|
||||
|
||||
let item_def_id = self.tcx.associated_item_def_ids(future_trait)[0];
|
||||
// `<T as Future>::Output`
|
||||
let projection_ty = trait_pred.map_bound(|trait_pred| {
|
||||
Ty::new_projection(
|
||||
self.tcx,
|
||||
item_def_id,
|
||||
// Future::Output has no args
|
||||
[trait_pred.self_ty()],
|
||||
)
|
||||
});
|
||||
let InferOk { value: projection_ty, .. } =
|
||||
self.at(&obligation.cause, obligation.param_env).normalize(projection_ty);
|
||||
|
||||
debug!(
|
||||
normalized_projection_type = ?self.resolve_vars_if_possible(projection_ty)
|
||||
);
|
||||
let try_obligation = self.mk_trait_obligation_with_new_self_ty(
|
||||
obligation.param_env,
|
||||
trait_pred.map_bound(|trait_pred| (trait_pred, projection_ty.skip_binder())),
|
||||
);
|
||||
debug!(try_trait_obligation = ?try_obligation);
|
||||
if self.predicate_may_hold(&try_obligation)
|
||||
&& let Ok(snippet) = self.tcx.sess.source_map().span_to_snippet(span)
|
||||
&& snippet.ends_with('?')
|
||||
{
|
||||
err.span_suggestion_verbose(
|
||||
span.with_hi(span.hi() - BytePos(1)).shrink_to_hi(),
|
||||
"consider `await`ing on the `Future`",
|
||||
".await",
|
||||
Applicability::MaybeIncorrect,
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -4665,13 +4662,7 @@ fn visit_expr(&mut self, ex: &'v hir::Expr<'v>) {
|
||||
|
||||
fn visit_body(&mut self, body: &'v hir::Body<'v>) {
|
||||
assert!(!self.in_block_tail);
|
||||
if body.coroutine_kind().is_none() {
|
||||
if let hir::ExprKind::Block(block, None) = body.value.kind {
|
||||
if block.expr.is_some() {
|
||||
self.in_block_tail = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
self.in_block_tail = true;
|
||||
hir::intravisit::walk_body(self, body);
|
||||
}
|
||||
}
|
||||
|
@ -1348,7 +1348,7 @@ fn fuzzy_match_tys(
|
||||
ignoring_lifetimes: bool,
|
||||
) -> Option<CandidateSimilarity>;
|
||||
|
||||
fn describe_coroutine(&self, body_id: hir::BodyId) -> Option<&'static str>;
|
||||
fn describe_closure(&self, kind: hir::ClosureKind) -> &'static str;
|
||||
|
||||
fn find_similar_impl_candidates(
|
||||
&self,
|
||||
@ -1925,46 +1925,49 @@ fn type_category(tcx: TyCtxt<'_>, t: Ty<'_>) -> Option<u32> {
|
||||
}
|
||||
}
|
||||
|
||||
fn describe_coroutine(&self, body_id: hir::BodyId) -> Option<&'static str> {
|
||||
self.tcx.hir().body(body_id).coroutine_kind.map(|coroutine_source| match coroutine_source {
|
||||
hir::CoroutineKind::Coroutine => "a coroutine",
|
||||
hir::CoroutineKind::Desugared(
|
||||
hir::CoroutineDesugaring::Async,
|
||||
hir::CoroutineSource::Block,
|
||||
) => "an async block",
|
||||
hir::CoroutineKind::Desugared(
|
||||
hir::CoroutineDesugaring::Async,
|
||||
hir::CoroutineSource::Fn,
|
||||
) => "an async function",
|
||||
hir::CoroutineKind::Desugared(
|
||||
hir::CoroutineDesugaring::Async,
|
||||
hir::CoroutineSource::Closure,
|
||||
) => "an async closure",
|
||||
hir::CoroutineKind::Desugared(
|
||||
hir::CoroutineDesugaring::AsyncGen,
|
||||
hir::CoroutineSource::Block,
|
||||
) => "an async gen block",
|
||||
hir::CoroutineKind::Desugared(
|
||||
hir::CoroutineDesugaring::AsyncGen,
|
||||
hir::CoroutineSource::Fn,
|
||||
) => "an async gen function",
|
||||
hir::CoroutineKind::Desugared(
|
||||
hir::CoroutineDesugaring::AsyncGen,
|
||||
hir::CoroutineSource::Closure,
|
||||
) => "an async gen closure",
|
||||
hir::CoroutineKind::Desugared(
|
||||
hir::CoroutineDesugaring::Gen,
|
||||
hir::CoroutineSource::Block,
|
||||
) => "a gen block",
|
||||
hir::CoroutineKind::Desugared(
|
||||
hir::CoroutineDesugaring::Gen,
|
||||
hir::CoroutineSource::Fn,
|
||||
) => "a gen function",
|
||||
hir::CoroutineKind::Desugared(
|
||||
hir::CoroutineDesugaring::Gen,
|
||||
hir::CoroutineSource::Closure,
|
||||
) => "a gen closure",
|
||||
})
|
||||
fn describe_closure(&self, kind: hir::ClosureKind) -> &'static str {
|
||||
match kind {
|
||||
hir::ClosureKind::Closure => "a closure",
|
||||
hir::ClosureKind::Coroutine(kind, _) => match kind {
|
||||
hir::CoroutineKind::Coroutine => "a coroutine",
|
||||
hir::CoroutineKind::Desugared(
|
||||
hir::CoroutineDesugaring::Async,
|
||||
hir::CoroutineSource::Block,
|
||||
) => "an async block",
|
||||
hir::CoroutineKind::Desugared(
|
||||
hir::CoroutineDesugaring::Async,
|
||||
hir::CoroutineSource::Fn,
|
||||
) => "an async function",
|
||||
hir::CoroutineKind::Desugared(
|
||||
hir::CoroutineDesugaring::Async,
|
||||
hir::CoroutineSource::Closure,
|
||||
) => "an async closure",
|
||||
hir::CoroutineKind::Desugared(
|
||||
hir::CoroutineDesugaring::AsyncGen,
|
||||
hir::CoroutineSource::Block,
|
||||
) => "an async gen block",
|
||||
hir::CoroutineKind::Desugared(
|
||||
hir::CoroutineDesugaring::AsyncGen,
|
||||
hir::CoroutineSource::Fn,
|
||||
) => "an async gen function",
|
||||
hir::CoroutineKind::Desugared(
|
||||
hir::CoroutineDesugaring::AsyncGen,
|
||||
hir::CoroutineSource::Closure,
|
||||
) => "an async gen closure",
|
||||
hir::CoroutineKind::Desugared(
|
||||
hir::CoroutineDesugaring::Gen,
|
||||
hir::CoroutineSource::Block,
|
||||
) => "a gen block",
|
||||
hir::CoroutineKind::Desugared(
|
||||
hir::CoroutineDesugaring::Gen,
|
||||
hir::CoroutineSource::Fn,
|
||||
) => "a gen function",
|
||||
hir::CoroutineKind::Desugared(
|
||||
hir::CoroutineDesugaring::Gen,
|
||||
hir::CoroutineSource::Closure,
|
||||
) => "a gen closure",
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
fn find_similar_impl_candidates(
|
||||
|
@ -125,9 +125,9 @@ hir-stats ExprField 40 ( 0.4%) 1 40
|
||||
hir-stats TraitItemRef 56 ( 0.6%) 2 28
|
||||
hir-stats Local 64 ( 0.7%) 1 64
|
||||
hir-stats Param 64 ( 0.7%) 2 32
|
||||
hir-stats Body 72 ( 0.8%) 3 24
|
||||
hir-stats InlineAsm 72 ( 0.8%) 1 72
|
||||
hir-stats ImplItemRef 72 ( 0.8%) 2 36
|
||||
hir-stats Body 96 ( 1.1%) 3 32
|
||||
hir-stats FieldDef 96 ( 1.1%) 2 48
|
||||
hir-stats Arm 96 ( 1.1%) 2 48
|
||||
hir-stats Stmt 96 ( 1.1%) 3 32
|
||||
@ -146,7 +146,7 @@ hir-stats - Trait 192 ( 2.1%) 4
|
||||
hir-stats WherePredicate 192 ( 2.1%) 3 64
|
||||
hir-stats - BoundPredicate 192 ( 2.1%) 3
|
||||
hir-stats Block 288 ( 3.2%) 6 48
|
||||
hir-stats Pat 360 ( 3.9%) 5 72
|
||||
hir-stats Pat 360 ( 4.0%) 5 72
|
||||
hir-stats - Wild 72 ( 0.8%) 1
|
||||
hir-stats - Struct 72 ( 0.8%) 1
|
||||
hir-stats - Binding 216 ( 2.4%) 3
|
||||
@ -172,7 +172,7 @@ hir-stats - Impl 88 ( 1.0%) 1
|
||||
hir-stats - Fn 176 ( 1.9%) 2
|
||||
hir-stats - Use 352 ( 3.9%) 4
|
||||
hir-stats Path 1_240 (13.6%) 31 40
|
||||
hir-stats PathSegment 1_920 (21.0%) 40 48
|
||||
hir-stats PathSegment 1_920 (21.1%) 40 48
|
||||
hir-stats ----------------------------------------------------------------
|
||||
hir-stats Total 9_136
|
||||
hir-stats Total 9_112
|
||||
hir-stats
|
||||
|
Loading…
Reference in New Issue
Block a user