@@ -55,75 +55,93 @@ impl<'tcx> RegionInferenceContext<'tcx> {
5555        infcx :  & InferCtxt < ' _ ,  ' tcx > , 
5656        opaque_ty_decls :  VecMap < OpaqueTypeKey < ' tcx > ,  ( OpaqueHiddenType < ' tcx > ,  OpaqueTyOrigin ) > , 
5757    )  -> VecMap < OpaqueTypeKey < ' tcx > ,  OpaqueHiddenType < ' tcx > >  { 
58-         opaque_ty_decls
59-             . into_iter ( ) 
60-             . map ( |( opaque_type_key,  ( concrete_type,  origin) ) | { 
61-                 let  substs = opaque_type_key. substs ; 
62-                 debug ! ( ?concrete_type,  ?substs) ; 
58+         let  mut  result:  VecMap < OpaqueTypeKey < ' tcx > ,  OpaqueHiddenType < ' tcx > >  = VecMap :: new ( ) ; 
59+         for  ( opaque_type_key,  ( concrete_type,  origin) )  in  opaque_ty_decls { 
60+             let  substs = opaque_type_key. substs ; 
61+             debug ! ( ?concrete_type,  ?substs) ; 
6362
64-                 let  mut  subst_regions = vec ! [ self . universal_regions. fr_static] ; 
65-                 let  universal_substs = infcx. tcx . fold_regions ( substs,  & mut  false ,  |region,  _| { 
66-                     if  let  ty:: RePlaceholder ( ..)  = region. kind ( )  { 
67-                         // Higher kinded regions don't need remapping, they don't refer to anything outside of this the substs. 
68-                         return  region; 
63+             let  mut  subst_regions = vec ! [ self . universal_regions. fr_static] ; 
64+             let  universal_substs = infcx. tcx . fold_regions ( substs,  & mut  false ,  |region,  _| { 
65+                 if  let  ty:: RePlaceholder ( ..)  = region. kind ( )  { 
66+                     // Higher kinded regions don't need remapping, they don't refer to anything outside of this the substs. 
67+                     return  region; 
68+                 } 
69+                 let  vid = self . to_region_vid ( region) ; 
70+                 trace ! ( ?vid) ; 
71+                 let  scc = self . constraint_sccs . scc ( vid) ; 
72+                 trace ! ( ?scc) ; 
73+                 match  self . scc_values . universal_regions_outlived_by ( scc) . find_map ( |lb| { 
74+                     self . eval_equal ( vid,  lb) . then_some ( self . definitions [ lb] . external_name ?) 
75+                 } )  { 
76+                     Some ( region)  => { 
77+                         let  vid = self . universal_regions . to_region_vid ( region) ; 
78+                         subst_regions. push ( vid) ; 
79+                         region
6980                    } 
70-                     let  vid = self . to_region_vid ( region) ; 
71-                     trace ! ( ?vid) ; 
72-                     let  scc = self . constraint_sccs . scc ( vid) ; 
73-                     trace ! ( ?scc) ; 
74-                     match  self . scc_values . universal_regions_outlived_by ( scc) . find_map ( |lb| { 
75-                         self . eval_equal ( vid,  lb) . then_some ( self . definitions [ lb] . external_name ?) 
76-                     } )  { 
77-                         Some ( region)  => { 
78-                             let  vid = self . universal_regions . to_region_vid ( region) ; 
79-                             subst_regions. push ( vid) ; 
80-                             region
81-                         } 
82-                         None  => { 
83-                             subst_regions. push ( vid) ; 
84-                             infcx. tcx . sess . delay_span_bug ( 
85-                                 concrete_type. span , 
86-                                 "opaque type with non-universal region substs" , 
87-                             ) ; 
88-                             infcx. tcx . lifetimes . re_static 
89-                         } 
81+                     None  => { 
82+                         subst_regions. push ( vid) ; 
83+                         infcx. tcx . sess . delay_span_bug ( 
84+                             concrete_type. span , 
85+                             "opaque type with non-universal region substs" , 
86+                         ) ; 
87+                         infcx. tcx . lifetimes . re_static 
9088                    } 
91-                 } ) ; 
89+                 } 
90+             } ) ; 
9291
93-                  subst_regions. sort ( ) ; 
94-                  subst_regions. dedup ( ) ; 
92+             subst_regions. sort ( ) ; 
93+             subst_regions. dedup ( ) ; 
9594
96-                  let  universal_concrete_type =
97-                      infcx. tcx . fold_regions ( concrete_type,  & mut  false ,  |region,  _| match  * region { 
98-                          ty:: ReVar ( vid)  => subst_regions
99-                              . iter ( ) 
100-                              . find ( |ur_vid| self . eval_equal ( vid,  * * ur_vid) ) 
101-                              . and_then ( |ur_vid| self . definitions [ * ur_vid] . external_name ) 
102-                              . unwrap_or ( infcx. tcx . lifetimes . re_root_empty ) , 
103-                          _ => region, 
104-                      } ) ; 
95+             let  universal_concrete_type =
96+                 infcx. tcx . fold_regions ( concrete_type,  & mut  false ,  |region,  _| match  * region { 
97+                     ty:: ReVar ( vid)  => subst_regions
98+                         . iter ( ) 
99+                         . find ( |ur_vid| self . eval_equal ( vid,  * * ur_vid) ) 
100+                         . and_then ( |ur_vid| self . definitions [ * ur_vid] . external_name ) 
101+                         . unwrap_or ( infcx. tcx . lifetimes . re_root_empty ) , 
102+                     _ => region, 
103+                 } ) ; 
105104
106-                  debug ! ( ?universal_concrete_type,  ?universal_substs) ; 
105+             debug ! ( ?universal_concrete_type,  ?universal_substs) ; 
107106
108-                 let  opaque_type_key =
109-                     OpaqueTypeKey  {  def_id :  opaque_type_key. def_id ,  substs :  universal_substs } ; 
110-                 let  remapped_type = infcx. infer_opaque_definition_from_instantiation ( 
111-                     opaque_type_key, 
112-                     universal_concrete_type, 
113-                 ) ; 
114-                 let  ty = if  check_opaque_type_parameter_valid ( 
115-                     infcx. tcx , 
116-                     opaque_type_key, 
117-                     origin, 
118-                     concrete_type. span , 
119-                 )  { 
120-                     remapped_type
121-                 }  else  { 
122-                     infcx. tcx . ty_error ( ) 
123-                 } ; 
124-                 ( opaque_type_key,  OpaqueHiddenType  {  ty,  span :  concrete_type. span  } ) 
125-             } ) 
126-             . collect ( ) 
107+             let  opaque_type_key =
108+                 OpaqueTypeKey  {  def_id :  opaque_type_key. def_id ,  substs :  universal_substs } ; 
109+             let  remapped_type = infcx. infer_opaque_definition_from_instantiation ( 
110+                 opaque_type_key, 
111+                 universal_concrete_type, 
112+             ) ; 
113+             let  ty = if  check_opaque_type_parameter_valid ( 
114+                 infcx. tcx , 
115+                 opaque_type_key, 
116+                 origin, 
117+                 concrete_type. span , 
118+             )  { 
119+                 remapped_type
120+             }  else  { 
121+                 infcx. tcx . ty_error ( ) 
122+             } ; 
123+             // Sometimes two opaque types are the same only after we remap the generic parameters 
124+             // back to the opaque type definition. E.g. we may have `OpaqueType<X, Y>` mapped to `(X, Y)` 
125+             // and `OpaqueType<Y, X>` mapped to `(Y, X)`, and those are the same, but we only know that 
126+             // once we convert the generic parameters to those of the opaque type. 
127+             if  let  Some ( prev)  = result. get_mut ( & opaque_type_key)  { 
128+                 if  prev. ty  != ty { 
129+                     let  mut  err = infcx. tcx . sess . struct_span_err ( 
130+                         concrete_type. span , 
131+                         & format ! ( "hidden type `{}` differed from previous `{}`" ,  ty,  prev. ty) , 
132+                     ) ; 
133+                     err. span_note ( prev. span ,  "previous hidden type bound here" ) ; 
134+                     err. emit ( ) ; 
135+                     prev. ty  = infcx. tcx . ty_error ( ) ; 
136+                 } 
137+                 // Pick a better span if there is one. 
138+                 // FIXME(oli-obk): collect multiple spans for better diagnostics down the road. 
139+                 prev. span  = prev. span . substitute_dummy ( concrete_type. span ) ; 
140+             }  else  { 
141+                 result. insert ( opaque_type_key,  OpaqueHiddenType  {  ty,  span :  concrete_type. span  } ) ; 
142+             } 
143+         } 
144+         result
127145    } 
128146
129147    /// Map the regions in the type to named regions. This is similar to what 
0 commit comments