@@ -13,12 +13,10 @@ use super::{
13
13
FulfillmentErrorCode ,
14
14
MismatchedProjectionTypes ,
15
15
Obligation ,
16
- ObligationCause ,
17
16
ObligationCauseCode ,
18
17
OutputTypeParameterMismatch ,
19
18
TraitNotObjectSafe ,
20
19
PredicateObligation ,
21
- SelectionContext ,
22
20
SelectionError ,
23
21
ObjectSafetyViolation ,
24
22
MethodViolationCode ,
@@ -28,9 +26,8 @@ use super::{
28
26
use fmt_macros:: { Parser , Piece , Position } ;
29
27
use hir:: def_id:: DefId ;
30
28
use infer:: InferCtxt ;
31
- use ty:: { self , ToPredicate , ToPolyTraitRef , Ty , TyCtxt } ;
29
+ use ty:: { self , ToPredicate , ToPolyTraitRef , TraitRef , Ty , TyCtxt , TypeFoldable } ;
32
30
use ty:: fast_reject;
33
- use ty:: fold:: { TypeFoldable , TypeFolder } ;
34
31
use util:: nodemap:: { FnvHashMap , FnvHashSet } ;
35
32
36
33
use std:: cmp;
@@ -93,7 +90,12 @@ pub fn report_projection_error<'a, 'tcx>(infcx: &InferCtxt<'a, 'tcx>,
93
90
let predicate =
94
91
infcx. resolve_type_vars_if_possible ( & obligation. predicate ) ;
95
92
96
- if !predicate. references_error ( ) {
93
+ // The TyError created by normalize_to_error can end up being unified
94
+ // into all obligations: for example, if our obligation is something
95
+ // like `$X = <() as Foo<$X>>::Out` and () does not implement Foo<_>,
96
+ // then $X will be unified with TyError, but the error still needs to be
97
+ // reported.
98
+ if !infcx. tcx . sess . has_errors ( ) || !predicate. references_error ( ) {
97
99
let mut err = struct_span_err ! ( infcx. tcx. sess, obligation. cause. span, E0271 ,
98
100
"type mismatch resolving `{}`: {}" ,
99
101
predicate,
@@ -103,10 +105,9 @@ pub fn report_projection_error<'a, 'tcx>(infcx: &InferCtxt<'a, 'tcx>,
103
105
}
104
106
}
105
107
106
- fn on_unimplemented_note < ' a , ' tcx > ( infcx : & InferCtxt < ' a , ' tcx > ,
107
- trait_ref : ty:: PolyTraitRef < ' tcx > ,
108
- span : Span ) -> Option < String > {
109
- let trait_ref = trait_ref. skip_binder ( ) ;
108
+ fn report_on_unimplemented < ' a , ' tcx > ( infcx : & InferCtxt < ' a , ' tcx > ,
109
+ trait_ref : & TraitRef < ' tcx > ,
110
+ span : Span ) -> Option < String > {
110
111
let def_id = trait_ref. def_id ;
111
112
let mut report = None ;
112
113
for item in infcx. tcx . get_attrs ( def_id) . iter ( ) {
@@ -174,53 +175,6 @@ fn on_unimplemented_note<'a, 'tcx>(infcx: &InferCtxt<'a, 'tcx>,
174
175
report
175
176
}
176
177
177
- fn find_similar_impl_candidates < ' a , ' tcx > (
178
- infcx : & InferCtxt < ' a , ' tcx > ,
179
- trait_ref : ty:: PolyTraitRef < ' tcx > )
180
- -> Vec < ty:: TraitRef < ' tcx > >
181
- {
182
- let simp = fast_reject:: simplify_type ( infcx. tcx ,
183
- trait_ref. skip_binder ( ) . self_ty ( ) ,
184
- true ) ;
185
- let mut impl_candidates = Vec :: new ( ) ;
186
- let trait_def = infcx. tcx . lookup_trait_def ( trait_ref. def_id ( ) ) ;
187
-
188
- match simp {
189
- Some ( simp) => trait_def. for_each_impl ( infcx. tcx , |def_id| {
190
- let imp = infcx. tcx . impl_trait_ref ( def_id) . unwrap ( ) ;
191
- let imp_simp = fast_reject:: simplify_type ( infcx. tcx ,
192
- imp. self_ty ( ) ,
193
- true ) ;
194
- if let Some ( imp_simp) = imp_simp {
195
- if simp != imp_simp {
196
- return ;
197
- }
198
- }
199
- impl_candidates. push ( imp) ;
200
- } ) ,
201
- None => trait_def. for_each_impl ( infcx. tcx , |def_id| {
202
- impl_candidates. push (
203
- infcx. tcx . impl_trait_ref ( def_id) . unwrap ( ) ) ;
204
- } )
205
- } ;
206
- impl_candidates
207
- }
208
-
209
- fn report_similar_impl_candidates ( span : Span ,
210
- err : & mut DiagnosticBuilder ,
211
- impl_candidates : & [ ty:: TraitRef ] )
212
- {
213
- err. fileline_help ( span, & format ! ( "the following implementations were found:" ) ) ;
214
-
215
- let end = cmp:: min ( 4 , impl_candidates. len ( ) ) ;
216
- for candidate in & impl_candidates[ 0 ..end] {
217
- err. fileline_help ( span, & format ! ( " {:?}" , candidate) ) ;
218
- }
219
- if impl_candidates. len ( ) > 4 {
220
- err. fileline_help ( span, & format ! ( "and {} others" , impl_candidates. len( ) -4 ) ) ;
221
- }
222
- }
223
-
224
178
/// Reports that an overflow has occurred and halts compilation. We
225
179
/// halt compilation unconditionally because it is important that
226
180
/// overflows never be masked -- they basically represent computations
@@ -408,39 +362,56 @@ pub fn report_selection_error<'a, 'tcx>(infcx: &InferCtxt<'a, 'tcx>,
408
362
let trait_ref = trait_predicate. to_poly_trait_ref ( ) ;
409
363
let mut err = struct_span_err ! (
410
364
infcx. tcx. sess, obligation. cause. span, E0277 ,
411
- "the trait bound `{}` is not satisfied" ,
412
- trait_ref. to_predicate( ) ) ;
413
-
414
- // Try to report a help message
415
-
416
- if !trait_ref. has_infer_types ( ) &&
417
- predicate_can_apply ( infcx, trait_ref)
418
- {
419
- // If a where-clause may be useful, remind the
420
- // user that they can add it.
421
- //
422
- // don't display an on-unimplemented note, as
423
- // these notes will often be of the form
424
- // "the type `T` can't be frobnicated"
425
- // which is somewhat confusing.
426
- err. fileline_help ( obligation. cause . span , & format ! (
427
- "consider adding a `where {}` bound" ,
428
- trait_ref. to_predicate( )
429
- ) ) ;
430
- } else if let Some ( s) = on_unimplemented_note ( infcx, trait_ref,
431
- obligation. cause . span ) {
432
- // Otherwise, if there is an on-unimplemented note,
433
- // display it.
365
+ "the trait `{}` is not implemented for the type `{}`" ,
366
+ trait_ref, trait_ref. self_ty( ) ) ;
367
+
368
+ // Check if it has a custom "#[rustc_on_unimplemented]"
369
+ // error message, report with that message if it does
370
+ let custom_note = report_on_unimplemented ( infcx, & trait_ref. 0 ,
371
+ obligation. cause . span ) ;
372
+ if let Some ( s) = custom_note {
434
373
err. fileline_note ( obligation. cause . span , & s) ;
435
374
} else {
436
- // If we can't show anything useful, try to find
437
- // similar impls.
375
+ let simp = fast_reject:: simplify_type ( infcx. tcx ,
376
+ trait_ref. self_ty ( ) ,
377
+ true ) ;
378
+ let mut impl_candidates = Vec :: new ( ) ;
379
+ let trait_def = infcx. tcx . lookup_trait_def ( trait_ref. def_id ( ) ) ;
380
+
381
+ match simp {
382
+ Some ( simp) => trait_def. for_each_impl ( infcx. tcx , |def_id| {
383
+ let imp = infcx. tcx . impl_trait_ref ( def_id) . unwrap ( ) ;
384
+ let imp_simp = fast_reject:: simplify_type ( infcx. tcx ,
385
+ imp. self_ty ( ) ,
386
+ true ) ;
387
+ if let Some ( imp_simp) = imp_simp {
388
+ if simp != imp_simp {
389
+ return ;
390
+ }
391
+ }
392
+ impl_candidates. push ( imp) ;
393
+ } ) ,
394
+ None => trait_def. for_each_impl ( infcx. tcx , |def_id| {
395
+ impl_candidates. push (
396
+ infcx. tcx . impl_trait_ref ( def_id) . unwrap ( ) ) ;
397
+ } )
398
+ } ;
438
399
439
- let impl_candidates =
440
- find_similar_impl_candidates ( infcx, trait_ref) ;
441
400
if impl_candidates. len ( ) > 0 {
442
- report_similar_impl_candidates ( obligation. cause . span ,
443
- & mut err, & impl_candidates) ;
401
+ err. fileline_help (
402
+ obligation. cause . span ,
403
+ & format ! ( "the following implementations were found:" ) ) ;
404
+
405
+ let end = cmp:: min ( 4 , impl_candidates. len ( ) ) ;
406
+ for candidate in & impl_candidates[ 0 ..end] {
407
+ err. fileline_help ( obligation. cause . span ,
408
+ & format ! ( " {:?}" , candidate) ) ;
409
+ }
410
+ if impl_candidates. len ( ) > 4 {
411
+ err. fileline_help ( obligation. cause . span ,
412
+ & format ! ( "and {} others" ,
413
+ impl_candidates. len( ) -4 ) ) ;
414
+ }
444
415
}
445
416
}
446
417
note_obligation_cause ( infcx, & mut err, obligation) ;
@@ -678,55 +649,6 @@ pub fn maybe_report_ambiguity<'a, 'tcx>(infcx: &InferCtxt<'a, 'tcx>,
678
649
}
679
650
}
680
651
681
- /// Returns whether the trait predicate may apply for *some* assignment
682
- /// to the type parameters.
683
- fn predicate_can_apply < ' a , ' tcx > ( infcx : & InferCtxt < ' a , ' tcx > ,
684
- pred : ty:: PolyTraitRef < ' tcx > )
685
- -> bool
686
- {
687
- struct ParamToVarFolder < ' a , ' tcx : ' a > {
688
- infcx : & ' a InferCtxt < ' a , ' tcx > ,
689
- var_map : FnvHashMap < Ty < ' tcx > , Ty < ' tcx > >
690
- }
691
-
692
- impl < ' a , ' tcx > TypeFolder < ' tcx > for ParamToVarFolder < ' a , ' tcx >
693
- {
694
- fn tcx ( & self ) -> & TyCtxt < ' tcx > { self . infcx . tcx }
695
-
696
- fn fold_ty ( & mut self , ty : Ty < ' tcx > ) -> Ty < ' tcx > {
697
- if let ty:: TyParam ( ..) = ty. sty {
698
- let infcx = self . infcx ;
699
- self . var_map . entry ( ty) . or_insert_with ( || infcx. next_ty_var ( ) )
700
- } else {
701
- ty. super_fold_with ( self )
702
- }
703
- }
704
- }
705
-
706
- infcx. probe ( |_| {
707
- let mut selcx = SelectionContext :: new ( infcx) ;
708
-
709
- let cleaned_pred = pred. fold_with ( & mut ParamToVarFolder {
710
- infcx : infcx,
711
- var_map : FnvHashMap ( )
712
- } ) ;
713
-
714
- let cleaned_pred = super :: project:: normalize (
715
- & mut selcx,
716
- ObligationCause :: dummy ( ) ,
717
- & cleaned_pred
718
- ) . value ;
719
-
720
- let obligation = Obligation :: new (
721
- ObligationCause :: dummy ( ) ,
722
- cleaned_pred. to_predicate ( )
723
- ) ;
724
-
725
- selcx. evaluate_obligation ( & obligation)
726
- } )
727
- }
728
-
729
-
730
652
fn need_type_info < ' a , ' tcx > ( infcx : & InferCtxt < ' a , ' tcx > ,
731
653
span : Span ,
732
654
ty : Ty < ' tcx > )
0 commit comments