@@ -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- , 
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