@@ -26,11 +26,11 @@ use super::{
2626
2727use fmt_macros:: { Parser , Piece , Position } ;
2828use 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 } ;
3131use ty:: fast_reject;
3232use ty:: fold:: TypeFolder ;
33- use ty:: subst:: { self , ParamSpace , Subst } ;
33+ use ty:: subst:: { self , Subst } ;
3434use util:: nodemap:: { FnvHashMap , FnvHashSet } ;
3535
3636use std:: cmp;
@@ -61,128 +61,6 @@ impl<'a, 'gcx, 'tcx> TraitErrorKey<'tcx> {
6161 }
6262}
6363
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-
18664impl < ' a , ' gcx , ' tcx > InferCtxt < ' a , ' gcx , ' tcx > {
18765 pub fn report_fulfillment_errors ( & self , errors : & Vec < FulfillmentError < ' tcx > > ) {
18866 for error in errors {
@@ -272,72 +150,53 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
272150 substs
273151 }
274152
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 ;
283161
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 ;
312166 }
313- }
314167
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
323190 }
324- None
325191 }
326192
327193 fn on_unimplemented_note ( & self ,
328194 trait_ref : ty:: PolyTraitRef < ' tcx > ,
329195 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 ( ) ) ;
330198 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+
341200 let span = obligation. cause . span ;
342201 let mut report = None ;
343202 for item in self . tcx . get_attrs ( def_id) . iter ( ) {
@@ -511,115 +370,15 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
511370 /// that we can give a more helpful error message (and, in particular,
512371 /// we do not suggest increasing the overflow limit, which is not
513372 /// 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 ) ;
520376
521377 debug ! ( "report_overflow_error_cycle: cycle={:?}" , cycle) ;
522378
523- assert_eq ! ( & cycle[ 0 ] . predicate, & cycle. last( ) . unwrap( ) . predicate) ;
524-
525- self . try_report_overflow_error_type_of_infinite_size ( & cycle) ;
526379 self . report_overflow_error ( & cycle[ 0 ] , false ) ;
527380 }
528381
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-
623382 pub fn report_selection_error ( & self ,
624383 obligation : & PredicateObligation < ' tcx > ,
625384 error : & SelectionError < ' tcx > ,
0 commit comments