@@ -26,11 +26,11 @@ use super::{
26
26
27
27
use fmt_macros:: { Parser , Piece , Position } ;
28
28
use hir:: def_id:: DefId ;
29
- use infer:: { InferCtxt , TypeOrigin } ;
30
- use ty:: { self , ToPredicate , ToPolyTraitRef , TraitRef , Ty , TyCtxt , TypeFoldable , TypeVariants } ;
29
+ use infer:: { InferCtxt } ;
30
+ use ty:: { self , ToPredicate , ToPolyTraitRef , Ty , TyCtxt , TypeFoldable } ;
31
31
use ty:: fast_reject;
32
32
use ty:: fold:: TypeFolder ;
33
- use ty:: subst:: { self , ParamSpace , Subst } ;
33
+ use ty:: subst:: { self , Subst } ;
34
34
use util:: nodemap:: { FnvHashMap , FnvHashSet } ;
35
35
36
36
use std:: cmp;
@@ -61,128 +61,6 @@ impl<'a, 'gcx, 'tcx> TraitErrorKey<'tcx> {
61
61
}
62
62
}
63
63
64
- // Enum used to differentiate the "big" and "little" weights.
65
- enum Weight {
66
- Coarse ,
67
- Precise ,
68
- }
69
-
70
- trait AssociatedWeight {
71
- fn get_weight ( & self ) -> ( u32 , u32 ) ;
72
- }
73
-
74
- impl < ' a > AssociatedWeight for TypeVariants < ' a > {
75
- // Left number is for "global"/"big" weight and right number is for better precision.
76
- fn get_weight ( & self ) -> ( u32 , u32 ) {
77
- match * self {
78
- TypeVariants :: TyBool => ( 1 , 1 ) ,
79
- TypeVariants :: TyChar => ( 1 , 2 ) ,
80
- TypeVariants :: TyStr => ( 1 , 3 ) ,
81
-
82
- TypeVariants :: TyInt ( _) => ( 2 , 1 ) ,
83
- TypeVariants :: TyUint ( _) => ( 2 , 2 ) ,
84
- TypeVariants :: TyFloat ( _) => ( 2 , 3 ) ,
85
- TypeVariants :: TyRawPtr ( _) => ( 2 , 4 ) ,
86
-
87
- TypeVariants :: TyEnum ( _, _) => ( 3 , 1 ) ,
88
- TypeVariants :: TyStruct ( _, _) => ( 3 , 2 ) ,
89
- TypeVariants :: TyBox ( _) => ( 3 , 3 ) ,
90
- TypeVariants :: TyTuple ( _) => ( 3 , 4 ) ,
91
-
92
- TypeVariants :: TyArray ( _, _) => ( 4 , 1 ) ,
93
- TypeVariants :: TySlice ( _) => ( 4 , 2 ) ,
94
-
95
- TypeVariants :: TyRef ( _, _) => ( 5 , 1 ) ,
96
- TypeVariants :: TyFnDef ( _, _, _) => ( 5 , 2 ) ,
97
- TypeVariants :: TyFnPtr ( _) => ( 5 , 3 ) ,
98
-
99
- TypeVariants :: TyTrait ( _) => ( 6 , 1 ) ,
100
-
101
- TypeVariants :: TyClosure ( _, _) => ( 7 , 1 ) ,
102
-
103
- TypeVariants :: TyProjection ( _) => ( 8 , 1 ) ,
104
- TypeVariants :: TyParam ( _) => ( 8 , 2 ) ,
105
- TypeVariants :: TyInfer ( _) => ( 8 , 3 ) ,
106
-
107
- TypeVariants :: TyError => ( 9 , 1 ) ,
108
- }
109
- }
110
- }
111
-
112
- // The "closer" the types are, the lesser the weight.
113
- fn get_weight_diff ( a : & ty:: TypeVariants , b : & TypeVariants , weight : Weight ) -> u32 {
114
- let ( w1, w2) = match weight {
115
- Weight :: Coarse => ( a. get_weight ( ) . 0 , b. get_weight ( ) . 0 ) ,
116
- Weight :: Precise => ( a. get_weight ( ) . 1 , b. get_weight ( ) . 1 ) ,
117
- } ;
118
- if w1 < w2 {
119
- w2 - w1
120
- } else {
121
- w1 - w2
122
- }
123
- }
124
-
125
- // Once we have "globally matching" types, we need to run another filter on them.
126
- //
127
- // In the function `get_best_matching_type`, we got the types which might fit the
128
- // most to the type we're looking for. This second filter now intends to get (if
129
- // possible) the type which fits the most.
130
- //
131
- // For example, the trait expects an `usize` and here you have `u32` and `i32`.
132
- // Obviously, the "correct" one is `u32`.
133
- fn filter_matching_types < ' tcx > ( weights : & [ ( usize , u32 ) ] ,
134
- imps : & [ ( DefId , subst:: Substs < ' tcx > ) ] ,
135
- trait_types : & [ ty:: Ty < ' tcx > ] )
136
- -> usize {
137
- let matching_weight = weights[ 0 ] . 1 ;
138
- let iter = weights. iter ( ) . filter ( |& & ( _, weight) | weight == matching_weight) ;
139
- let mut filtered_weights = vec ! ( ) ;
140
-
141
- for & ( pos, _) in iter {
142
- let mut weight = 0 ;
143
- for ( type_to_compare, original_type) in imps[ pos] . 1
144
- . types
145
- . get_slice ( ParamSpace :: TypeSpace )
146
- . iter ( )
147
- . zip ( trait_types. iter ( ) ) {
148
- weight += get_weight_diff ( & type_to_compare. sty , & original_type. sty , Weight :: Precise ) ;
149
- }
150
- filtered_weights. push ( ( pos, weight) ) ;
151
- }
152
- filtered_weights. sort_by ( |a, b| a. 1 . cmp ( & b. 1 ) ) ;
153
- filtered_weights[ 0 ] . 0
154
- }
155
-
156
- // Here, we run the "big" filter. Little example:
157
- //
158
- // We receive a `String`, an `u32` and an `i32`.
159
- // The trait expected an `usize`.
160
- // From human point of view, it's easy to determine that `String` doesn't correspond to
161
- // the expected type at all whereas `u32` and `i32` could.
162
- //
163
- // This first filter intends to only keep the types which match the most.
164
- fn get_best_matching_type < ' tcx > ( imps : & [ ( DefId , subst:: Substs < ' tcx > ) ] ,
165
- trait_types : & [ ty:: Ty < ' tcx > ] ) -> usize {
166
- let mut weights = vec ! ( ) ;
167
- for ( pos, imp) in imps. iter ( ) . enumerate ( ) {
168
- let mut weight = 0 ;
169
- for ( type_to_compare, original_type) in imp. 1
170
- . types
171
- . get_slice ( ParamSpace :: TypeSpace )
172
- . iter ( )
173
- . zip ( trait_types. iter ( ) ) {
174
- weight += get_weight_diff ( & type_to_compare. sty , & original_type. sty , Weight :: Coarse ) ;
175
- }
176
- weights. push ( ( pos, weight) ) ;
177
- }
178
- weights. sort_by ( |a, b| a. 1 . cmp ( & b. 1 ) ) ;
179
- if weights[ 0 ] . 1 == weights[ 1 ] . 1 {
180
- filter_matching_types ( & weights, & imps, trait_types)
181
- } else {
182
- weights[ 0 ] . 0
183
- }
184
- }
185
-
186
64
impl < ' a , ' gcx , ' tcx > InferCtxt < ' a , ' gcx , ' tcx > {
187
65
pub fn report_fulfillment_errors ( & self , errors : & Vec < FulfillmentError < ' tcx > > ) {
188
66
for error in errors {
@@ -272,72 +150,53 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
272
150
substs
273
151
}
274
152
275
- fn get_current_failing_impl ( & self ,
276
- trait_ref : & TraitRef < ' tcx > ,
277
- obligation : & PredicateObligation < ' tcx > )
278
- -> Option < ( DefId , subst :: Substs < ' tcx > ) > {
279
- let simp = fast_reject :: simplify_type ( self . tcx ,
280
- trait_ref . self_ty ( ) ,
281
- true ) ;
282
- let trait_def = self . tcx . lookup_trait_def ( trait_ref . def_id ) ;
153
+ fn impl_with_self_type_of ( & self ,
154
+ trait_ref : ty :: PolyTraitRef < ' tcx > ,
155
+ obligation : & PredicateObligation < ' tcx > )
156
+ -> Option < DefId >
157
+ {
158
+ let tcx = self . tcx ;
159
+ let mut result = None ;
160
+ let mut ambiguous = false ;
283
161
284
- match simp {
285
- Some ( _) => {
286
- let mut matching_impls = Vec :: new ( ) ;
287
- trait_def. for_each_impl ( self . tcx , |def_id| {
288
- let imp = self . tcx . impl_trait_ref ( def_id) . unwrap ( ) ;
289
- let substs = self . impl_substs ( def_id, obligation. clone ( ) ) ;
290
- let imp = imp. subst ( self . tcx , & substs) ;
291
-
292
- if self . eq_types ( true ,
293
- TypeOrigin :: Misc ( obligation. cause . span ) ,
294
- trait_ref. self_ty ( ) ,
295
- imp. self_ty ( ) ) . is_ok ( ) {
296
- matching_impls. push ( ( def_id, imp. substs . clone ( ) ) ) ;
297
- }
298
- } ) ;
299
- if matching_impls. len ( ) == 0 {
300
- None
301
- } else if matching_impls. len ( ) == 1 {
302
- Some ( matching_impls[ 0 ] . clone ( ) )
303
- } else {
304
- let end = trait_ref. input_types ( ) . len ( ) - 1 ;
305
- // we need to determine which type is the good one!
306
- Some ( matching_impls[ get_best_matching_type ( & matching_impls,
307
- & trait_ref. input_types ( ) [ 0 ..end] ) ]
308
- . clone ( ) )
309
- }
310
- } ,
311
- None => None ,
162
+ let trait_self_ty = tcx. erase_late_bound_regions ( & trait_ref) . self_ty ( ) ;
163
+
164
+ if trait_self_ty. is_ty_var ( ) {
165
+ return None ;
312
166
}
313
- }
314
167
315
- fn find_attr ( & self ,
316
- def_id : DefId ,
317
- attr_name : & str )
318
- -> Option < ast:: Attribute > {
319
- for item in self . tcx . get_attrs ( def_id) . iter ( ) {
320
- if item. check_name ( attr_name) {
321
- return Some ( item. clone ( ) ) ;
322
- }
168
+ self . tcx . lookup_trait_def ( trait_ref. def_id ( ) )
169
+ . for_each_relevant_impl ( self . tcx , trait_self_ty, |def_id| {
170
+ let impl_self_ty = tcx
171
+ . impl_trait_ref ( def_id)
172
+ . unwrap ( )
173
+ . self_ty ( )
174
+ . subst ( tcx, & self . impl_substs ( def_id, obligation. clone ( ) ) ) ;
175
+
176
+ if !tcx. has_attr ( def_id, "rustc_on_unimplemented" ) {
177
+ return ;
178
+ }
179
+
180
+ if let Ok ( ..) = self . can_equate ( & trait_self_ty, & impl_self_ty) {
181
+ ambiguous = result. is_some ( ) ;
182
+ result = Some ( def_id) ;
183
+ }
184
+ } ) ;
185
+
186
+ if ambiguous {
187
+ None
188
+ } else {
189
+ result
323
190
}
324
- None
325
191
}
326
192
327
193
fn on_unimplemented_note ( & self ,
328
194
trait_ref : ty:: PolyTraitRef < ' tcx > ,
329
195
obligation : & PredicateObligation < ' tcx > ) -> Option < String > {
196
+ let def_id = self . impl_with_self_type_of ( trait_ref, obligation)
197
+ . unwrap_or ( trait_ref. def_id ( ) ) ;
330
198
let trait_ref = trait_ref. skip_binder ( ) ;
331
- let def_id = match self . get_current_failing_impl ( trait_ref, obligation) {
332
- Some ( ( def_id, _) ) => {
333
- if let Some ( _) = self . find_attr ( def_id, "rustc_on_unimplemented" ) {
334
- def_id
335
- } else {
336
- trait_ref. def_id
337
- }
338
- } ,
339
- None => trait_ref. def_id ,
340
- } ;
199
+
341
200
let span = obligation. cause . span ;
342
201
let mut report = None ;
343
202
for item in self . tcx . get_attrs ( def_id) . iter ( ) {
@@ -511,115 +370,15 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
511
370
/// that we can give a more helpful error message (and, in particular,
512
371
/// we do not suggest increasing the overflow limit, which is not
513
372
/// going to help).
514
- pub fn report_overflow_error_cycle ( & self , cycle : & Vec < PredicateObligation < ' tcx > > ) -> ! {
515
- assert ! ( cycle. len( ) > 1 ) ;
516
-
517
- debug ! ( "report_overflow_error_cycle(cycle length = {})" , cycle. len( ) ) ;
518
-
519
- let cycle = self . resolve_type_vars_if_possible ( cycle) ;
373
+ pub fn report_overflow_error_cycle ( & self , cycle : & [ PredicateObligation < ' tcx > ] ) -> ! {
374
+ let cycle = self . resolve_type_vars_if_possible ( & cycle. to_owned ( ) ) ;
375
+ assert ! ( cycle. len( ) > 0 ) ;
520
376
521
377
debug ! ( "report_overflow_error_cycle: cycle={:?}" , cycle) ;
522
378
523
- assert_eq ! ( & cycle[ 0 ] . predicate, & cycle. last( ) . unwrap( ) . predicate) ;
524
-
525
- self . try_report_overflow_error_type_of_infinite_size ( & cycle) ;
526
379
self . report_overflow_error ( & cycle[ 0 ] , false ) ;
527
380
}
528
381
529
- /// If a cycle results from evaluated whether something is Sized, that
530
- /// is a particular special case that always results from a struct or
531
- /// enum definition that lacks indirection (e.g., `struct Foo { x: Foo
532
- /// }`). We wish to report a targeted error for this case.
533
- pub fn try_report_overflow_error_type_of_infinite_size ( & self ,
534
- cycle : & [ PredicateObligation < ' tcx > ] )
535
- {
536
- let sized_trait = match self . tcx . lang_items . sized_trait ( ) {
537
- Some ( v) => v,
538
- None => return ,
539
- } ;
540
- let top_is_sized = {
541
- match cycle[ 0 ] . predicate {
542
- ty:: Predicate :: Trait ( ref data) => data. def_id ( ) == sized_trait,
543
- _ => false ,
544
- }
545
- } ;
546
- if !top_is_sized {
547
- return ;
548
- }
549
-
550
- // The only way to have a type of infinite size is to have,
551
- // somewhere, a struct/enum type involved. Identify all such types
552
- // and report the cycle to the user.
553
-
554
- let struct_enum_tys: Vec < _ > =
555
- cycle. iter ( )
556
- . flat_map ( |obligation| match obligation. predicate {
557
- ty:: Predicate :: Trait ( ref data) => {
558
- assert_eq ! ( data. def_id( ) , sized_trait) ;
559
- let self_ty = data. skip_binder ( ) . trait_ref . self_ty ( ) ; // (*)
560
- // (*) ok to skip binder because this is just
561
- // error reporting and regions don't really
562
- // matter
563
- match self_ty. sty {
564
- ty:: TyEnum ( ..) | ty:: TyStruct ( ..) => Some ( self_ty) ,
565
- _ => None ,
566
- }
567
- }
568
- _ => {
569
- span_bug ! ( obligation. cause. span,
570
- "Sized cycle involving non-trait-ref: {:?}" ,
571
- obligation. predicate) ;
572
- }
573
- } )
574
- . collect ( ) ;
575
-
576
- assert ! ( !struct_enum_tys. is_empty( ) ) ;
577
-
578
- // This is a bit tricky. We want to pick a "main type" in the
579
- // listing that is local to the current crate, so we can give a
580
- // good span to the user. But it might not be the first one in our
581
- // cycle list. So find the first one that is local and then
582
- // rotate.
583
- let ( main_index, main_def_id) =
584
- struct_enum_tys. iter ( )
585
- . enumerate ( )
586
- . filter_map ( |( index, ty) | match ty. sty {
587
- ty:: TyEnum ( adt_def, _) | ty:: TyStruct ( adt_def, _)
588
- if adt_def. did . is_local ( ) =>
589
- Some ( ( index, adt_def. did ) ) ,
590
- _ =>
591
- None ,
592
- } )
593
- . next ( )
594
- . unwrap ( ) ; // should always be SOME local type involved!
595
-
596
- // Rotate so that the "main" type is at index 0.
597
- let struct_enum_tys: Vec < _ > =
598
- struct_enum_tys. iter ( )
599
- . cloned ( )
600
- . skip ( main_index)
601
- . chain ( struct_enum_tys. iter ( ) . cloned ( ) . take ( main_index) )
602
- . collect ( ) ;
603
-
604
- let tcx = self . tcx ;
605
- let mut err = tcx. recursive_type_with_infinite_size_error ( main_def_id) ;
606
- let len = struct_enum_tys. len ( ) ;
607
- if len > 2 {
608
- err. note ( & format ! ( "type `{}` is embedded within `{}`..." ,
609
- struct_enum_tys[ 0 ] ,
610
- struct_enum_tys[ 1 ] ) ) ;
611
- for & next_ty in & struct_enum_tys[ 1 ..len-1 ] {
612
- err. note ( & format ! ( "...which in turn is embedded within `{}`..." , next_ty) ) ;
613
- }
614
- err. note ( & format ! ( "...which in turn is embedded within `{}`, \
615
- completing the cycle.",
616
- struct_enum_tys[ len-1 ] ) ) ;
617
- }
618
- err. emit ( ) ;
619
- self . tcx . sess . abort_if_errors ( ) ;
620
- bug ! ( ) ;
621
- }
622
-
623
382
pub fn report_selection_error ( & self ,
624
383
obligation : & PredicateObligation < ' tcx > ,
625
384
error : & SelectionError < ' tcx > ,
0 commit comments