diff --git a/src/librustc_typeck/check/callee.rs b/src/librustc_typeck/check/callee.rs index d4f639c070de3..727fbf7b30f67 100644 --- a/src/librustc_typeck/check/callee.rs +++ b/src/librustc_typeck/check/callee.rs @@ -1,16 +1,16 @@ -use super::{Expectation, FnCtxt, Needs, TupleArgumentsFlag}; use super::autoderef::Autoderef; use super::method::MethodCallee; +use super::{Expectation, FnCtxt, Needs, TupleArgumentsFlag}; +use errors::Applicability; use hir::def::Def; use hir::def_id::{DefId, LOCAL_CRATE}; +use rustc::ty::adjustment::{Adjust, Adjustment, AllowTwoPhase, AutoBorrow, AutoBorrowMutability}; +use rustc::ty::{self, Ty, TyCtxt, TypeFoldable}; use rustc::{infer, traits}; -use rustc::ty::{self, TyCtxt, TypeFoldable, Ty}; -use rustc::ty::adjustment::{Adjustment, Adjust, AllowTwoPhase, AutoBorrow, AutoBorrowMutability}; use rustc_target::spec::abi; use syntax::ast::Ident; use syntax_pos::Span; -use errors::Applicability; use rustc::hir; @@ -33,12 +33,13 @@ enum CallStep<'tcx> { } impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { - pub fn check_call(&self, - call_expr: &'gcx hir::Expr, - callee_expr: &'gcx hir::Expr, - arg_exprs: &'gcx [hir::Expr], - expected: Expectation<'tcx>) - -> Ty<'tcx> { + pub fn check_call( + &self, + call_expr: &'gcx hir::Expr, + callee_expr: &'gcx hir::Expr, + arg_exprs: &'gcx [hir::Expr], + expected: Expectation<'tcx>, + ) -> Ty<'tcx> { let original_callee_ty = self.check_expr(callee_expr); let expr_ty = self.structurally_resolved_type(call_expr.span, original_callee_ty); @@ -74,15 +75,17 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { output } - fn try_overloaded_call_step(&self, - call_expr: &'gcx hir::Expr, - callee_expr: &'gcx hir::Expr, - autoderef: &Autoderef<'a, 'gcx, 'tcx>) - -> Option> { + fn try_overloaded_call_step( + &self, + call_expr: &'gcx hir::Expr, + callee_expr: &'gcx hir::Expr, + autoderef: &Autoderef<'a, 'gcx, 'tcx>, + ) -> Option> { let adjusted_ty = autoderef.unambiguous_final_ty(self); - debug!("try_overloaded_call_step(call_expr={:?}, adjusted_ty={:?})", - call_expr, - adjusted_ty); + debug!( + "try_overloaded_call_step(call_expr={:?}, adjusted_ty={:?})", + call_expr, adjusted_ty + ); // If the callee is a bare function or a closure, then we're all set. match adjusted_ty.sty { @@ -100,21 +103,26 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { // fnmut vs fnonce. If so, we have to defer further processing. if self.closure_kind(def_id, substs).is_none() { let closure_ty = self.closure_sig(def_id, substs); - let fn_sig = self.replace_bound_vars_with_fresh_vars( - call_expr.span, - infer::FnCall, - &closure_ty - ).0; + let fn_sig = self + .replace_bound_vars_with_fresh_vars( + call_expr.span, + infer::FnCall, + &closure_ty, + ) + .0; let adjustments = autoderef.adjust_steps(self, Needs::None); - self.record_deferred_call_resolution(def_id, DeferredCallResolution { - call_expr, - callee_expr, - adjusted_ty, - adjustments, - fn_sig, - closure_def_id: def_id, - closure_substs: substs, - }); + self.record_deferred_call_resolution( + def_id, + DeferredCallResolution { + call_expr, + callee_expr, + adjusted_ty, + adjustments, + fn_sig, + closure_def_id: def_id, + closure_substs: substs, + }, + ); return Some(CallStep::DeferredClosure(fn_sig)); } } @@ -134,34 +142,50 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { _ => {} } - self.try_overloaded_call_traits(call_expr, adjusted_ty).map(|(autoref, method)| { - let mut adjustments = autoderef.adjust_steps(self, Needs::None); - adjustments.extend(autoref); - self.apply_adjustments(callee_expr, adjustments); - CallStep::Overloaded(method) - }) + self.try_overloaded_call_traits(call_expr, adjusted_ty) + .map(|(autoref, method)| { + let mut adjustments = autoderef.adjust_steps(self, Needs::None); + adjustments.extend(autoref); + self.apply_adjustments(callee_expr, adjustments); + CallStep::Overloaded(method) + }) } - fn try_overloaded_call_traits(&self, - call_expr: &hir::Expr, - adjusted_ty: Ty<'tcx>) - -> Option<(Option>, - MethodCallee<'tcx>)> { + fn try_overloaded_call_traits( + &self, + call_expr: &hir::Expr, + adjusted_ty: Ty<'tcx>, + ) -> Option<(Option>, MethodCallee<'tcx>)> { // Try the options that are least restrictive on the caller first. - for &(opt_trait_def_id, method_name, borrow) in - &[(self.tcx.lang_items().fn_trait(), Ident::from_str("call"), true), - (self.tcx.lang_items().fn_mut_trait(), Ident::from_str("call_mut"), true), - (self.tcx.lang_items().fn_once_trait(), Ident::from_str("call_once"), false)] { + for &(opt_trait_def_id, method_name, borrow) in &[ + ( + self.tcx.lang_items().fn_trait(), + Ident::from_str("call"), + true, + ), + ( + self.tcx.lang_items().fn_mut_trait(), + Ident::from_str("call_mut"), + true, + ), + ( + self.tcx.lang_items().fn_once_trait(), + Ident::from_str("call_once"), + false, + ), + ] { let trait_def_id = match opt_trait_def_id { Some(def_id) => def_id, None => continue, }; - if let Some(ok) = self.lookup_method_in_trait(call_expr.span, - method_name, - trait_def_id, - adjusted_ty, - None) { + if let Some(ok) = self.lookup_method_in_trait( + call_expr.span, + method_name, + trait_def_id, + adjusted_ty, + None, + ) { let method = self.register_infer_ok_obligations(ok); let mut autoref = None; if borrow { @@ -173,11 +197,11 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { // deployment, conservatively omit // overloaded function call ops. allow_two_phase_borrow: AllowTwoPhase::No, - } + }, }; autoref = Some(Adjustment { kind: Adjust::Borrow(AutoBorrow::Ref(region, mutbl)), - target: method.sig.inputs()[0] + target: method.sig.inputs()[0], }); } } @@ -188,16 +212,18 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { None } - fn confirm_builtin_call(&self, - call_expr: &hir::Expr, - callee_ty: Ty<'tcx>, - arg_exprs: &'gcx [hir::Expr], - expected: Expectation<'tcx>) - -> Ty<'tcx> { + fn confirm_builtin_call( + &self, + call_expr: &hir::Expr, + callee_ty: Ty<'tcx>, + arg_exprs: &'gcx [hir::Expr], + expected: Expectation<'tcx>, + ) -> Ty<'tcx> { let (fn_sig, def_span) = match callee_ty.sty { - ty::FnDef(def_id, _) => { - (callee_ty.fn_sig(self.tcx), self.tcx.hir().span_if_local(def_id)) - } + ty::FnDef(def_id, _) => ( + callee_ty.fn_sig(self.tcx), + self.tcx.hir().span_if_local(def_id), + ), ty::FnPtr(sig) => (sig, None), ref t => { let mut unit_variant = None; @@ -219,15 +245,19 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { match unit_variant { Some(ref path) => format!("enum variant `{}`", path), None => format!("`{}`", callee_ty), - }); + } + ); if let Some(ref path) = unit_variant { err.span_suggestion_with_applicability( call_expr.span, - &format!("`{}` is a unit variant, you need to write it \ - without the parenthesis", path), + &format!( + "`{}` is a unit variant, you need to write it \ + without the parenthesis", + path + ), path.to_string(), - Applicability::MachineApplicable + Applicability::MachineApplicable, ); } @@ -235,48 +265,50 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { let def = match callee.node { hir::ExprKind::Path(ref qpath) => { self.tables.borrow().qpath_def(qpath, callee.hir_id) - }, + } hir::ExprKind::Call(ref inner_callee, _) => { // If the call spans more than one line and the callee kind is // itself another `ExprCall`, that's a clue that we might just be // missing a semicolon (Issue #51055) - let call_is_multiline = self.tcx.sess.source_map() - .is_multiline(call_expr.span); + let call_is_multiline = + self.tcx.sess.source_map().is_multiline(call_expr.span); if call_is_multiline { let span = self.tcx.sess.source_map().next_point(callee.span); err.span_suggestion_with_applicability( span, "try adding a semicolon", ";".to_owned(), - Applicability::MaybeIncorrect + Applicability::MaybeIncorrect, ); } if let hir::ExprKind::Path(ref inner_qpath) = inner_callee.node { inner_callee_path = Some(inner_qpath); - self.tables.borrow().qpath_def(inner_qpath, inner_callee.hir_id) + self.tables + .borrow() + .qpath_def(inner_qpath, inner_callee.hir_id) } else { Def::Err } - }, - _ => { - Def::Err } + _ => Def::Err, }; err.span_label(call_expr.span, "call expression requires function"); let def_span = match def { Def::Err => None, - Def::Local(id) | Def::Upvar(id, ..) => { - Some(self.tcx.hir().span(id)) - } - _ => def.opt_def_id().and_then(|did| self.tcx.hir().span_if_local(did)), + Def::Local(id) | Def::Upvar(id, ..) => Some(self.tcx.hir().span(id)), + _ => def + .opt_def_id() + .and_then(|did| self.tcx.hir().span_if_local(did)), }; if let Some(span) = def_span { let label = match (unit_variant, inner_callee_path) { (Some(path), _) => format!("`{}` defined here", path), (_, Some(hir::QPath::Resolved(_, path))) => format!( - "`{}` defined here returns `{}`", path, callee_ty.to_string() + "`{}` defined here returns `{}`", + path, + callee_ty.to_string() ), _ => format!("`{}` defined here", callee_ty.to_string()), }; @@ -284,19 +316,25 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { } err.emit(); } else { - bug!("call_expr.node should be an ExprKind::Call, got {:?}", call_expr.node); + bug!( + "call_expr.node should be an ExprKind::Call, got {:?}", + call_expr.node + ); } // This is the "default" function signature, used in case of error. // In that case, we check each argument against "error" in order to // set up all the node type bindings. - (ty::Binder::bind(self.tcx.mk_fn_sig( - self.err_args(arg_exprs.len()).into_iter(), - self.tcx.types.err, - false, - hir::Unsafety::Normal, - abi::Abi::Rust - )), None) + ( + ty::Binder::bind(self.tcx.mk_fn_sig( + self.err_args(arg_exprs.len()).into_iter(), + self.tcx.types.err, + false, + hir::Unsafety::Normal, + abi::Abi::Rust, + )), + None, + ) } }; @@ -305,69 +343,80 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { // renormalize the associated types at this point, since they // previously appeared within a `Binder<>` and hence would not // have been normalized before. - let fn_sig = - self.replace_bound_vars_with_fresh_vars(call_expr.span, infer::FnCall, &fn_sig) - .0; + let fn_sig = self + .replace_bound_vars_with_fresh_vars(call_expr.span, infer::FnCall, &fn_sig) + .0; let fn_sig = self.normalize_associated_types_in(call_expr.span, &fn_sig); // Call the generic checker. - let expected_arg_tys = - self.expected_inputs_for_expected_output(call_expr.span, - expected, - fn_sig.output(), - fn_sig.inputs()); - self.check_argument_types(call_expr.span, - call_expr.span, - fn_sig.inputs(), - &expected_arg_tys[..], - arg_exprs, - fn_sig.variadic, - TupleArgumentsFlag::DontTupleArguments, - def_span); + let expected_arg_tys = self.expected_inputs_for_expected_output( + call_expr.span, + expected, + fn_sig.output(), + fn_sig.inputs(), + ); + self.check_argument_types( + call_expr.span, + call_expr.span, + fn_sig.inputs(), + &expected_arg_tys[..], + arg_exprs, + fn_sig.variadic, + TupleArgumentsFlag::DontTupleArguments, + def_span, + ); fn_sig.output() } - fn confirm_deferred_closure_call(&self, - call_expr: &hir::Expr, - arg_exprs: &'gcx [hir::Expr], - expected: Expectation<'tcx>, - fn_sig: ty::FnSig<'tcx>) - -> Ty<'tcx> { + fn confirm_deferred_closure_call( + &self, + call_expr: &hir::Expr, + arg_exprs: &'gcx [hir::Expr], + expected: Expectation<'tcx>, + fn_sig: ty::FnSig<'tcx>, + ) -> Ty<'tcx> { // `fn_sig` is the *signature* of the cosure being called. We // don't know the full details yet (`Fn` vs `FnMut` etc), but we // do know the types expected for each argument and the return // type. - let expected_arg_tys = self.expected_inputs_for_expected_output(call_expr.span, - expected, - fn_sig.output().clone(), - fn_sig.inputs()); - - self.check_argument_types(call_expr.span, - call_expr.span, - fn_sig.inputs(), - &expected_arg_tys, - arg_exprs, - fn_sig.variadic, - TupleArgumentsFlag::TupleArguments, - None); + let expected_arg_tys = self.expected_inputs_for_expected_output( + call_expr.span, + expected, + fn_sig.output().clone(), + fn_sig.inputs(), + ); + + self.check_argument_types( + call_expr.span, + call_expr.span, + fn_sig.inputs(), + &expected_arg_tys, + arg_exprs, + fn_sig.variadic, + TupleArgumentsFlag::TupleArguments, + None, + ); fn_sig.output() } - fn confirm_overloaded_call(&self, - call_expr: &hir::Expr, - arg_exprs: &'gcx [hir::Expr], - expected: Expectation<'tcx>, - method_callee: MethodCallee<'tcx>) - -> Ty<'tcx> { - let output_type = self.check_method_argument_types(call_expr.span, - call_expr.span, - Ok(method_callee), - arg_exprs, - TupleArgumentsFlag::TupleArguments, - expected); + fn confirm_overloaded_call( + &self, + call_expr: &hir::Expr, + arg_exprs: &'gcx [hir::Expr], + expected: Expectation<'tcx>, + method_callee: MethodCallee<'tcx>, + ) -> Ty<'tcx> { + let output_type = self.check_method_argument_types( + call_expr.span, + call_expr.span, + Ok(method_callee), + arg_exprs, + TupleArgumentsFlag::TupleArguments, + expected, + ); self.write_method_call(call_expr.hir_id, method_callee); output_type @@ -391,11 +440,12 @@ impl<'a, 'gcx, 'tcx> DeferredCallResolution<'gcx, 'tcx> { // we should not be invoked until the closure kind has been // determined by upvar inference - assert!(fcx.closure_kind(self.closure_def_id, self.closure_substs).is_some()); + assert!(fcx + .closure_kind(self.closure_def_id, self.closure_substs) + .is_some()); // We may now know enough to figure out fn vs fnmut etc. - match fcx.try_overloaded_call_traits(self.call_expr, - self.adjusted_ty) { + match fcx.try_overloaded_call_traits(self.call_expr, self.adjusted_ty) { Some((autoref, method_callee)) => { // One problem is that when we get here, we are going // to have a newly instantiated function signature @@ -410,22 +460,28 @@ impl<'a, 'gcx, 'tcx> DeferredCallResolution<'gcx, 'tcx> { debug!("attempt_resolution: method_callee={:?}", method_callee); for (method_arg_ty, self_arg_ty) in - method_sig.inputs().iter().skip(1).zip(self.fn_sig.inputs()) { + method_sig.inputs().iter().skip(1).zip(self.fn_sig.inputs()) + { fcx.demand_eqtype(self.call_expr.span, &self_arg_ty, &method_arg_ty); } - fcx.demand_eqtype(self.call_expr.span, method_sig.output(), self.fn_sig.output()); + fcx.demand_eqtype( + self.call_expr.span, + method_sig.output(), + self.fn_sig.output(), + ); let mut adjustments = self.adjustments; adjustments.extend(autoref); fcx.apply_adjustments(self.callee_expr, adjustments); - fcx.write_method_call(self.call_expr.hir_id, - method_callee); + fcx.write_method_call(self.call_expr.hir_id, method_callee); } None => { - span_bug!(self.call_expr.span, - "failed to find an overloaded call trait for closure call"); + span_bug!( + self.call_expr.span, + "failed to find an overloaded call trait for closure call" + ); } } }