Refactor rustc_hir_typeck::closure.
This commit is contained in:
parent
2c4b0b29cf
commit
e82c08f58e
@ -26,10 +26,12 @@ pub(super) fn check_fn<'a, 'tcx>(
|
|||||||
param_env: ty::ParamEnv<'tcx>,
|
param_env: ty::ParamEnv<'tcx>,
|
||||||
fn_sig: ty::FnSig<'tcx>,
|
fn_sig: ty::FnSig<'tcx>,
|
||||||
decl: &'tcx hir::FnDecl<'tcx>,
|
decl: &'tcx hir::FnDecl<'tcx>,
|
||||||
fn_id: hir::HirId,
|
fn_def_id: LocalDefId,
|
||||||
body: &'tcx hir::Body<'tcx>,
|
body: &'tcx hir::Body<'tcx>,
|
||||||
can_be_generator: Option<hir::Movability>,
|
can_be_generator: Option<hir::Movability>,
|
||||||
) -> (FnCtxt<'a, 'tcx>, Option<GeneratorTypes<'tcx>>) {
|
) -> (FnCtxt<'a, 'tcx>, Option<GeneratorTypes<'tcx>>) {
|
||||||
|
let fn_id = inherited.tcx.hir().local_def_id_to_hir_id(fn_def_id);
|
||||||
|
|
||||||
// Create the function context. This is either derived from scratch or,
|
// Create the function context. This is either derived from scratch or,
|
||||||
// in the case of closures, based on the outer context.
|
// in the case of closures, based on the outer context.
|
||||||
let mut fcx = FnCtxt::new(inherited, param_env, body.value.hir_id);
|
let mut fcx = FnCtxt::new(inherited, param_env, body.value.hir_id);
|
||||||
|
@ -4,7 +4,7 @@ use super::{check_fn, Expectation, FnCtxt, GeneratorTypes};
|
|||||||
|
|
||||||
use hir::def::DefKind;
|
use hir::def::DefKind;
|
||||||
use rustc_hir as hir;
|
use rustc_hir as hir;
|
||||||
use rustc_hir::def_id::DefId;
|
use rustc_hir::def_id::LocalDefId;
|
||||||
use rustc_hir::lang_items::LangItem;
|
use rustc_hir::lang_items::LangItem;
|
||||||
use rustc_hir_analysis::astconv::AstConv;
|
use rustc_hir_analysis::astconv::AstConv;
|
||||||
use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
|
use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
|
||||||
@ -41,18 +41,14 @@ struct ClosureSignatures<'tcx> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||||
#[instrument(skip(self, expr, _capture, decl, body_id), level = "debug")]
|
#[instrument(skip(self, closure), level = "debug")]
|
||||||
pub fn check_expr_closure(
|
pub fn check_expr_closure(
|
||||||
&self,
|
&self,
|
||||||
expr: &hir::Expr<'_>,
|
closure: &hir::Closure<'tcx>,
|
||||||
_capture: hir::CaptureBy,
|
expr_span: Span,
|
||||||
decl: &'tcx hir::FnDecl<'tcx>,
|
|
||||||
body_id: hir::BodyId,
|
|
||||||
gen: Option<hir::Movability>,
|
|
||||||
expected: Expectation<'tcx>,
|
expected: Expectation<'tcx>,
|
||||||
) -> Ty<'tcx> {
|
) -> Ty<'tcx> {
|
||||||
trace!("decl = {:#?}", decl);
|
trace!("decl = {:#?}", closure.fn_decl);
|
||||||
trace!("expr = {:#?}", expr);
|
|
||||||
|
|
||||||
// It's always helpful for inference if we know the kind of
|
// It's always helpful for inference if we know the kind of
|
||||||
// closure sooner rather than later, so first examine the expected
|
// closure sooner rather than later, so first examine the expected
|
||||||
@ -61,26 +57,25 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||||||
Some(ty) => self.deduce_expectations_from_expected_type(ty),
|
Some(ty) => self.deduce_expectations_from_expected_type(ty),
|
||||||
None => (None, None),
|
None => (None, None),
|
||||||
};
|
};
|
||||||
let body = self.tcx.hir().body(body_id);
|
let body = self.tcx.hir().body(closure.body);
|
||||||
self.check_closure(expr, expected_kind, decl, body, gen, expected_sig)
|
self.check_closure(closure, expr_span, expected_kind, body, expected_sig)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[instrument(skip(self, expr, body, decl), level = "debug", ret)]
|
#[instrument(skip(self, closure, body), level = "debug", ret)]
|
||||||
fn check_closure(
|
fn check_closure(
|
||||||
&self,
|
&self,
|
||||||
expr: &hir::Expr<'_>,
|
closure: &hir::Closure<'tcx>,
|
||||||
|
expr_span: Span,
|
||||||
opt_kind: Option<ty::ClosureKind>,
|
opt_kind: Option<ty::ClosureKind>,
|
||||||
decl: &'tcx hir::FnDecl<'tcx>,
|
|
||||||
body: &'tcx hir::Body<'tcx>,
|
body: &'tcx hir::Body<'tcx>,
|
||||||
gen: Option<hir::Movability>,
|
|
||||||
expected_sig: Option<ExpectedSig<'tcx>>,
|
expected_sig: Option<ExpectedSig<'tcx>>,
|
||||||
) -> Ty<'tcx> {
|
) -> Ty<'tcx> {
|
||||||
trace!("decl = {:#?}", decl);
|
trace!("decl = {:#?}", closure.fn_decl);
|
||||||
let expr_def_id = self.tcx.hir().local_def_id(expr.hir_id);
|
let expr_def_id = closure.def_id;
|
||||||
debug!(?expr_def_id);
|
debug!(?expr_def_id);
|
||||||
|
|
||||||
let ClosureSignatures { bound_sig, liberated_sig } =
|
let ClosureSignatures { bound_sig, liberated_sig } =
|
||||||
self.sig_of_closure(expr.hir_id, expr_def_id.to_def_id(), decl, body, expected_sig);
|
self.sig_of_closure(expr_def_id, closure.fn_decl, body, expected_sig);
|
||||||
|
|
||||||
debug!(?bound_sig, ?liberated_sig);
|
debug!(?bound_sig, ?liberated_sig);
|
||||||
|
|
||||||
@ -88,10 +83,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||||||
self,
|
self,
|
||||||
self.param_env.without_const(),
|
self.param_env.without_const(),
|
||||||
liberated_sig,
|
liberated_sig,
|
||||||
decl,
|
closure.fn_decl,
|
||||||
expr.hir_id,
|
expr_def_id,
|
||||||
body,
|
body,
|
||||||
gen,
|
closure.movability,
|
||||||
)
|
)
|
||||||
.1;
|
.1;
|
||||||
|
|
||||||
@ -102,7 +97,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||||||
|
|
||||||
let tupled_upvars_ty = self.next_ty_var(TypeVariableOrigin {
|
let tupled_upvars_ty = self.next_ty_var(TypeVariableOrigin {
|
||||||
kind: TypeVariableOriginKind::ClosureSynthetic,
|
kind: TypeVariableOriginKind::ClosureSynthetic,
|
||||||
span: self.tcx.hir().span(expr.hir_id),
|
span: self.tcx.def_span(expr_def_id),
|
||||||
});
|
});
|
||||||
|
|
||||||
if let Some(GeneratorTypes { resume_ty, yield_ty, interior, movability }) = generator_types
|
if let Some(GeneratorTypes { resume_ty, yield_ty, interior, movability }) = generator_types
|
||||||
@ -148,7 +143,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||||||
None => self.next_ty_var(TypeVariableOrigin {
|
None => self.next_ty_var(TypeVariableOrigin {
|
||||||
// FIXME(eddyb) distinguish closure kind inference variables from the rest.
|
// FIXME(eddyb) distinguish closure kind inference variables from the rest.
|
||||||
kind: TypeVariableOriginKind::ClosureSynthetic,
|
kind: TypeVariableOriginKind::ClosureSynthetic,
|
||||||
span: expr.span,
|
span: expr_span,
|
||||||
}),
|
}),
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -342,30 +337,28 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||||||
|
|
||||||
fn sig_of_closure(
|
fn sig_of_closure(
|
||||||
&self,
|
&self,
|
||||||
hir_id: hir::HirId,
|
expr_def_id: LocalDefId,
|
||||||
expr_def_id: DefId,
|
|
||||||
decl: &hir::FnDecl<'_>,
|
decl: &hir::FnDecl<'_>,
|
||||||
body: &hir::Body<'_>,
|
body: &hir::Body<'_>,
|
||||||
expected_sig: Option<ExpectedSig<'tcx>>,
|
expected_sig: Option<ExpectedSig<'tcx>>,
|
||||||
) -> ClosureSignatures<'tcx> {
|
) -> ClosureSignatures<'tcx> {
|
||||||
if let Some(e) = expected_sig {
|
if let Some(e) = expected_sig {
|
||||||
self.sig_of_closure_with_expectation(hir_id, expr_def_id, decl, body, e)
|
self.sig_of_closure_with_expectation(expr_def_id, decl, body, e)
|
||||||
} else {
|
} else {
|
||||||
self.sig_of_closure_no_expectation(hir_id, expr_def_id, decl, body)
|
self.sig_of_closure_no_expectation(expr_def_id, decl, body)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// If there is no expected signature, then we will convert the
|
/// If there is no expected signature, then we will convert the
|
||||||
/// types that the user gave into a signature.
|
/// types that the user gave into a signature.
|
||||||
#[instrument(skip(self, hir_id, expr_def_id, decl, body), level = "debug")]
|
#[instrument(skip(self, expr_def_id, decl, body), level = "debug")]
|
||||||
fn sig_of_closure_no_expectation(
|
fn sig_of_closure_no_expectation(
|
||||||
&self,
|
&self,
|
||||||
hir_id: hir::HirId,
|
expr_def_id: LocalDefId,
|
||||||
expr_def_id: DefId,
|
|
||||||
decl: &hir::FnDecl<'_>,
|
decl: &hir::FnDecl<'_>,
|
||||||
body: &hir::Body<'_>,
|
body: &hir::Body<'_>,
|
||||||
) -> ClosureSignatures<'tcx> {
|
) -> ClosureSignatures<'tcx> {
|
||||||
let bound_sig = self.supplied_sig_of_closure(hir_id, expr_def_id, decl, body);
|
let bound_sig = self.supplied_sig_of_closure(expr_def_id, decl, body);
|
||||||
|
|
||||||
self.closure_sigs(expr_def_id, body, bound_sig)
|
self.closure_sigs(expr_def_id, body, bound_sig)
|
||||||
}
|
}
|
||||||
@ -411,17 +404,16 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||||||
///
|
///
|
||||||
/// # Arguments
|
/// # Arguments
|
||||||
///
|
///
|
||||||
/// - `expr_def_id`: the `DefId` of the closure expression
|
/// - `expr_def_id`: the `LocalDefId` of the closure expression
|
||||||
/// - `decl`: the HIR declaration of the closure
|
/// - `decl`: the HIR declaration of the closure
|
||||||
/// - `body`: the body of the closure
|
/// - `body`: the body of the closure
|
||||||
/// - `expected_sig`: the expected signature (if any). Note that
|
/// - `expected_sig`: the expected signature (if any). Note that
|
||||||
/// this is missing a binder: that is, there may be late-bound
|
/// this is missing a binder: that is, there may be late-bound
|
||||||
/// regions with depth 1, which are bound then by the closure.
|
/// regions with depth 1, which are bound then by the closure.
|
||||||
#[instrument(skip(self, hir_id, expr_def_id, decl, body), level = "debug")]
|
#[instrument(skip(self, expr_def_id, decl, body), level = "debug")]
|
||||||
fn sig_of_closure_with_expectation(
|
fn sig_of_closure_with_expectation(
|
||||||
&self,
|
&self,
|
||||||
hir_id: hir::HirId,
|
expr_def_id: LocalDefId,
|
||||||
expr_def_id: DefId,
|
|
||||||
decl: &hir::FnDecl<'_>,
|
decl: &hir::FnDecl<'_>,
|
||||||
body: &hir::Body<'_>,
|
body: &hir::Body<'_>,
|
||||||
expected_sig: ExpectedSig<'tcx>,
|
expected_sig: ExpectedSig<'tcx>,
|
||||||
@ -430,7 +422,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||||||
// expectation if things don't see to match up with what we
|
// expectation if things don't see to match up with what we
|
||||||
// expect.
|
// expect.
|
||||||
if expected_sig.sig.c_variadic() != decl.c_variadic {
|
if expected_sig.sig.c_variadic() != decl.c_variadic {
|
||||||
return self.sig_of_closure_no_expectation(hir_id, expr_def_id, decl, body);
|
return self.sig_of_closure_no_expectation(expr_def_id, decl, body);
|
||||||
} else if expected_sig.sig.skip_binder().inputs_and_output.len() != decl.inputs.len() + 1 {
|
} 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(
|
return self.sig_of_closure_with_mismatched_number_of_arguments(
|
||||||
expr_def_id,
|
expr_def_id,
|
||||||
@ -466,27 +458,21 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||||||
// Along the way, it also writes out entries for types that the user
|
// Along the way, it also writes out entries for types that the user
|
||||||
// wrote into our typeck results, which are then later used by the privacy
|
// wrote into our typeck results, which are then later used by the privacy
|
||||||
// check.
|
// check.
|
||||||
match self.merge_supplied_sig_with_expectation(
|
match self.merge_supplied_sig_with_expectation(expr_def_id, decl, body, closure_sigs) {
|
||||||
hir_id,
|
|
||||||
expr_def_id,
|
|
||||||
decl,
|
|
||||||
body,
|
|
||||||
closure_sigs,
|
|
||||||
) {
|
|
||||||
Ok(infer_ok) => self.register_infer_ok_obligations(infer_ok),
|
Ok(infer_ok) => self.register_infer_ok_obligations(infer_ok),
|
||||||
Err(_) => self.sig_of_closure_no_expectation(hir_id, expr_def_id, decl, body),
|
Err(_) => self.sig_of_closure_no_expectation(expr_def_id, decl, body),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn sig_of_closure_with_mismatched_number_of_arguments(
|
fn sig_of_closure_with_mismatched_number_of_arguments(
|
||||||
&self,
|
&self,
|
||||||
expr_def_id: DefId,
|
expr_def_id: LocalDefId,
|
||||||
decl: &hir::FnDecl<'_>,
|
decl: &hir::FnDecl<'_>,
|
||||||
body: &hir::Body<'_>,
|
body: &hir::Body<'_>,
|
||||||
expected_sig: ExpectedSig<'tcx>,
|
expected_sig: ExpectedSig<'tcx>,
|
||||||
) -> ClosureSignatures<'tcx> {
|
) -> ClosureSignatures<'tcx> {
|
||||||
let hir = self.tcx.hir();
|
let hir = self.tcx.hir();
|
||||||
let expr_map_node = hir.get_if_local(expr_def_id).unwrap();
|
let expr_map_node = hir.get_by_def_id(expr_def_id);
|
||||||
let expected_args: Vec<_> = expected_sig
|
let expected_args: Vec<_> = expected_sig
|
||||||
.sig
|
.sig
|
||||||
.skip_binder()
|
.skip_binder()
|
||||||
@ -499,7 +485,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||||||
None => (None, Vec::new()),
|
None => (None, Vec::new()),
|
||||||
};
|
};
|
||||||
let expected_span =
|
let expected_span =
|
||||||
expected_sig.cause_span.unwrap_or_else(|| hir.span_if_local(expr_def_id).unwrap());
|
expected_sig.cause_span.unwrap_or_else(|| self.tcx.def_span(expr_def_id));
|
||||||
self.report_arg_count_mismatch(
|
self.report_arg_count_mismatch(
|
||||||
expected_span,
|
expected_span,
|
||||||
closure_span,
|
closure_span,
|
||||||
@ -517,11 +503,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||||||
/// Enforce the user's types against the expectation. See
|
/// Enforce the user's types against the expectation. See
|
||||||
/// `sig_of_closure_with_expectation` for details on the overall
|
/// `sig_of_closure_with_expectation` for details on the overall
|
||||||
/// strategy.
|
/// strategy.
|
||||||
#[instrument(level = "debug", skip(self, hir_id, expr_def_id, decl, body, expected_sigs))]
|
#[instrument(level = "debug", skip(self, expr_def_id, decl, body, expected_sigs))]
|
||||||
fn merge_supplied_sig_with_expectation(
|
fn merge_supplied_sig_with_expectation(
|
||||||
&self,
|
&self,
|
||||||
hir_id: hir::HirId,
|
expr_def_id: LocalDefId,
|
||||||
expr_def_id: DefId,
|
|
||||||
decl: &hir::FnDecl<'_>,
|
decl: &hir::FnDecl<'_>,
|
||||||
body: &hir::Body<'_>,
|
body: &hir::Body<'_>,
|
||||||
mut expected_sigs: ClosureSignatures<'tcx>,
|
mut expected_sigs: ClosureSignatures<'tcx>,
|
||||||
@ -530,7 +515,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||||||
//
|
//
|
||||||
// (See comment on `sig_of_closure_with_expectation` for the
|
// (See comment on `sig_of_closure_with_expectation` for the
|
||||||
// meaning of these letters.)
|
// meaning of these letters.)
|
||||||
let supplied_sig = self.supplied_sig_of_closure(hir_id, expr_def_id, decl, body);
|
let supplied_sig = self.supplied_sig_of_closure(expr_def_id, decl, body);
|
||||||
|
|
||||||
debug!(?supplied_sig);
|
debug!(?supplied_sig);
|
||||||
|
|
||||||
@ -610,8 +595,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||||||
#[instrument(skip(self, decl, body), level = "debug", ret)]
|
#[instrument(skip(self, decl, body), level = "debug", ret)]
|
||||||
fn supplied_sig_of_closure(
|
fn supplied_sig_of_closure(
|
||||||
&self,
|
&self,
|
||||||
hir_id: hir::HirId,
|
expr_def_id: LocalDefId,
|
||||||
expr_def_id: DefId,
|
|
||||||
decl: &hir::FnDecl<'_>,
|
decl: &hir::FnDecl<'_>,
|
||||||
body: &hir::Body<'_>,
|
body: &hir::Body<'_>,
|
||||||
) -> ty::PolyFnSig<'tcx> {
|
) -> ty::PolyFnSig<'tcx> {
|
||||||
@ -620,6 +604,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||||||
trace!("decl = {:#?}", decl);
|
trace!("decl = {:#?}", decl);
|
||||||
debug!(?body.generator_kind);
|
debug!(?body.generator_kind);
|
||||||
|
|
||||||
|
let hir_id = self.tcx.hir().local_def_id_to_hir_id(expr_def_id);
|
||||||
let bound_vars = self.tcx.late_bound_vars(hir_id);
|
let bound_vars = self.tcx.late_bound_vars(hir_id);
|
||||||
|
|
||||||
// First, convert the types that the user supplied (if any).
|
// First, convert the types that the user supplied (if any).
|
||||||
@ -664,10 +649,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||||||
let result = self.normalize_associated_types_in(self.tcx.hir().span(hir_id), result);
|
let result = self.normalize_associated_types_in(self.tcx.hir().span(hir_id), result);
|
||||||
|
|
||||||
let c_result = self.inh.infcx.canonicalize_response(result);
|
let c_result = self.inh.infcx.canonicalize_response(result);
|
||||||
self.typeck_results
|
self.typeck_results.borrow_mut().user_provided_sigs.insert(expr_def_id, c_result);
|
||||||
.borrow_mut()
|
|
||||||
.user_provided_sigs
|
|
||||||
.insert(expr_def_id.expect_local(), c_result);
|
|
||||||
|
|
||||||
result
|
result
|
||||||
}
|
}
|
||||||
@ -681,7 +663,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||||||
#[instrument(skip(self), level = "debug", ret)]
|
#[instrument(skip(self), level = "debug", ret)]
|
||||||
fn deduce_future_output_from_obligations(
|
fn deduce_future_output_from_obligations(
|
||||||
&self,
|
&self,
|
||||||
expr_def_id: DefId,
|
expr_def_id: LocalDefId,
|
||||||
body_id: hir::HirId,
|
body_id: hir::HirId,
|
||||||
) -> Option<Ty<'tcx>> {
|
) -> Option<Ty<'tcx>> {
|
||||||
let ret_coercion = self.ret_coercion.as_ref().unwrap_or_else(|| {
|
let ret_coercion = self.ret_coercion.as_ref().unwrap_or_else(|| {
|
||||||
@ -830,14 +812,15 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||||||
|
|
||||||
fn closure_sigs(
|
fn closure_sigs(
|
||||||
&self,
|
&self,
|
||||||
expr_def_id: DefId,
|
expr_def_id: LocalDefId,
|
||||||
body: &hir::Body<'_>,
|
body: &hir::Body<'_>,
|
||||||
bound_sig: ty::PolyFnSig<'tcx>,
|
bound_sig: ty::PolyFnSig<'tcx>,
|
||||||
) -> ClosureSignatures<'tcx> {
|
) -> ClosureSignatures<'tcx> {
|
||||||
let liberated_sig = self.tcx().liberate_late_bound_regions(expr_def_id, bound_sig);
|
let liberated_sig =
|
||||||
|
self.tcx().liberate_late_bound_regions(expr_def_id.to_def_id(), bound_sig);
|
||||||
let liberated_sig = self.inh.normalize_associated_types_in(
|
let liberated_sig = self.inh.normalize_associated_types_in(
|
||||||
body.value.span,
|
body.value.span,
|
||||||
body.value.hir_id,
|
self.tcx.hir().local_def_id_to_hir_id(expr_def_id),
|
||||||
self.param_env,
|
self.param_env,
|
||||||
liberated_sig,
|
liberated_sig,
|
||||||
);
|
);
|
||||||
|
@ -30,7 +30,7 @@ use rustc_hir::def::{CtorKind, DefKind, Res};
|
|||||||
use rustc_hir::def_id::DefId;
|
use rustc_hir::def_id::DefId;
|
||||||
use rustc_hir::intravisit::Visitor;
|
use rustc_hir::intravisit::Visitor;
|
||||||
use rustc_hir::lang_items::LangItem;
|
use rustc_hir::lang_items::LangItem;
|
||||||
use rustc_hir::{Closure, ExprKind, HirId, QPath};
|
use rustc_hir::{ExprKind, HirId, QPath};
|
||||||
use rustc_hir_analysis::astconv::AstConv as _;
|
use rustc_hir_analysis::astconv::AstConv as _;
|
||||||
use rustc_hir_analysis::check::ty_kind_suggestion;
|
use rustc_hir_analysis::check::ty_kind_suggestion;
|
||||||
use rustc_infer::infer;
|
use rustc_infer::infer;
|
||||||
@ -324,9 +324,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||||||
ExprKind::Match(discrim, arms, match_src) => {
|
ExprKind::Match(discrim, arms, match_src) => {
|
||||||
self.check_match(expr, &discrim, arms, expected, match_src)
|
self.check_match(expr, &discrim, arms, expected, match_src)
|
||||||
}
|
}
|
||||||
ExprKind::Closure(&Closure { capture_clause, fn_decl, body, movability, .. }) => {
|
ExprKind::Closure(closure) => self.check_expr_closure(closure, expr.span, expected),
|
||||||
self.check_expr_closure(expr, capture_clause, &fn_decl, body, movability, expected)
|
|
||||||
}
|
|
||||||
ExprKind::Block(body, _) => self.check_block_with_expected(&body, expected),
|
ExprKind::Block(body, _) => self.check_block_with_expected(&body, expected),
|
||||||
ExprKind::Call(callee, args) => self.check_call(expr, &callee, args, expected),
|
ExprKind::Call(callee, args) => self.check_call(expr, &callee, args, expected),
|
||||||
ExprKind::MethodCall(segment, receiver, args, _) => {
|
ExprKind::MethodCall(segment, receiver, args, _) => {
|
||||||
|
@ -352,8 +352,8 @@ impl<'a, 'tcx> ExprUseVisitor<'a, 'tcx> {
|
|||||||
self.consume_expr(base);
|
self.consume_expr(base);
|
||||||
}
|
}
|
||||||
|
|
||||||
hir::ExprKind::Closure { .. } => {
|
hir::ExprKind::Closure(closure) => {
|
||||||
self.walk_captures(expr);
|
self.walk_captures(closure);
|
||||||
}
|
}
|
||||||
|
|
||||||
hir::ExprKind::Box(ref base) => {
|
hir::ExprKind::Box(ref base) => {
|
||||||
@ -745,7 +745,7 @@ impl<'a, 'tcx> ExprUseVisitor<'a, 'tcx> {
|
|||||||
///
|
///
|
||||||
/// - When reporting the Place back to the Delegate, ensure that the UpvarId uses the enclosing
|
/// - When reporting the Place back to the Delegate, ensure that the UpvarId uses the enclosing
|
||||||
/// closure as the DefId.
|
/// closure as the DefId.
|
||||||
fn walk_captures(&mut self, closure_expr: &hir::Expr<'_>) {
|
fn walk_captures(&mut self, closure_expr: &hir::Closure<'_>) {
|
||||||
fn upvar_is_local_variable<'tcx>(
|
fn upvar_is_local_variable<'tcx>(
|
||||||
upvars: Option<&'tcx FxIndexMap<hir::HirId, hir::Upvar>>,
|
upvars: Option<&'tcx FxIndexMap<hir::HirId, hir::Upvar>>,
|
||||||
upvar_id: hir::HirId,
|
upvar_id: hir::HirId,
|
||||||
@ -757,7 +757,7 @@ impl<'a, 'tcx> ExprUseVisitor<'a, 'tcx> {
|
|||||||
debug!("walk_captures({:?})", closure_expr);
|
debug!("walk_captures({:?})", closure_expr);
|
||||||
|
|
||||||
let tcx = self.tcx();
|
let tcx = self.tcx();
|
||||||
let closure_def_id = tcx.hir().local_def_id(closure_expr.hir_id);
|
let closure_def_id = closure_expr.def_id;
|
||||||
let upvars = tcx.upvars_mentioned(self.body_owner);
|
let upvars = tcx.upvars_mentioned(self.body_owner);
|
||||||
|
|
||||||
// For purposes of this function, generator and closures are equivalent.
|
// For purposes of this function, generator and closures are equivalent.
|
||||||
@ -829,10 +829,11 @@ impl<'a, 'tcx> ExprUseVisitor<'a, 'tcx> {
|
|||||||
// be a local variable
|
// be a local variable
|
||||||
PlaceBase::Local(*var_hir_id)
|
PlaceBase::Local(*var_hir_id)
|
||||||
};
|
};
|
||||||
|
let closure_hir_id = tcx.hir().local_def_id_to_hir_id(closure_def_id);
|
||||||
let place_with_id = PlaceWithHirId::new(
|
let place_with_id = PlaceWithHirId::new(
|
||||||
capture_info.path_expr_id.unwrap_or(
|
capture_info
|
||||||
capture_info.capture_kind_expr_id.unwrap_or(closure_expr.hir_id),
|
.path_expr_id
|
||||||
),
|
.unwrap_or(capture_info.capture_kind_expr_id.unwrap_or(closure_hir_id)),
|
||||||
place.base_ty,
|
place.base_ty,
|
||||||
place_base,
|
place_base,
|
||||||
place.projections.clone(),
|
place.projections.clone(),
|
||||||
|
@ -251,7 +251,7 @@ fn typeck_with_fallback<'tcx>(
|
|||||||
param_env,
|
param_env,
|
||||||
fn_sig,
|
fn_sig,
|
||||||
);
|
);
|
||||||
check_fn(&inh, param_env, fn_sig, decl, id, body, None).0
|
check_fn(&inh, param_env, fn_sig, decl, def_id, body, None).0
|
||||||
} else {
|
} else {
|
||||||
let fcx = FnCtxt::new(&inh, param_env, body.value.hir_id);
|
let fcx = FnCtxt::new(&inh, param_env, body.value.hir_id);
|
||||||
let expected_type = body_ty
|
let expected_type = body_ty
|
||||||
|
Loading…
x
Reference in New Issue
Block a user