diff --git a/src/librustc_typeck/astconv.rs b/src/librustc_typeck/astconv.rs index 7cc8e067132f878257772434afd4ab46d0f30412..1471e235156eb8ade6a050fe0668ceb92e75565a 100644 --- a/src/librustc_typeck/astconv.rs +++ b/src/librustc_typeck/astconv.rs @@ -1206,65 +1206,6 @@ pub fn ty_of_fn(&self, bare_fn_ty } - pub fn ty_of_closure(&self, - unsafety: hir::Unsafety, - decl: &hir::FnDecl, - abi: abi::Abi, - expected_sig: Option>) - -> ty::PolyFnSig<'tcx> - { - debug!("ty_of_closure(expected_sig={:?})", - expected_sig); - - let input_tys = decl.inputs.iter().enumerate().map(|(i, a)| { - let expected_arg_ty = expected_sig.as_ref().and_then(|e| { - // no guarantee that the correct number of expected args - // were supplied - if i < e.inputs().len() { - Some(e.inputs()[i]) - } else { - None - } - }); - - let input_ty = self.ty_of_arg(a, expected_arg_ty); - debug!("ty_of_closure: i={} input_ty={:?} expected_arg_ty={:?}", - i, input_ty, expected_arg_ty); - - input_ty - }); - - let expected_ret_ty = expected_sig.as_ref().map(|e| e.output()); - - let output_ty = match decl.output { - hir::Return(ref output) => { - if let (&hir::TyInfer, Some(expected_ret_ty)) = (&output.node, expected_ret_ty) { - self.record_ty(output.hir_id, expected_ret_ty, output.span); - expected_ret_ty - } else { - self.ast_ty_to_ty(&output) - } - } - hir::DefaultReturn(span) => { - if let Some(expected_ret_ty) = expected_ret_ty { - expected_ret_ty - } else { - self.ty_infer(span) - } - } - }; - - debug!("ty_of_closure: output_ty={:?}", output_ty); - - ty::Binder(self.tcx().mk_fn_sig( - input_tys, - output_ty, - decl.variadic, - unsafety, - abi - )) - } - /// Given the bounds on an object, determines what single region bound (if any) we can /// use to summarize this type. The basic idea is that we will use the bound the user /// provided, if they provided one, and otherwise search the supertypes of trait bounds diff --git a/src/librustc_typeck/check/closure.rs b/src/librustc_typeck/check/closure.rs index 077050167db287bda9a2caa0da23686d2d8683a8..fac2119cb44d6357f3417d34f14ecf42dda589b6 100644 --- a/src/librustc_typeck/check/closure.rs +++ b/src/librustc_typeck/check/closure.rs @@ -56,11 +56,7 @@ fn check_closure(&self, expected_sig); let expr_def_id = self.tcx.hir.local_def_id(expr.id); - let sig = AstConv::ty_of_closure(self, - hir::Unsafety::Normal, - decl, - Abi::RustCall, - expected_sig); + let sig = self.ty_of_closure(decl, expected_sig); debug!("check_closure: ty_of_closure returns {:?}", sig); @@ -274,4 +270,72 @@ fn self_type_matches_expected_vid(&self, _ => None, } } + + /// Invoked to compute the signature of a closure expression. This + /// combines any user-provided type annotations (e.g., `|x: u32| + /// -> u32 { .. }`) with the expected signature. + /// + /// The arguments here are a bit odd-ball: + /// + /// - `decl`: the HIR declaration of the closure + /// - `expected_sig`: the expected signature (if any). Note that + /// this is missing a binder: that is, there may be late-bound + /// regions with depth 1, which are bound then by the closure. + fn ty_of_closure(&self, + decl: &hir::FnDecl, + expected_sig: Option>) + -> ty::PolyFnSig<'tcx> + { + let astconv: &AstConv = self; + + debug!("ty_of_closure(expected_sig={:?})", + expected_sig); + + let input_tys = decl.inputs.iter().enumerate().map(|(i, a)| { + let expected_arg_ty = expected_sig.as_ref().and_then(|e| { + // no guarantee that the correct number of expected args + // were supplied + if i < e.inputs().len() { + Some(e.inputs()[i]) + } else { + None + } + }); + + let input_ty = astconv.ty_of_arg(a, expected_arg_ty); + debug!("ty_of_closure: i={} input_ty={:?} expected_arg_ty={:?}", + i, input_ty, expected_arg_ty); + + input_ty + }); + + let expected_ret_ty = expected_sig.as_ref().map(|e| e.output()); + + let output_ty = match decl.output { + hir::Return(ref output) => { + if let (&hir::TyInfer, Some(expected_ret_ty)) = (&output.node, expected_ret_ty) { + astconv.record_ty(output.hir_id, expected_ret_ty, output.span); + expected_ret_ty + } else { + astconv.ast_ty_to_ty(&output) + } + } + hir::DefaultReturn(span) => { + if let Some(expected_ret_ty) = expected_ret_ty { + expected_ret_ty + } else { + astconv.ty_infer(span) + } + } + }; + + debug!("ty_of_closure: output_ty={:?}", output_ty); + + ty::Binder(self.tcx.mk_fn_sig( + input_tys, + output_ty, + decl.variadic, + hir::Unsafety::Normal, + Abi::RustCall)) + } }