@@ -105,44 +105,89 @@ impl UniversalRegionRelations<'tcx> {
105105
106106 /// Finds an "upper bound" for `fr` that is not local. In other
107107 /// 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.
110109 ///
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 > {
114112 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+ } )
116142 . unwrap_or ( self . universal_regions . fr_static )
117143 }
118144
145+
119146 /// Finds a "lower bound" for `fr` that is not local. In other
120147 /// 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.
123149 ///
124150 /// (*) If there are multiple competing choices, we pick the "postdominating"
125151 /// one. See `TransitiveRelation::postdom_upper_bound` for details.
126152 crate fn non_local_lower_bound ( & self , fr : RegionVid ) -> Option < RegionVid > {
127153 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+ } )
129175 }
130176
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 > (
136181 & self ,
137- relation : & TransitiveRelation < RegionVid > ,
138- fr0 : RegionVid ,
139- ) -> Option < RegionVid > {
182+ relation : & ' a TransitiveRelation < RegionVid > ,
183+ fr0 : & ' a RegionVid ,
184+ ) -> Vec < & ' a RegionVid > {
140185 // This method assumes that `fr0` is one of the universally
141186 // quantified region variables.
142- assert ! ( self . universal_regions. is_universal_region( fr0) ) ;
187+ assert ! ( self . universal_regions. is_universal_region( * fr0) ) ;
143188
144189 let mut external_parents = vec ! [ ] ;
145- let mut queue = vec ! [ & fr0] ;
190+ let mut queue = vec ! [ fr0] ;
146191
147192 // Keep expanding `fr` into its parents until we reach
148193 // non-local regions.
@@ -157,24 +202,7 @@ impl UniversalRegionRelations<'tcx> {
157202
158203 debug ! ( "non_local_bound: external_parents={:?}" , external_parents) ;
159204
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
178206 }
179207
180208 /// Returns `true` if fr1 is known to outlive fr2.
0 commit comments