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