@@ -12,8 +12,8 @@ use rustc_index::bit_set::GrowableBitSet;
12
12
use rustc_infer:: infer:: InferOk ;
13
13
use rustc_infer:: infer:: LateBoundRegionConversionTime :: HigherRankedType ;
14
14
use rustc_middle:: ty:: {
15
- self , GenericArg , GenericArgKind , GenericParamDefKind , InternalSubsts , SubstsRef ,
16
- ToPolyTraitRef , ToPredicate , Ty , TyCtxt ,
15
+ self , Binder , GenericArg , GenericArgKind , GenericParamDefKind , InternalSubsts , SubstsRef ,
16
+ ToPolyTraitRef , ToPredicate , TraitRef , Ty , TyCtxt ,
17
17
} ;
18
18
use rustc_span:: def_id:: DefId ;
19
19
@@ -98,8 +98,8 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
98
98
ImplSource :: Future ( vtable_future)
99
99
}
100
100
101
- FnPointerCandidate { .. } => {
102
- let data = self . confirm_fn_pointer_candidate ( obligation) ?;
101
+ FnPointerCandidate { is_const } => {
102
+ let data = self . confirm_fn_pointer_candidate ( obligation, is_const ) ?;
103
103
ImplSource :: FnPointer ( data)
104
104
}
105
105
@@ -597,17 +597,19 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
597
597
fn confirm_fn_pointer_candidate (
598
598
& mut self ,
599
599
obligation : & TraitObligation < ' tcx > ,
600
+ is_const : bool ,
600
601
) -> Result < ImplSourceFnPointerData < ' tcx , PredicateObligation < ' tcx > > , SelectionError < ' tcx > >
601
602
{
602
603
debug ! ( ?obligation, "confirm_fn_pointer_candidate" ) ;
603
604
605
+ let tcx = self . tcx ( ) ;
604
606
let self_ty = self
605
607
. infcx
606
608
. shallow_resolve ( obligation. self_ty ( ) . no_bound_vars ( ) )
607
609
. expect ( "fn pointer should not capture bound vars from predicate" ) ;
608
- let sig = self_ty. fn_sig ( self . tcx ( ) ) ;
610
+ let sig = self_ty. fn_sig ( tcx) ;
609
611
let trait_ref = closure_trait_ref_and_return_type (
610
- self . tcx ( ) ,
612
+ tcx,
611
613
obligation. predicate . def_id ( ) ,
612
614
self_ty,
613
615
sig,
@@ -616,9 +618,19 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
616
618
. map_bound ( |( trait_ref, _) | trait_ref) ;
617
619
618
620
let mut nested = self . confirm_poly_trait_refs ( obligation, trait_ref) ?;
621
+ let cause = obligation. derived_cause ( BuiltinDerivedObligation ) ;
622
+
623
+ if obligation. is_const ( ) && !is_const {
624
+ // function is a trait method
625
+ if let ty:: FnDef ( def_id, substs) = self_ty. kind ( ) && let Some ( trait_id) = tcx. trait_of_item ( * def_id) {
626
+ let trait_ref = TraitRef :: from_method ( tcx, trait_id, * substs) ;
627
+ let poly_trait_pred = Binder :: dummy ( trait_ref) . with_constness ( ty:: BoundConstness :: ConstIfConst ) ;
628
+ let obligation = Obligation :: new ( tcx, cause. clone ( ) , obligation. param_env , poly_trait_pred) ;
629
+ nested. push ( obligation) ;
630
+ }
631
+ }
619
632
620
633
// Confirm the `type Output: Sized;` bound that is present on `FnOnce`
621
- let cause = obligation. derived_cause ( BuiltinDerivedObligation ) ;
622
634
let output_ty = self . infcx . replace_bound_vars_with_placeholders ( sig. output ( ) ) ;
623
635
let output_ty = normalize_with_depth_to (
624
636
self ,
0 commit comments