13
13
14
14
use super :: { CombinedSnapshot ,
15
15
InferCtxt ,
16
+ LateBoundRegion ,
16
17
HigherRankedType ,
18
+ RegionVariableOrigin ,
17
19
SubregionOrigin ,
18
20
SkolemizationMap } ;
19
21
use super :: combine:: CombineFields ;
@@ -27,6 +29,15 @@ use util::nodemap::{FxHashMap, FxHashSet};
27
29
28
30
pub struct HrMatchResult < U > {
29
31
pub value : U ,
32
+
33
+ /// Normally, when we do a higher-ranked match operation, we
34
+ /// expect all higher-ranked regions to be constrained as part of
35
+ /// the match operation. However, in the transition period for
36
+ /// #32330, it can happen that we sometimes have unconstrained
37
+ /// regions that get instantiated with fresh variables. In that
38
+ /// case, we collect the set of unconstrained bound regions here
39
+ /// and replace them with fresh variables.
40
+ pub unconstrained_regions : Vec < ty:: BoundRegion > ,
30
41
}
31
42
32
43
impl < ' a , ' gcx , ' tcx > CombineFields < ' a , ' gcx , ' tcx > {
@@ -97,6 +108,7 @@ impl<'a, 'gcx, 'tcx> CombineFields<'a, 'gcx, 'tcx> {
97
108
/// that do not appear in `T`. If that happens, those regions are
98
109
/// unconstrained, and this routine replaces them with `'static`.
99
110
pub fn higher_ranked_match < T , U > ( & mut self ,
111
+ span : Span ,
100
112
a_pair : & Binder < ( T , U ) > ,
101
113
b_match : & T ,
102
114
a_is_expected : bool )
@@ -146,16 +158,28 @@ impl<'a, 'gcx, 'tcx> CombineFields<'a, 'gcx, 'tcx> {
146
158
// be any region from the sets above, except for other members of
147
159
// `skol_map`. There should always be a representative if things
148
160
// are properly well-formed.
161
+ let mut unconstrained_regions = vec ! [ ] ;
149
162
let skol_representatives: FxHashMap < _ , _ > =
150
163
skol_resolution_map
151
164
. iter ( )
152
- . map ( |( & skol, & ( _ , ref regions) ) | {
165
+ . map ( |( & skol, & ( br , ref regions) ) | {
153
166
let representative =
154
167
regions. iter ( )
155
168
. filter ( |& & r| !skol_resolution_map. contains_key ( r) )
156
169
. cloned ( )
157
170
. next ( )
158
- . expect ( "no representative region" ) ;
171
+ . unwrap_or_else ( || { // [1]
172
+ unconstrained_regions. push ( br) ;
173
+ self . infcx . next_region_var (
174
+ LateBoundRegion ( span, br, HigherRankedType ) )
175
+ } ) ;
176
+
177
+ // [1] There should always be a representative,
178
+ // unless the higher-ranked region did not appear
179
+ // in the values being matched. We should reject
180
+ // as ill-formed cases that can lead to this, but
181
+ // right now we sometimes issue warnings (see
182
+ // #32330).
159
183
160
184
( skol, representative)
161
185
} )
@@ -192,7 +216,10 @@ impl<'a, 'gcx, 'tcx> CombineFields<'a, 'gcx, 'tcx> {
192
216
// We are now done with these skolemized variables.
193
217
self . infcx . pop_skolemized ( skol_map, snapshot) ;
194
218
195
- Ok ( HrMatchResult { value : a_value } )
219
+ Ok ( HrMatchResult {
220
+ value : a_value,
221
+ unconstrained_regions,
222
+ } )
196
223
} ) ;
197
224
}
198
225
@@ -630,13 +657,28 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
630
657
skol_br,
631
658
tainted_region) ;
632
659
633
- return Err ( if overly_polymorphic {
660
+ let issue_32330 = if let & ty:: ReVar ( vid) = tainted_region {
661
+ match self . region_vars . var_origin ( vid) {
662
+ RegionVariableOrigin :: EarlyBoundRegion ( _, _, issue_32330) => {
663
+ issue_32330. map ( Box :: new)
664
+ }
665
+ _ => None
666
+ }
667
+ } else {
668
+ None
669
+ } ;
670
+
671
+ if overly_polymorphic {
634
672
debug ! ( "Overly polymorphic!" ) ;
635
- TypeError :: RegionsOverlyPolymorphic ( skol_br, tainted_region)
673
+ return Err ( TypeError :: RegionsOverlyPolymorphic ( skol_br,
674
+ tainted_region,
675
+ issue_32330) ) ;
636
676
} else {
637
677
debug ! ( "Not as polymorphic!" ) ;
638
- TypeError :: RegionsInsufficientlyPolymorphic ( skol_br, tainted_region)
639
- } )
678
+ return Err ( TypeError :: RegionsInsufficientlyPolymorphic ( skol_br,
679
+ tainted_region,
680
+ issue_32330) ) ;
681
+ }
640
682
}
641
683
}
642
684
0 commit comments