diff options
| author | Camille GILLOT <gillot.camille@gmail.com> | 2018-11-04 11:23:45 +0100 |
|---|---|---|
| committer | Camille GILLOT <gillot.camille@gmail.com> | 2018-12-30 14:47:11 +0100 |
| commit | 1827d52a3f39fd9b25cebf4d78f2e0926c0cb593 (patch) | |
| tree | dbd72ae86be3ea9fb636204f5ac053bb5978f551 | |
| parent | 6de9c13830c74551632f2a1b299778d9e62381ff (diff) | |
| download | rust-1827d52a3f39fd9b25cebf4d78f2e0926c0cb593.tar.gz rust-1827d52a3f39fd9b25cebf4d78f2e0926c0cb593.zip | |
rustc_typeck: Implement resolution advised in issue 45510.
When resolving Fn traits, the compiler failed to take into account overloaded implementations. To resolve this, we inform the trait dispatch code that the arguments will becoming as a tuple of correct arity.
| -rw-r--r-- | src/librustc_typeck/check/callee.rs | 20 |
1 files changed, 16 insertions, 4 deletions
diff --git a/src/librustc_typeck/check/callee.rs b/src/librustc_typeck/check/callee.rs index 727fbf7b30f..5a79bec4dd7 100644 --- a/src/librustc_typeck/check/callee.rs +++ b/src/librustc_typeck/check/callee.rs @@ -8,6 +8,7 @@ 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::infer::type_variable::TypeVariableOrigin; use rustc_target::spec::abi; use syntax::ast::Ident; use syntax_pos::Span; @@ -46,7 +47,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { let mut autoderef = self.autoderef(callee_expr.span, expr_ty); let mut result = None; while result.is_none() && autoderef.next().is_some() { - result = self.try_overloaded_call_step(call_expr, callee_expr, &autoderef); + result = self.try_overloaded_call_step(call_expr, callee_expr, arg_exprs, &autoderef); } autoderef.finalize(self); @@ -79,6 +80,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { &self, call_expr: &'gcx hir::Expr, callee_expr: &'gcx hir::Expr, + arg_exprs: &'gcx [hir::Expr], autoderef: &Autoderef<'a, 'gcx, 'tcx>, ) -> Option<CallStep<'tcx>> { let adjusted_ty = autoderef.unambiguous_final_ty(self); @@ -142,7 +144,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { _ => {} } - self.try_overloaded_call_traits(call_expr, adjusted_ty) + self.try_overloaded_call_traits(call_expr, adjusted_ty, Some(arg_exprs)) .map(|(autoref, method)| { let mut adjustments = autoderef.adjust_steps(self, Needs::None); adjustments.extend(autoref); @@ -155,6 +157,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { &self, call_expr: &hir::Expr, adjusted_ty: Ty<'tcx>, + opt_arg_exprs: Option<&'gcx [hir::Expr]>, ) -> Option<(Option<Adjustment<'tcx>>, MethodCallee<'tcx>)> { // Try the options that are least restrictive on the caller first. for &(opt_trait_def_id, method_name, borrow) in &[ @@ -179,12 +182,21 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { None => continue, }; + let opt_input_types = opt_arg_exprs.map(|arg_exprs| [self.tcx.mk_tup( + arg_exprs + .iter() + .map(|e| self.next_ty_var( + TypeVariableOrigin::TypeInference(e.span) + )) + )]); + let opt_input_types = opt_input_types.as_ref().map(AsRef::as_ref); + if let Some(ok) = self.lookup_method_in_trait( call_expr.span, method_name, trait_def_id, adjusted_ty, - None, + opt_input_types, ) { let method = self.register_infer_ok_obligations(ok); let mut autoref = None; @@ -445,7 +457,7 @@ impl<'a, 'gcx, 'tcx> DeferredCallResolution<'gcx, 'tcx> { .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, None) { Some((autoref, method_callee)) => { // One problem is that when we get here, we are going // to have a newly instantiated function signature |
