@@ -105,44 +105,89 @@ impl UniversalRegionRelations<'tcx> {
105
105
106
106
/// Finds an "upper bound" for `fr` that is not local. In other
107
107
/// words, returns the smallest (*) known region `fr1` that (a)
108
- /// outlives `fr` and (b) is not local. This cannot fail, because
109
- /// we will always find `'static` at worst.
108
+ /// outlives `fr` and (b) is not local.
110
109
///
111
- /// (*) If there are multiple competing choices, we pick the "postdominating"
112
- /// one. See `TransitiveRelation::postdom_upper_bound` for details.
113
- crate fn non_local_upper_bound ( & self , fr : RegionVid ) -> RegionVid {
110
+ /// (*) If there are multiple competing choices, we return all of them.
111
+ crate fn non_local_upper_bounds ( & ' a self , fr : & ' a RegionVid ) -> Vec < & ' a RegionVid > {
114
112
debug ! ( "non_local_upper_bound(fr={:?})" , fr) ;
115
- self . non_local_bound ( & self . inverse_outlives , fr)
113
+ let res = self . non_local_bounds ( & self . inverse_outlives , fr) ;
114
+ assert ! ( !res. is_empty( ) , "can't find an upper bound!?" ) ;
115
+ res
116
+ }
117
+
118
+ /// Returns the "postdominating" bound of the set of
119
+ /// `non_local_upper_bounds` for the given region.
120
+ crate fn non_local_upper_bound ( & self , fr : RegionVid ) -> RegionVid {
121
+ let upper_bounds = self . non_local_upper_bounds ( & fr) ;
122
+
123
+ // In case we find more than one, reduce to one for
124
+ // convenience. This is to prevent us from generating more
125
+ // complex constraints, but it will cause spurious errors.
126
+ let post_dom = self
127
+ . inverse_outlives
128
+ . mutual_immediate_postdominator ( upper_bounds) ;
129
+
130
+ debug ! ( "non_local_bound: post_dom={:?}" , post_dom) ;
131
+
132
+ post_dom
133
+ . and_then ( |& post_dom| {
134
+ // If the mutual immediate postdom is not local, then
135
+ // there is no non-local result we can return.
136
+ if !self . universal_regions . is_local_free_region ( post_dom) {
137
+ Some ( post_dom)
138
+ } else {
139
+ None
140
+ }
141
+ } )
116
142
. unwrap_or ( self . universal_regions . fr_static )
117
143
}
118
144
145
+
119
146
/// Finds a "lower bound" for `fr` that is not local. In other
120
147
/// words, returns the largest (*) known region `fr1` that (a) is
121
- /// outlived by `fr` and (b) is not local. This cannot fail,
122
- /// because we will always find `'static` at worst.
148
+ /// outlived by `fr` and (b) is not local.
123
149
///
124
150
/// (*) If there are multiple competing choices, we pick the "postdominating"
125
151
/// one. See `TransitiveRelation::postdom_upper_bound` for details.
126
152
crate fn non_local_lower_bound ( & self , fr : RegionVid ) -> Option < RegionVid > {
127
153
debug ! ( "non_local_lower_bound(fr={:?})" , fr) ;
128
- self . non_local_bound ( & self . outlives , fr)
154
+ let lower_bounds = self . non_local_bounds ( & self . outlives , & fr) ;
155
+
156
+ // In case we find more than one, reduce to one for
157
+ // convenience. This is to prevent us from generating more
158
+ // complex constraints, but it will cause spurious errors.
159
+ let post_dom = self
160
+ . outlives
161
+ . mutual_immediate_postdominator ( lower_bounds) ;
162
+
163
+ debug ! ( "non_local_bound: post_dom={:?}" , post_dom) ;
164
+
165
+ post_dom
166
+ . and_then ( |& post_dom| {
167
+ // If the mutual immediate postdom is not local, then
168
+ // there is no non-local result we can return.
169
+ if !self . universal_regions . is_local_free_region ( post_dom) {
170
+ Some ( post_dom)
171
+ } else {
172
+ None
173
+ }
174
+ } )
129
175
}
130
176
131
- /// Helper for `non_local_upper_bound` and
132
- /// `non_local_lower_bound`. Repeatedly invokes `postdom_parent`
133
- /// until we find something that is not local. Returns `None` if we
134
- /// never do so.
135
- fn non_local_bound (
177
+ /// Helper for `non_local_upper_bounds` and `non_local_lower_bounds`.
178
+ /// Repeatedly invokes `postdom_parent` until we find something that is not
179
+ /// local. Returns `None` if we never do so.
180
+ fn non_local_bounds < ' a > (
136
181
& self ,
137
- relation : & TransitiveRelation < RegionVid > ,
138
- fr0 : RegionVid ,
139
- ) -> Option < RegionVid > {
182
+ relation : & ' a TransitiveRelation < RegionVid > ,
183
+ fr0 : & ' a RegionVid ,
184
+ ) -> Vec < & ' a RegionVid > {
140
185
// This method assumes that `fr0` is one of the universally
141
186
// quantified region variables.
142
- assert ! ( self . universal_regions. is_universal_region( fr0) ) ;
187
+ assert ! ( self . universal_regions. is_universal_region( * fr0) ) ;
143
188
144
189
let mut external_parents = vec ! [ ] ;
145
- let mut queue = vec ! [ & fr0] ;
190
+ let mut queue = vec ! [ fr0] ;
146
191
147
192
// Keep expanding `fr` into its parents until we reach
148
193
// non-local regions.
@@ -157,24 +202,7 @@ impl UniversalRegionRelations<'tcx> {
157
202
158
203
debug ! ( "non_local_bound: external_parents={:?}" , external_parents) ;
159
204
160
- // In case we find more than one, reduce to one for
161
- // convenience. This is to prevent us from generating more
162
- // complex constraints, but it will cause spurious errors.
163
- let post_dom = relation
164
- . mutual_immediate_postdominator ( external_parents)
165
- . cloned ( ) ;
166
-
167
- debug ! ( "non_local_bound: post_dom={:?}" , post_dom) ;
168
-
169
- post_dom. and_then ( |post_dom| {
170
- // If the mutual immediate postdom is not local, then
171
- // there is no non-local result we can return.
172
- if !self . universal_regions . is_local_free_region ( post_dom) {
173
- Some ( post_dom)
174
- } else {
175
- None
176
- }
177
- } )
205
+ external_parents
178
206
}
179
207
180
208
/// Returns `true` if fr1 is known to outlive fr2.
0 commit comments