@@ -11,26 +11,56 @@ use rustc_trait_selection::traits;
1111
1212use crate :: FnCtxt ;
1313
14+ enum ClauseFlavor {
15+ /// Predicate comes from `predicates_of`.
16+ Where ,
17+ /// Predicate comes from `const_conditions`.
18+ Const ,
19+ }
20+
1421impl < ' a , ' tcx > FnCtxt < ' a , ' tcx > {
1522 pub ( crate ) fn adjust_fulfillment_error_for_expr_obligation (
1623 & self ,
1724 error : & mut traits:: FulfillmentError < ' tcx > ,
1825 ) -> bool {
19- let ObligationCauseCode :: WhereClauseInExpr ( def_id, _, hir_id, idx) =
20- * error. obligation . cause . code ( ) . peel_derives ( )
21- else {
22- return false ;
26+ let ( def_id, hir_id, idx, flavor) = match * error. obligation . cause . code ( ) . peel_derives ( ) {
27+ ObligationCauseCode :: WhereClauseInExpr ( def_id, _, hir_id, idx) => {
28+ ( def_id, hir_id, idx, ClauseFlavor :: Where )
29+ }
30+ ObligationCauseCode :: HostEffectInExpr ( def_id, _, hir_id, idx) => {
31+ ( def_id, hir_id, idx, ClauseFlavor :: Const )
32+ }
33+ _ => return false ,
2334 } ;
2435
25- let Some ( uninstantiated_pred) = self
26- . tcx
27- . predicates_of ( def_id)
28- . instantiate_identity ( self . tcx )
29- . predicates
30- . into_iter ( )
31- . nth ( idx)
32- else {
33- return false ;
36+ let uninstantiated_pred = match flavor {
37+ ClauseFlavor :: Where => {
38+ if let Some ( pred) = self
39+ . tcx
40+ . predicates_of ( def_id)
41+ . instantiate_identity ( self . tcx )
42+ . predicates
43+ . into_iter ( )
44+ . nth ( idx)
45+ {
46+ pred
47+ } else {
48+ return false ;
49+ }
50+ }
51+ ClauseFlavor :: Const => {
52+ if let Some ( ( pred, _) ) = self
53+ . tcx
54+ . const_conditions ( def_id)
55+ . instantiate_identity ( self . tcx )
56+ . into_iter ( )
57+ . nth ( idx)
58+ {
59+ pred. to_host_effect_clause ( self . tcx , ty:: BoundConstness :: Maybe )
60+ } else {
61+ return false ;
62+ }
63+ }
3464 } ;
3565
3666 let generics = self . tcx . generics_of ( def_id) ;
@@ -39,6 +69,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
3969 ty:: ClauseKind :: Trait ( pred) => {
4070 ( pred. trait_ref . args . to_vec ( ) , Some ( pred. self_ty ( ) . into ( ) ) )
4171 }
72+ ty:: ClauseKind :: HostEffect ( pred) => {
73+ ( pred. trait_ref . args . to_vec ( ) , Some ( pred. self_ty ( ) . into ( ) ) )
74+ }
4275 ty:: ClauseKind :: Projection ( pred) => ( pred. projection_term . args . to_vec ( ) , None ) ,
4376 ty:: ClauseKind :: ConstArgHasType ( arg, ty) => ( vec ! [ ty. into( ) , arg. into( ) ] , None ) ,
4477 ty:: ClauseKind :: ConstEvaluatable ( e) => ( vec ! [ e. into( ) ] , None ) ,
@@ -94,39 +127,62 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
94127 self . find_ambiguous_parameter_in ( def_id, error. root_obligation . predicate ) ;
95128 }
96129
97- let ( expr, qpath) = match self . tcx . hir_node ( hir_id) {
98- hir:: Node :: Expr ( expr) => {
99- if self . closure_span_overlaps_error ( error, expr. span ) {
100- return false ;
130+ match self . tcx . hir_node ( hir_id) {
131+ hir:: Node :: Expr ( expr) => self . point_at_expr_if_possible (
132+ error,
133+ def_id,
134+ expr,
135+ predicate_self_type_to_point_at,
136+ param_to_point_at,
137+ fallback_param_to_point_at,
138+ self_param_to_point_at,
139+ ) ,
140+
141+ hir:: Node :: Ty ( hir:: Ty { kind : hir:: TyKind :: Path ( qpath) , .. } ) => {
142+ for param in [
143+ predicate_self_type_to_point_at,
144+ param_to_point_at,
145+ fallback_param_to_point_at,
146+ self_param_to_point_at,
147+ ]
148+ . into_iter ( )
149+ . flatten ( )
150+ {
151+ if self . point_at_path_if_possible ( error, def_id, param, & qpath) {
152+ return true ;
153+ }
101154 }
102- let qpath =
103- if let hir:: ExprKind :: Path ( qpath) = expr. kind { Some ( qpath) } else { None } ;
104155
105- ( Some ( & expr . kind ) , qpath )
156+ false
106157 }
107- hir:: Node :: Ty ( hir:: Ty { kind : hir:: TyKind :: Path ( qpath) , .. } ) => ( None , Some ( * qpath) ) ,
108- _ => return false ,
109- } ;
110158
111- if let Some ( qpath) = qpath {
112- // Prefer pointing at the turbofished arg that corresponds to the
113- // self type of the failing predicate over anything else.
114- if let Some ( param) = predicate_self_type_to_point_at
115- && self . point_at_path_if_possible ( error, def_id, param, & qpath)
116- {
117- return true ;
118- }
159+ _ => false ,
160+ }
161+ }
119162
120- if let hir:: Node :: Expr ( hir:: Expr {
121- kind : hir:: ExprKind :: Call ( callee, args) ,
122- hir_id : call_hir_id,
123- span : call_span,
124- ..
125- } ) = self . tcx . parent_hir_node ( hir_id)
126- && callee. hir_id == hir_id
127- {
128- if self . closure_span_overlaps_error ( error, * call_span) {
129- return false ;
163+ fn point_at_expr_if_possible (
164+ & self ,
165+ error : & mut traits:: FulfillmentError < ' tcx > ,
166+ callee_def_id : DefId ,
167+ expr : & ' tcx hir:: Expr < ' tcx > ,
168+ predicate_self_type_to_point_at : Option < ty:: GenericArg < ' tcx > > ,
169+ param_to_point_at : Option < ty:: GenericArg < ' tcx > > ,
170+ fallback_param_to_point_at : Option < ty:: GenericArg < ' tcx > > ,
171+ self_param_to_point_at : Option < ty:: GenericArg < ' tcx > > ,
172+ ) -> bool {
173+ if self . closure_span_overlaps_error ( error, expr. span ) {
174+ return false ;
175+ }
176+
177+ match expr. kind {
178+ hir:: ExprKind :: Call (
179+ hir:: Expr { kind : hir:: ExprKind :: Path ( qpath) , span : callee_span, .. } ,
180+ args,
181+ ) => {
182+ if let Some ( param) = predicate_self_type_to_point_at
183+ && self . point_at_path_if_possible ( error, callee_def_id, param, & qpath)
184+ {
185+ return true ;
130186 }
131187
132188 for param in [ param_to_point_at, fallback_param_to_point_at, self_param_to_point_at]
@@ -135,32 +191,68 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
135191 {
136192 if self . blame_specific_arg_if_possible (
137193 error,
138- def_id ,
194+ callee_def_id ,
139195 param,
140- * call_hir_id ,
141- callee . span ,
196+ expr . hir_id ,
197+ * callee_span ,
142198 None ,
143199 args,
144200 ) {
145201 return true ;
146202 }
147203 }
204+
205+ for param in [ param_to_point_at, fallback_param_to_point_at, self_param_to_point_at]
206+ . into_iter ( )
207+ . flatten ( )
208+ {
209+ if self . point_at_path_if_possible ( error, callee_def_id, param, & qpath) {
210+ return true ;
211+ }
212+ }
148213 }
214+ hir:: ExprKind :: Path ( qpath) => {
215+ // If the parent is an call, then process this as a call.
216+ //
217+ // This is because the `WhereClauseInExpr` obligations come from
218+ // the well-formedness of the *path* expression, but we care to
219+ // point at the call expression (namely, its args).
220+ if let hir:: Node :: Expr (
221+ call_expr @ hir:: Expr { kind : hir:: ExprKind :: Call ( callee, ..) , .. } ,
222+ ) = self . tcx . parent_hir_node ( expr. hir_id )
223+ && callee. hir_id == expr. hir_id
224+ {
225+ return self . point_at_expr_if_possible (
226+ error,
227+ callee_def_id,
228+ call_expr,
229+ predicate_self_type_to_point_at,
230+ param_to_point_at,
231+ fallback_param_to_point_at,
232+ self_param_to_point_at,
233+ ) ;
234+ }
149235
150- for param in [ param_to_point_at , fallback_param_to_point_at , self_param_to_point_at ]
151- . into_iter ( )
152- . flatten ( )
153- {
154- if self . point_at_path_if_possible ( error , def_id , param , & qpath ) {
236+ // Otherwise, just try to point at path components.
237+
238+ if let Some ( param ) = predicate_self_type_to_point_at
239+ && self . point_at_path_if_possible ( error , callee_def_id , param , & qpath )
240+ {
155241 return true ;
156242 }
157- }
158- }
159243
160- match expr {
161- Some ( hir:: ExprKind :: MethodCall ( segment, receiver, args, ..) ) => {
244+ for param in [ param_to_point_at, fallback_param_to_point_at, self_param_to_point_at]
245+ . into_iter ( )
246+ . flatten ( )
247+ {
248+ if self . point_at_path_if_possible ( error, callee_def_id, param, & qpath) {
249+ return true ;
250+ }
251+ }
252+ }
253+ hir:: ExprKind :: MethodCall ( segment, receiver, args, ..) => {
162254 if let Some ( param) = predicate_self_type_to_point_at
163- && self . point_at_generic_if_possible ( error, def_id , param, segment)
255+ && self . point_at_generic_if_possible ( error, callee_def_id , param, segment)
164256 {
165257 // HACK: This is not correct, since `predicate_self_type_to_point_at` might
166258 // not actually correspond to the receiver of the method call. But we
@@ -170,7 +262,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
170262 error. obligation . cause . map_code ( |parent_code| {
171263 ObligationCauseCode :: FunctionArg {
172264 arg_hir_id : receiver. hir_id ,
173- call_hir_id : hir_id,
265+ call_hir_id : expr . hir_id ,
174266 parent_code,
175267 }
176268 } ) ;
@@ -183,9 +275,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
183275 {
184276 if self . blame_specific_arg_if_possible (
185277 error,
186- def_id ,
278+ callee_def_id ,
187279 param,
188- hir_id,
280+ expr . hir_id ,
189281 segment. ident . span ,
190282 Some ( receiver) ,
191283 args,
@@ -194,7 +286,12 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
194286 }
195287 }
196288 if let Some ( param_to_point_at) = param_to_point_at
197- && self . point_at_generic_if_possible ( error, def_id, param_to_point_at, segment)
289+ && self . point_at_generic_if_possible (
290+ error,
291+ callee_def_id,
292+ param_to_point_at,
293+ segment,
294+ )
198295 {
199296 return true ;
200297 }
@@ -208,17 +305,21 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
208305 return true ;
209306 }
210307 }
211- Some ( hir:: ExprKind :: Struct ( qpath, fields, ..) ) => {
308+ hir:: ExprKind :: Struct ( qpath, fields, ..) => {
212309 if let Res :: Def ( DefKind :: Struct | DefKind :: Variant , variant_def_id) =
213- self . typeck_results . borrow ( ) . qpath_res ( qpath, hir_id)
310+ self . typeck_results . borrow ( ) . qpath_res ( qpath, expr . hir_id )
214311 {
215312 for param in
216313 [ param_to_point_at, fallback_param_to_point_at, self_param_to_point_at]
217314 . into_iter ( )
218315 . flatten ( )
219316 {
220- let refined_expr =
221- self . point_at_field_if_possible ( def_id, param, variant_def_id, fields) ;
317+ let refined_expr = self . point_at_field_if_possible (
318+ callee_def_id,
319+ param,
320+ variant_def_id,
321+ fields,
322+ ) ;
222323
223324 match refined_expr {
224325 None => { }
@@ -242,7 +343,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
242343 . into_iter ( )
243344 . flatten ( )
244345 {
245- if self . point_at_path_if_possible ( error, def_id , param, qpath) {
346+ if self . point_at_path_if_possible ( error, callee_def_id , param, qpath) {
246347 return true ;
247348 }
248349 }
@@ -525,7 +626,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
525626 expr : & ' tcx hir:: Expr < ' tcx > ,
526627 ) -> Result < & ' tcx hir:: Expr < ' tcx > , & ' tcx hir:: Expr < ' tcx > > {
527628 match obligation_cause_code {
528- traits:: ObligationCauseCode :: WhereClauseInExpr ( _, _, _, _) => {
629+ traits:: ObligationCauseCode :: WhereClauseInExpr ( _, _, _, _)
630+ | ObligationCauseCode :: HostEffectInExpr ( ..) => {
529631 // This is the "root"; we assume that the `expr` is already pointing here.
530632 // Therefore, we return `Ok` so that this `expr` can be refined further.
531633 Ok ( expr)
0 commit comments