@@ -55,75 +55,93 @@ impl<'tcx> RegionInferenceContext<'tcx> {
55
55
infcx : & InferCtxt < ' _ , ' tcx > ,
56
56
opaque_ty_decls : VecMap < OpaqueTypeKey < ' tcx > , ( OpaqueHiddenType < ' tcx > , OpaqueTyOrigin ) > ,
57
57
) -> 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) ;
63
62
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
69
80
}
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
90
88
}
91
- } ) ;
89
+ }
90
+ } ) ;
92
91
93
- subst_regions. sort ( ) ;
94
- subst_regions. dedup ( ) ;
92
+ subst_regions. sort ( ) ;
93
+ subst_regions. dedup ( ) ;
95
94
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
+ } ) ;
105
104
106
- debug ! ( ?universal_concrete_type, ?universal_substs) ;
105
+ debug ! ( ?universal_concrete_type, ?universal_substs) ;
107
106
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
127
145
}
128
146
129
147
/// Map the regions in the type to named regions. This is similar to what
0 commit comments