@@ -51,6 +51,166 @@ impl<I: Interner> Assumptions<I> {
5151 }
5252}
5353
54+ #[ derive_where( Clone , Hash , PartialEq , Debug ; I : Interner ) ]
55+ pub enum RegionConstraint < I : Interner > {
56+ Ambiguity ,
57+ RegionOutlives ( I :: Region , I :: Region ) ,
58+ AliasTyOutlivesFromEnv ( Binder < I , ( AliasTy < I > , I :: Region ) > ) ,
59+ /// This is an `I::Ty` for two reasons:
60+ /// 1. We need the type visitable impl to be able to `visit_ty` on this so canonicalization
61+ /// knows about the placeholder
62+ /// 2. When exiting the trait solver there may be placeholder outlives corresponding to params
63+ /// from the root universe. These need to be changed from a `Placeholder` to the original
64+ /// `Param`.
65+ PlaceholderTyOutlives ( I :: Ty , I :: Region ) ,
66+
67+ And ( Box < [ RegionConstraint < I > ] > ) ,
68+ Or ( Box < [ RegionConstraint < I > ] > ) ,
69+ }
70+
71+ #[ cfg( feature = "nightly" ) ]
72+ // This is not a derived impl because a perfect derive leads to cycle errors which
73+ // means the trait is never actually implemented but the compiler doesn't tell you
74+ // that so if you get a *WEIRD* error where its just telling you random types don't
75+ // implement HashStable.... it's because of that
76+ impl < CTX , I : Interner > HashStable < CTX > for RegionConstraint < I >
77+ where
78+ I :: Region : HashStable < CTX > ,
79+ AliasTy < I > : HashStable < CTX > ,
80+ I :: Ty : HashStable < CTX > ,
81+ I :: BoundVarKinds : HashStable < CTX > ,
82+ {
83+ #[ inline]
84+ fn hash_stable ( & self , hcx : & mut CTX , hasher : & mut StableHasher ) {
85+ use RegionConstraint :: * ;
86+
87+ std:: mem:: discriminant ( self ) . hash_stable ( hcx, hasher) ;
88+ match self {
89+ Ambiguity => ( ) ,
90+ RegionOutlives ( a, b) => {
91+ a. hash_stable ( hcx, hasher) ;
92+ b. hash_stable ( hcx, hasher) ;
93+ }
94+ AliasTyOutlivesFromEnv ( outlives) => {
95+ outlives. hash_stable ( hcx, hasher) ;
96+ }
97+ PlaceholderTyOutlives ( a, b) => {
98+ a. hash_stable ( hcx, hasher) ;
99+ b. hash_stable ( hcx, hasher) ;
100+ }
101+ And ( and) => {
102+ for a in and. iter ( ) {
103+ a. hash_stable ( hcx, hasher) ;
104+ }
105+ }
106+ Or ( or) => {
107+ for a in or. iter ( ) {
108+ a. hash_stable ( hcx, hasher) ;
109+ }
110+ }
111+ }
112+ }
113+ }
114+
115+ impl < I : Interner > TypeFoldable < I > for RegionConstraint < I > {
116+ fn try_fold_with < F : FallibleTypeFolder < I > > ( self , f : & mut F ) -> Result < Self , F :: Error > {
117+ use RegionConstraint :: * ;
118+ Ok ( match self {
119+ Ambiguity => self ,
120+ RegionOutlives ( a, b) => RegionOutlives ( a. try_fold_with ( f) ?, b. try_fold_with ( f) ?) ,
121+ AliasTyOutlivesFromEnv ( outlives) => AliasTyOutlivesFromEnv ( outlives. try_fold_with ( f) ?) ,
122+ PlaceholderTyOutlives ( a, b) => {
123+ PlaceholderTyOutlives ( a. try_fold_with ( f) ?, b. try_fold_with ( f) ?)
124+ }
125+ And ( and) => {
126+ let mut new_and = Vec :: new ( ) ;
127+ for a in and {
128+ new_and. push ( a. try_fold_with ( f) ?) ;
129+ }
130+ And ( new_and. into_boxed_slice ( ) )
131+ }
132+ Or ( or) => {
133+ let mut new_or = Vec :: new ( ) ;
134+ for a in or {
135+ new_or. push ( a. try_fold_with ( f) ?) ;
136+ }
137+ Or ( new_or. into_boxed_slice ( ) )
138+ }
139+ } )
140+ }
141+
142+ fn fold_with < F : TypeFolder < I > > ( self , f : & mut F ) -> Self {
143+ use RegionConstraint :: * ;
144+ match self {
145+ Ambiguity => self ,
146+ RegionOutlives ( a, b) => RegionOutlives ( a. fold_with ( f) , b. fold_with ( f) ) ,
147+ AliasTyOutlivesFromEnv ( outlives) => AliasTyOutlivesFromEnv ( outlives. fold_with ( f) ) ,
148+ PlaceholderTyOutlives ( a, b) => PlaceholderTyOutlives ( a. fold_with ( f) , b. fold_with ( f) ) ,
149+ And ( and) => {
150+ let mut new_and = Vec :: new ( ) ;
151+ for a in and {
152+ new_and. push ( a. fold_with ( f) ) ;
153+ }
154+ And ( new_and. into_boxed_slice ( ) )
155+ }
156+ Or ( or) => {
157+ let mut new_or = Vec :: new ( ) ;
158+ for a in or {
159+ new_or. push ( a. fold_with ( f) ) ;
160+ }
161+ Or ( new_or. into_boxed_slice ( ) )
162+ }
163+ }
164+ }
165+ }
166+
167+ impl < I : Interner > TypeVisitable < I > for RegionConstraint < I > {
168+ fn visit_with < F : TypeVisitor < I > > ( & self , f : & mut F ) -> F :: Result {
169+ use core:: ops:: ControlFlow :: * ;
170+
171+ use RegionConstraint :: * ;
172+
173+ match self {
174+ Ambiguity => ( ) ,
175+ RegionOutlives ( a, b) => {
176+ if let b @ Break ( _) = a. visit_with ( f) . branch ( ) {
177+ return F :: Result :: from_branch ( b) ;
178+ } ;
179+ if let b @ Break ( _) = b. visit_with ( f) . branch ( ) {
180+ return F :: Result :: from_branch ( b) ;
181+ } ;
182+ }
183+ AliasTyOutlivesFromEnv ( outlives) => {
184+ return outlives. visit_with ( f) ;
185+ }
186+ PlaceholderTyOutlives ( a, b) => {
187+ if let b @ Break ( _) = a. visit_with ( f) . branch ( ) {
188+ return F :: Result :: from_branch ( b) ;
189+ } ;
190+ if let b @ Break ( _) = b. visit_with ( f) . branch ( ) {
191+ return F :: Result :: from_branch ( b) ;
192+ } ;
193+ }
194+ And ( and) => {
195+ for a in and {
196+ if let b @ Break ( _) = a. visit_with ( f) . branch ( ) {
197+ return F :: Result :: from_branch ( b) ;
198+ } ;
199+ }
200+ }
201+ Or ( or) => {
202+ for a in or {
203+ if let b @ Break ( _) = a. visit_with ( f) . branch ( ) {
204+ return F :: Result :: from_branch ( b) ;
205+ } ;
206+ }
207+ }
208+ } ;
209+
210+ F :: Result :: output ( )
211+ }
212+ }
213+
54214pub fn max_universe < Infcx : InferCtxtLike < Interner = I > , I : Interner , T : TypeVisitable < I > > (
55215 infcx : & Infcx ,
56216 t : T ,
0 commit comments