checker: fix invalid cast warning for flag enums (#12848)
							parent
							
								
									11d2b8b354
								
							
						
					
					
						commit
						65f12f3217
					
				| 
						 | 
					@ -3592,24 +3592,30 @@ pub fn (mut c Checker) cast_expr(mut node ast.CastExpr) ast.Type {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			if enum_decl := c.table.enum_decls[to_type_sym.name] {
 | 
								if enum_decl := c.table.enum_decls[to_type_sym.name] {
 | 
				
			||||||
				mut in_range := false
 | 
									mut in_range := false
 | 
				
			||||||
				mut enum_val := 0
 | 
									if enum_decl.is_flag {
 | 
				
			||||||
 | 
										// if a flag enum has 4 variants, the maximum possible value would have all 4 flags set (0b1111)
 | 
				
			||||||
 | 
										max_val := (1 << enum_decl.fields.len) - 1
 | 
				
			||||||
 | 
										in_range = node_val >= 0 && node_val <= max_val
 | 
				
			||||||
 | 
									} else {
 | 
				
			||||||
 | 
										mut enum_val := 0
 | 
				
			||||||
 | 
					
 | 
				
			||||||
				for enum_field in enum_decl.fields {
 | 
										for enum_field in enum_decl.fields {
 | 
				
			||||||
					// check if the field of the enum value is an integer literal
 | 
											// check if the field of the enum value is an integer literal
 | 
				
			||||||
					if enum_field.expr is ast.IntegerLiteral {
 | 
											if enum_field.expr is ast.IntegerLiteral {
 | 
				
			||||||
						enum_val = enum_field.expr.val.int()
 | 
												enum_val = enum_field.expr.val.int()
 | 
				
			||||||
 | 
											}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
											if node_val == enum_val {
 | 
				
			||||||
 | 
												in_range = true
 | 
				
			||||||
 | 
												break
 | 
				
			||||||
 | 
											}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
											enum_val += 1
 | 
				
			||||||
					}
 | 
										}
 | 
				
			||||||
 | 
					 | 
				
			||||||
					if node_val == enum_val {
 | 
					 | 
				
			||||||
						in_range = true
 | 
					 | 
				
			||||||
						break
 | 
					 | 
				
			||||||
					}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
					enum_val += 1
 | 
					 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
				if !in_range {
 | 
									if !in_range {
 | 
				
			||||||
					c.warn('$node_val does not represents a value of enum $enum_typ_name',
 | 
										c.warn('$node_val does not represent a value of enum $enum_typ_name',
 | 
				
			||||||
						node.pos)
 | 
											node.pos)
 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,6 +1,27 @@
 | 
				
			||||||
vlib/v/checker/tests/enum_cast.vv:6:13: error: 12 does not represents a value of enum Color
 | 
					vlib/v/checker/tests/enum_cast.vv:9:13: error: 12 does not represent a value of enum Color
 | 
				
			||||||
    4 |     println(Color(0))
 | 
					    7 |     println(Color(0))
 | 
				
			||||||
    5 |     println(Color(10))
 | 
					    8 |     println(Color(10))
 | 
				
			||||||
    6 |     println(Color(12))
 | 
					    9 |     println(Color(12))
 | 
				
			||||||
      |             ~~~~~~~~~
 | 
					      |             ~~~~~~~~~
 | 
				
			||||||
    7 | }
 | 
					   10 |     println(Color(-10))
 | 
				
			||||||
 | 
					   11 |
 | 
				
			||||||
 | 
					vlib/v/checker/tests/enum_cast.vv:10:13: error: -10 does not represent a value of enum Color
 | 
				
			||||||
 | 
					    8 |     println(Color(10))
 | 
				
			||||||
 | 
					    9 |     println(Color(12))
 | 
				
			||||||
 | 
					   10 |     println(Color(-10))
 | 
				
			||||||
 | 
					      |             ~~~~~~~~~~
 | 
				
			||||||
 | 
					   11 | 
 | 
				
			||||||
 | 
					   12 |     println(Permissions(0b101))
 | 
				
			||||||
 | 
					vlib/v/checker/tests/enum_cast.vv:13:13: error: 10 does not represent a value of enum Permissions
 | 
				
			||||||
 | 
					   11 | 
 | 
				
			||||||
 | 
					   12 |     println(Permissions(0b101))
 | 
				
			||||||
 | 
					   13 |     println(Permissions(0b1010))
 | 
				
			||||||
 | 
					      |             ~~~~~~~~~~~~~~~~~~~
 | 
				
			||||||
 | 
					   14 |     println(Permissions(-1))
 | 
				
			||||||
 | 
					   15 | }
 | 
				
			||||||
 | 
					vlib/v/checker/tests/enum_cast.vv:14:13: error: -1 does not represent a value of enum Permissions
 | 
				
			||||||
 | 
					   12 |     println(Permissions(0b101))
 | 
				
			||||||
 | 
					   13 |     println(Permissions(0b1010))
 | 
				
			||||||
 | 
					   14 |     println(Permissions(-1))
 | 
				
			||||||
 | 
					      |             ~~~~~~~~~~~~~~~
 | 
				
			||||||
 | 
					   15 | }
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,7 +1,15 @@
 | 
				
			||||||
enum Color { red green = 10 blue }
 | 
					enum Color { red green = 10 blue }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					[flag]
 | 
				
			||||||
 | 
					enum Permissions { read write execute }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
fn main() {
 | 
					fn main() {
 | 
				
			||||||
    println(Color(0))
 | 
					    println(Color(0))
 | 
				
			||||||
    println(Color(10))
 | 
					    println(Color(10))
 | 
				
			||||||
    println(Color(12))
 | 
					    println(Color(12))
 | 
				
			||||||
}
 | 
					    println(Color(-10))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    println(Permissions(0b101))
 | 
				
			||||||
 | 
					    println(Permissions(0b1010))
 | 
				
			||||||
 | 
					    println(Permissions(-1))
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in New Issue