@@ -333,15 +333,57 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
333333 )
334334 }
335335
336+ pub ( super ) fn obligation_for_op_method (
337+ & self ,
338+ span : Span ,
339+ trait_def_id : DefId ,
340+ self_ty : Ty < ' tcx > ,
341+ opt_input_type : Option < Ty < ' tcx > > ,
342+ opt_input_expr : Option < & ' tcx hir:: Expr < ' tcx > > ,
343+ ) -> ( traits:: Obligation < ' tcx , ty:: Predicate < ' tcx > > , & ' tcx ty:: List < ty:: subst:: GenericArg < ' tcx > > )
344+ {
345+ // Construct a trait-reference `self_ty : Trait<input_tys>`
346+ let substs = InternalSubsts :: for_item ( self . tcx , trait_def_id, |param, _| {
347+ match param. kind {
348+ GenericParamDefKind :: Lifetime | GenericParamDefKind :: Const { .. } => { }
349+ GenericParamDefKind :: Type { .. } => {
350+ if param. index == 0 {
351+ return self_ty. into ( ) ;
352+ } else if let Some ( input_type) = opt_input_type {
353+ return input_type. into ( ) ;
354+ }
355+ }
356+ }
357+ self . var_for_def ( span, param)
358+ } ) ;
359+
360+ let trait_ref = ty:: TraitRef :: new ( trait_def_id, substs) ;
361+
362+ // Construct an obligation
363+ let poly_trait_ref = ty:: Binder :: dummy ( trait_ref) ;
364+ (
365+ traits:: Obligation :: new (
366+ traits:: ObligationCause :: new (
367+ span,
368+ self . body_id ,
369+ traits:: BinOp {
370+ rhs_span : opt_input_expr. map ( |expr| expr. span ) ,
371+ is_lit : opt_input_expr
372+ . map_or ( false , |expr| matches ! ( expr. kind, hir:: ExprKind :: Lit ( _) ) ) ,
373+ } ,
374+ ) ,
375+ self . param_env ,
376+ poly_trait_ref. without_const ( ) . to_predicate ( self . tcx ) ,
377+ ) ,
378+ substs,
379+ )
380+ }
381+
336382 /// `lookup_method_in_trait` is used for overloaded operators.
337383 /// It does a very narrow slice of what the normal probe/confirm path does.
338384 /// In particular, it doesn't really do any probing: it simply constructs
339385 /// an obligation for a particular trait with the given self type and checks
340386 /// whether that trait is implemented.
341- //
342- // FIXME(#18741): it seems likely that we can consolidate some of this
343- // code with the other method-lookup code. In particular, the second half
344- // of this method is basically the same as confirmation.
345387 #[ instrument( level = "debug" , skip( self , span, opt_input_types) ) ]
346388 pub ( super ) fn lookup_method_in_trait (
347389 & self ,
@@ -358,7 +400,57 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
358400
359401 let ( obligation, substs) =
360402 self . obligation_for_method ( span, trait_def_id, self_ty, opt_input_types) ;
403+ self . construct_obligation_for_trait (
404+ span,
405+ m_name,
406+ trait_def_id,
407+ obligation,
408+ substs,
409+ None ,
410+ false ,
411+ )
412+ }
361413
414+ pub ( super ) fn lookup_op_method_in_trait (
415+ & self ,
416+ span : Span ,
417+ m_name : Ident ,
418+ trait_def_id : DefId ,
419+ self_ty : Ty < ' tcx > ,
420+ opt_input_type : Option < Ty < ' tcx > > ,
421+ opt_input_expr : Option < & ' tcx hir:: Expr < ' tcx > > ,
422+ ) -> Option < InferOk < ' tcx , MethodCallee < ' tcx > > > {
423+ let ( obligation, substs) = self . obligation_for_op_method (
424+ span,
425+ trait_def_id,
426+ self_ty,
427+ opt_input_type,
428+ opt_input_expr,
429+ ) ;
430+ self . construct_obligation_for_trait (
431+ span,
432+ m_name,
433+ trait_def_id,
434+ obligation,
435+ substs,
436+ opt_input_expr,
437+ true ,
438+ )
439+ }
440+
441+ // FIXME(#18741): it seems likely that we can consolidate some of this
442+ // code with the other method-lookup code. In particular, the second half
443+ // of this method is basically the same as confirmation.
444+ fn construct_obligation_for_trait (
445+ & self ,
446+ span : Span ,
447+ m_name : Ident ,
448+ trait_def_id : DefId ,
449+ obligation : traits:: PredicateObligation < ' tcx > ,
450+ substs : & ' tcx ty:: List < ty:: subst:: GenericArg < ' tcx > > ,
451+ opt_input_expr : Option < & ' tcx hir:: Expr < ' tcx > > ,
452+ is_op : bool ,
453+ ) -> Option < InferOk < ' tcx , MethodCallee < ' tcx > > > {
362454 debug ! ( ?obligation) ;
363455
364456 // Now we want to know if this can be matched
@@ -395,8 +487,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
395487 let fn_sig = self . replace_bound_vars_with_fresh_vars ( span, infer:: FnCall , fn_sig) . 0 ;
396488 let fn_sig = fn_sig. subst ( self . tcx , substs) ;
397489
398- let InferOk { value, obligations : o } =
399- self . normalize_associated_types_in_as_infer_ok ( span, fn_sig) ;
490+ let InferOk { value, obligations : o } = if is_op {
491+ self . normalize_op_associated_types_in_as_infer_ok ( span, fn_sig, opt_input_expr)
492+ } else {
493+ self . normalize_associated_types_in_as_infer_ok ( span, fn_sig)
494+ } ;
400495 let fn_sig = {
401496 obligations. extend ( o) ;
402497 value
@@ -412,16 +507,31 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
412507 // any late-bound regions appearing in its bounds.
413508 let bounds = self . tcx . predicates_of ( def_id) . instantiate ( self . tcx , substs) ;
414509
415- let InferOk { value, obligations : o } =
416- self . normalize_associated_types_in_as_infer_ok ( span, bounds) ;
510+ let InferOk { value, obligations : o } = if is_op {
511+ self . normalize_op_associated_types_in_as_infer_ok ( span, bounds, opt_input_expr)
512+ } else {
513+ self . normalize_associated_types_in_as_infer_ok ( span, bounds)
514+ } ;
417515 let bounds = {
418516 obligations. extend ( o) ;
419517 value
420518 } ;
421519
422520 assert ! ( !bounds. has_escaping_bound_vars( ) ) ;
423521
424- let cause = traits:: ObligationCause :: misc ( span, self . body_id ) ;
522+ let cause = if is_op {
523+ ObligationCause :: new (
524+ span,
525+ self . body_id ,
526+ traits:: BinOp {
527+ rhs_span : opt_input_expr. map ( |expr| expr. span ) ,
528+ is_lit : opt_input_expr
529+ . map_or ( false , |expr| matches ! ( expr. kind, hir:: ExprKind :: Lit ( _) ) ) ,
530+ } ,
531+ )
532+ } else {
533+ traits:: ObligationCause :: misc ( span, self . body_id )
534+ } ;
425535 obligations. extend ( traits:: predicates_for_generics ( cause. clone ( ) , self . param_env , bounds) ) ;
426536
427537 // Also add an obligation for the method type being well-formed.
0 commit comments