@@ -23,24 +23,31 @@ impl InferredType {
2323 /// Combine two values from different control-flow paths.
2424 ///
2525 /// `Unknown` means at least one path is opaque, so the result is unknown.
26- /// Distinct known subtypes join to `Felt`.
26+ /// Distinct known subtypes join to their least upper bound in the lattice
27+ /// `Bool <: U32 <: Felt`, with `Address` as a sibling of `U32`.
2728 pub fn combine_paths ( self , other : Self ) -> Self {
2829 match ( self , other) {
2930 ( a, b) if a == b => a,
3031 ( Self :: Unknown , _) | ( _, Self :: Unknown ) => Self :: Unknown ,
32+ // Bool <: U32
33+ ( Self :: Bool , Self :: U32 ) | ( Self :: U32 , Self :: Bool ) => Self :: U32 ,
3134 _ => Self :: Felt ,
3235 }
3336 }
3437
3538 /// Refine a stored type with newly inferred information.
3639 ///
3740 /// Existing `Unknown` values are replaced by `new_type`. Existing known
38- /// values are widened conservatively if they disagree.
41+ /// values are widened to their least upper bound in the lattice
42+ /// `Bool <: U32 <: Felt` if they disagree, with `Address` as a sibling
43+ /// of `U32`.
3944 pub fn refine ( self , new_type : Self ) -> Self {
4045 match ( self , new_type) {
4146 ( Self :: Unknown , t) => t,
4247 ( t, Self :: Unknown ) => t,
4348 ( a, b) if a == b => a,
49+ // Bool <: U32
50+ ( Self :: Bool , Self :: U32 ) | ( Self :: U32 , Self :: Bool ) => Self :: U32 ,
4451 _ => Self :: Felt ,
4552 }
4653 }
@@ -140,7 +147,7 @@ pub fn check_compatibility(actual: InferredType, expected: TypeRequirement) -> C
140147 } ,
141148 TypeRequirement :: U32 => match actual {
142149 InferredType :: Unknown => Compatibility :: Indeterminate ,
143- InferredType :: U32 => Compatibility :: Compatible ,
150+ InferredType :: U32 | InferredType :: Bool => Compatibility :: Compatible ,
144151 _ => Compatibility :: Incompatible ,
145152 } ,
146153 TypeRequirement :: Address => match actual {
@@ -187,6 +194,8 @@ impl VarKey {
187194mod tests {
188195 use super :: * ;
189196
197+ // -- check_compatibility --------------------------------------------------
198+
190199 #[ test]
191200 fn felt_accepts_promotable_types ( ) {
192201 assert_eq ! (
@@ -203,16 +212,36 @@ mod tests {
203212 ) ;
204213 }
205214
215+ #[ test]
216+ fn bool_is_compatible_with_u32 ( ) {
217+ assert_eq ! (
218+ check_compatibility( InferredType :: Bool , TypeRequirement :: U32 ) ,
219+ Compatibility :: Compatible
220+ ) ;
221+ }
222+
206223 #[ test]
207224 fn mismatched_exact_types_are_incompatible ( ) {
208225 assert_eq ! (
209226 check_compatibility( InferredType :: Felt , TypeRequirement :: Bool ) ,
210227 Compatibility :: Incompatible
211228 ) ;
229+ assert_eq ! (
230+ check_compatibility( InferredType :: Felt , TypeRequirement :: U32 ) ,
231+ Compatibility :: Incompatible
232+ ) ;
233+ assert_eq ! (
234+ check_compatibility( InferredType :: U32 , TypeRequirement :: Bool ) ,
235+ Compatibility :: Incompatible
236+ ) ;
212237 assert_eq ! (
213238 check_compatibility( InferredType :: Bool , TypeRequirement :: Address ) ,
214239 Compatibility :: Incompatible
215240 ) ;
241+ assert_eq ! (
242+ check_compatibility( InferredType :: Address , TypeRequirement :: Bool ) ,
243+ Compatibility :: Incompatible
244+ ) ;
216245 }
217246
218247 #[ test]
@@ -226,4 +255,124 @@ mod tests {
226255 Compatibility :: Indeterminate
227256 ) ;
228257 }
258+
259+ // -- combine_paths --------------------------------------------------------
260+
261+ #[ test]
262+ fn combine_paths_same_type ( ) {
263+ assert_eq ! (
264+ InferredType :: Bool . combine_paths( InferredType :: Bool ) ,
265+ InferredType :: Bool
266+ ) ;
267+ assert_eq ! (
268+ InferredType :: U32 . combine_paths( InferredType :: U32 ) ,
269+ InferredType :: U32
270+ ) ;
271+ assert_eq ! (
272+ InferredType :: Felt . combine_paths( InferredType :: Felt ) ,
273+ InferredType :: Felt
274+ ) ;
275+ }
276+
277+ #[ test]
278+ fn combine_paths_bool_u32_yields_u32 ( ) {
279+ assert_eq ! (
280+ InferredType :: Bool . combine_paths( InferredType :: U32 ) ,
281+ InferredType :: U32
282+ ) ;
283+ assert_eq ! (
284+ InferredType :: U32 . combine_paths( InferredType :: Bool ) ,
285+ InferredType :: U32
286+ ) ;
287+ }
288+
289+ #[ test]
290+ fn combine_paths_with_felt_yields_felt ( ) {
291+ assert_eq ! (
292+ InferredType :: Bool . combine_paths( InferredType :: Felt ) ,
293+ InferredType :: Felt
294+ ) ;
295+ assert_eq ! (
296+ InferredType :: U32 . combine_paths( InferredType :: Felt ) ,
297+ InferredType :: Felt
298+ ) ;
299+ assert_eq ! (
300+ InferredType :: Address . combine_paths( InferredType :: Felt ) ,
301+ InferredType :: Felt
302+ ) ;
303+ }
304+
305+ #[ test]
306+ fn combine_paths_address_siblings_yield_felt ( ) {
307+ assert_eq ! (
308+ InferredType :: Bool . combine_paths( InferredType :: Address ) ,
309+ InferredType :: Felt
310+ ) ;
311+ assert_eq ! (
312+ InferredType :: U32 . combine_paths( InferredType :: Address ) ,
313+ InferredType :: Felt
314+ ) ;
315+ }
316+
317+ #[ test]
318+ fn combine_paths_unknown_yields_unknown ( ) {
319+ assert_eq ! (
320+ InferredType :: Bool . combine_paths( InferredType :: Unknown ) ,
321+ InferredType :: Unknown
322+ ) ;
323+ assert_eq ! (
324+ InferredType :: Unknown . combine_paths( InferredType :: U32 ) ,
325+ InferredType :: Unknown
326+ ) ;
327+ }
328+
329+ // -- refine ---------------------------------------------------------------
330+
331+ #[ test]
332+ fn refine_unknown_takes_new ( ) {
333+ assert_eq ! (
334+ InferredType :: Unknown . refine( InferredType :: Bool ) ,
335+ InferredType :: Bool
336+ ) ;
337+ assert_eq ! (
338+ InferredType :: Unknown . refine( InferredType :: U32 ) ,
339+ InferredType :: U32
340+ ) ;
341+ }
342+
343+ #[ test]
344+ fn refine_bool_u32_yields_u32 ( ) {
345+ assert_eq ! (
346+ InferredType :: Bool . refine( InferredType :: U32 ) ,
347+ InferredType :: U32
348+ ) ;
349+ assert_eq ! (
350+ InferredType :: U32 . refine( InferredType :: Bool ) ,
351+ InferredType :: U32
352+ ) ;
353+ }
354+
355+ #[ test]
356+ fn refine_with_felt_yields_felt ( ) {
357+ assert_eq ! (
358+ InferredType :: Bool . refine( InferredType :: Felt ) ,
359+ InferredType :: Felt
360+ ) ;
361+ assert_eq ! (
362+ InferredType :: U32 . refine( InferredType :: Felt ) ,
363+ InferredType :: Felt
364+ ) ;
365+ }
366+
367+ #[ test]
368+ fn refine_address_siblings_yield_felt ( ) {
369+ assert_eq ! (
370+ InferredType :: Bool . refine( InferredType :: Address ) ,
371+ InferredType :: Felt
372+ ) ;
373+ assert_eq ! (
374+ InferredType :: U32 . refine( InferredType :: Address ) ,
375+ InferredType :: Felt
376+ ) ;
377+ }
229378}
0 commit comments