Browse Source

Improve -vet shadowing to allow `x := x if cond else y` etc

gingerBill 3 years ago
parent
commit
b4df272eb5
1 changed files with 28 additions and 9 deletions
  1. 28 9
      src/checker.cpp

+ 28 - 9
src/checker.cpp

@@ -544,6 +544,28 @@ GB_COMPARE_PROC(vetted_entity_variable_pos_cmp) {
 	return token_pos_cmp(x->token.pos, y->token.pos);
 }
 
+bool check_vet_shadowing_assignment(Checker *c, Entity *shadowed, Ast *expr) {
+	Ast *init = unparen_expr(expr);
+	if (init == nullptr) {
+		return false;
+	}
+	if (init->kind == Ast_Ident) {
+		// TODO(bill): Which logic is better? Same name or same entity
+		// bool ignore = init->Ident.token.string == name;
+		bool ignore = init->Ident.entity == shadowed;
+		if (ignore) {
+			return true;
+		}
+	} else if (init->kind == Ast_TernaryIfExpr) {
+		bool x = check_vet_shadowing_assignment(c, shadowed, init->TernaryIfExpr.x);
+		bool y = check_vet_shadowing_assignment(c, shadowed, init->TernaryIfExpr.y);
+		if (x || y) {
+			return true;
+		}
+	}
+
+	return false;
+}
 
 
 bool check_vet_shadowing(Checker *c, Entity *e, VettedEntity *ve) {
@@ -594,17 +616,14 @@ bool check_vet_shadowing(Checker *c, Entity *e, VettedEntity *ve) {
 	}
 
 	// NOTE(bill): Ignore intentional redeclaration
-	// x := x;
+	// x := x
 	// Suggested in issue #637 (2020-05-11)
+	// Also allow the following
+	// x := x if cond else y
+	// x := z if cond else x
 	if ((e->flags & EntityFlag_Using) == 0 && e->kind == Entity_Variable) {
-		Ast *init = unparen_expr(e->Variable.init_expr);
-		if (init != nullptr && init->kind == Ast_Ident) {
-			// TODO(bill): Which logic is better? Same name or same entity
-			// bool ignore = init->Ident.token.string == name;
-			bool ignore = init->Ident.entity == shadowed;
-			if (ignore) {
-				return false;
-			}
+		if (check_vet_shadowing_assignment(c, shadowed, e->Variable.init_expr)) {
+			return false;
 		}
 	}