@@ -4,7 +4,7 @@ use rustc_hir::def::Res;
44use rustc_hir:: def_id:: DefId ;
55use rustc_infer:: traits:: ObligationCauseCode ;
66use rustc_middle:: ty:: { self , Ty , TyCtxt , TypeSuperVisitable , TypeVisitable , TypeVisitor } ;
7- use rustc_span:: { self , Span } ;
7+ use rustc_span:: { self , symbol :: kw , Span } ;
88use rustc_trait_selection:: traits;
99
1010use std:: ops:: ControlFlow ;
@@ -25,17 +25,28 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
2525
2626 let generics = self . tcx . generics_of ( def_id) ;
2727 let predicate_substs = match unsubstituted_pred. kind ( ) . skip_binder ( ) {
28- ty:: PredicateKind :: Clause ( ty:: Clause :: Trait ( pred) ) => pred. trait_ref . substs ,
29- ty:: PredicateKind :: Clause ( ty:: Clause :: Projection ( pred) ) => pred. projection_ty . substs ,
30- _ => ty:: List :: empty ( ) ,
28+ ty:: PredicateKind :: Clause ( ty:: Clause :: Trait ( pred) ) => pred. trait_ref . substs . to_vec ( ) ,
29+ ty:: PredicateKind :: Clause ( ty:: Clause :: Projection ( pred) ) => {
30+ pred. projection_ty . substs . to_vec ( )
31+ }
32+ ty:: PredicateKind :: Clause ( ty:: Clause :: ConstArgHasType ( arg, ty) ) => {
33+ vec ! [ ty. into( ) , arg. into( ) ]
34+ }
35+ ty:: PredicateKind :: ConstEvaluatable ( e) => vec ! [ e. into( ) ] ,
36+ _ => return false ,
3137 } ;
3238
33- let find_param_matching = |matches : & dyn Fn ( & ty:: ParamTy ) -> bool | {
34- predicate_substs. types ( ) . find_map ( |ty | {
35- ty . walk ( ) . find_map ( |arg| {
39+ let find_param_matching = |matches : & dyn Fn ( ty:: ParamTerm ) -> bool | {
40+ predicate_substs. iter ( ) . find_map ( |arg | {
41+ arg . walk ( ) . find_map ( |arg| {
3642 if let ty:: GenericArgKind :: Type ( ty) = arg. unpack ( )
37- && let ty:: Param ( param_ty) = ty. kind ( )
38- && matches ( param_ty)
43+ && let ty:: Param ( param_ty) = * ty. kind ( )
44+ && matches ( ty:: ParamTerm :: Ty ( param_ty) )
45+ {
46+ Some ( arg)
47+ } else if let ty:: GenericArgKind :: Const ( ct) = arg. unpack ( )
48+ && let ty:: ConstKind :: Param ( param_ct) = ct. kind ( )
49+ && matches ( ty:: ParamTerm :: Const ( param_ct) )
3950 {
4051 Some ( arg)
4152 } else {
@@ -47,21 +58,22 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
4758
4859 // Prefer generics that are local to the fn item, since these are likely
4960 // to be the cause of the unsatisfied predicate.
50- let mut param_to_point_at = find_param_matching ( & |param_ty | {
51- self . tcx . parent ( generics. type_param ( param_ty , self . tcx ) . def_id ) == def_id
61+ let mut param_to_point_at = find_param_matching ( & |param_term | {
62+ self . tcx . parent ( generics. param_at ( param_term . index ( ) , self . tcx ) . def_id ) == def_id
5263 } ) ;
5364 // Fall back to generic that isn't local to the fn item. This will come
5465 // from a trait or impl, for example.
55- let mut fallback_param_to_point_at = find_param_matching ( & |param_ty | {
56- self . tcx . parent ( generics. type_param ( param_ty , self . tcx ) . def_id ) != def_id
57- && param_ty . name != rustc_span :: symbol :: kw:: SelfUpper
66+ let mut fallback_param_to_point_at = find_param_matching ( & |param_term | {
67+ self . tcx . parent ( generics. param_at ( param_term . index ( ) , self . tcx ) . def_id ) != def_id
68+ && ! matches ! ( param_term , ty :: ParamTerm :: Ty ( ty ) if ty . name == kw:: SelfUpper )
5869 } ) ;
5970 // Finally, the `Self` parameter is possibly the reason that the predicate
6071 // is unsatisfied. This is less likely to be true for methods, because
6172 // method probe means that we already kinda check that the predicates due
6273 // to the `Self` type are true.
63- let mut self_param_to_point_at =
64- find_param_matching ( & |param_ty| param_ty. name == rustc_span:: symbol:: kw:: SelfUpper ) ;
74+ let mut self_param_to_point_at = find_param_matching (
75+ & |param_term| matches ! ( param_term, ty:: ParamTerm :: Ty ( ty) if ty. name == kw:: SelfUpper ) ,
76+ ) ;
6577
6678 // Finally, for ambiguity-related errors, we actually want to look
6779 // for a parameter that is the source of the inference type left
@@ -225,14 +237,12 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
225237 . own_substs ( ty:: InternalSubsts :: identity_for_item ( self . tcx , def_id) ) ;
226238 let Some ( ( index, _) ) = own_substs
227239 . iter ( )
228- . filter ( |arg| matches ! ( arg. unpack( ) , ty:: GenericArgKind :: Type ( _) ) )
229240 . enumerate ( )
230241 . find ( |( _, arg) | * * arg == param_to_point_at) else { return false } ;
231242 let Some ( arg) = segment
232243 . args ( )
233244 . args
234245 . iter ( )
235- . filter ( |arg| matches ! ( arg, hir:: GenericArg :: Type ( _) ) )
236246 . nth ( index) else { return false ; } ;
237247 error. obligation . cause . span = arg
238248 . span ( )
0 commit comments