Skip to content

Commit 9760a9c

Browse files
authored
checker,transformer: add always true/false branch detection for the if and match constructs (#25674)
1 parent ae21217 commit 9760a9c

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

50 files changed

+1340
-48
lines changed

cmd/tools/changelog_helper.v

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -111,9 +111,6 @@ fn main() {
111111
}
112112
}
113113
os.write_file(log_txt, lines.join('\n'))!
114-
if true {
115-
// return
116-
}
117114
mut app := &App{
118115
total_lines: lines.len
119116
}
@@ -122,10 +119,6 @@ fn main() {
122119
category_titles)
123120
os.write_file('CHANGELOG.md', app.result)!
124121
changelog_txt := os.read_file('CHANGELOG.md')!.to_lower()
125-
if true {
126-
// println(changelog_txt)
127-
// return
128-
}
129122
// mut counter := 0 // to display how many commits are left
130123
for line in lines {
131124
s := line.trim_space()

vlib/os/filepath.v

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -218,18 +218,20 @@ fn clean_path(path string) string {
218218

219219
// to_slash returns the result of replacing each separator character in path with a slash (`/`).
220220
pub fn to_slash(path string) string {
221-
if path_separator == '/' {
222-
return path
221+
return $if windows {
222+
path.replace(path_separator, '/')
223+
} $else {
224+
path
223225
}
224-
return path.replace(path_separator, '/')
225226
}
226227

227228
// from_slash returns the result of replacing each slash (`/`) character is path with a separator character.
228229
pub fn from_slash(path string) string {
229-
if path_separator == '/' {
230-
return path
230+
return $if windows {
231+
path.replace('/', path_separator)
232+
} $else {
233+
path
231234
}
232-
return path.replace('/', path_separator)
233235
}
234236

235237
// win_volume_len returns the length of the

vlib/os/os.v

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ fn executable_fallback() string {
4444
}
4545
}
4646
if !is_abs_path(exepath) {
47-
other_separator := if path_separator == '/' { '\\' } else { '/' }
47+
other_separator := $if windows { '/' } $else { '\\' }
4848
rexepath := exepath.replace(other_separator, path_separator)
4949
if rexepath.contains(path_separator) {
5050
exepath = join_path_single(wd_at_startup, exepath)
@@ -848,7 +848,7 @@ pub fn mkdir_all(opath string, params MkdirParams) ! {
848848
}
849849
return error('path `${opath}` already exists, and is not a folder')
850850
}
851-
other_separator := if path_separator == '/' { '\\' } else { '/' }
851+
other_separator := $if windows { '/' } $else { '\\' }
852852
path := opath.replace(other_separator, path_separator)
853853
mut p := if path.starts_with(path_separator) { path_separator } else { '' }
854854
path_parts := path.trim_left(path_separator).split(path_separator)

vlib/v/checker/checker.v

Lines changed: 6 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -152,7 +152,8 @@ mut:
152152
v_current_commit_hash string // same as old C.V_CURRENT_COMMIT_HASH
153153
assign_stmt_attr string // for `x := [1,2,3] @[freed]`
154154

155-
js_string ast.Type = ast.void_type // when `js"string literal"` is used, `js_string` will be equal to `JS.String`
155+
js_string ast.Type = ast.void_type // when `js"string literal"` is used, `js_string` will be equal to `JS.String`
156+
checker_transformer &transformer.Transformer = unsafe { nil }
156157
}
157158

158159
pub fn new_checker(table &ast.Table, pref_ &pref.Preferences) &Checker {
@@ -174,6 +175,7 @@ pub fn new_checker(table &ast.Table, pref_ &pref.Preferences) &Checker {
174175
)
175176
match_exhaustive_cutoff_limit: pref_.checker_match_exhaustive_cutoff_limit
176177
v_current_commit_hash: v_current_commit_hash
178+
checker_transformer: transformer.new_transformer_with_table(table, pref_)
177179
}
178180
checker.type_resolver = type_resolver.TypeResolver.new(table, checker)
179181
checker.comptime = &checker.type_resolver.info
@@ -2109,8 +2111,7 @@ fn (mut c Checker) enum_decl(mut node ast.EnumDecl) {
21092111
ast.InfixExpr {
21102112
// Handle `enum Foo { x = 1 + 2 }`
21112113
c.infix_expr(mut field.expr)
2112-
mut t := transformer.new_transformer_with_table(c.table, c.pref)
2113-
folded_expr := t.infix_expr(mut field.expr)
2114+
folded_expr := c.checker_transformer.infix_expr(mut field.expr)
21142115

21152116
if folded_expr is ast.IntegerLiteral {
21162117
c.check_enum_field_integer_literal(folded_expr, signed, node.is_multi_allowed,
@@ -2120,8 +2121,7 @@ fn (mut c Checker) enum_decl(mut node ast.EnumDecl) {
21202121
}
21212122
ast.ParExpr {
21222123
c.expr(mut field.expr.expr)
2123-
mut t := transformer.new_transformer_with_table(c.table, c.pref)
2124-
folded_expr := t.expr(mut field.expr.expr)
2124+
folded_expr := c.checker_transformer.expr(mut field.expr.expr)
21252125

21262126
if folded_expr is ast.IntegerLiteral {
21272127
c.check_enum_field_integer_literal(folded_expr, signed, node.is_multi_allowed,
@@ -2160,9 +2160,7 @@ fn (mut c Checker) enum_decl(mut node ast.EnumDecl) {
21602160
if field.expr.kind == .constant && field.expr.obj.typ.is_int() {
21612161
// accepts int constants as enum value
21622162
if mut field.expr.obj is ast.ConstField {
2163-
mut t := transformer.new_transformer_with_table(c.table,
2164-
c.pref)
2165-
folded_expr := t.expr(mut field.expr.obj.expr)
2163+
folded_expr := c.checker_transformer.expr(mut field.expr.obj.expr)
21662164

21672165
if folded_expr is ast.IntegerLiteral {
21682166
c.check_enum_field_integer_literal(folded_expr, signed,

vlib/v/checker/if.v

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -156,6 +156,17 @@ fn (mut c Checker) if_expr(mut node ast.IfExpr) ast.Type {
156156
c.error('non-bool type `${c.table.type_to_str(cond_typ)}` used as if condition',
157157
branch.cond.pos())
158158
}
159+
if !c.pref.translated && !c.file.is_translated {
160+
mut check_expr := branch.cond
161+
t_expr := c.checker_transformer.expr(mut check_expr)
162+
if t_expr is ast.BoolLiteral {
163+
if t_expr.val {
164+
c.note('condition is always true', branch.cond.pos())
165+
} else {
166+
c.note('condition is always false', branch.cond.pos())
167+
}
168+
}
169+
}
159170
}
160171
} else {
161172
// else branch

vlib/v/checker/match.v

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -235,6 +235,25 @@ fn (mut c Checker) match_expr(mut node ast.MatchExpr) ast.Type {
235235
}
236236
}
237237

238+
if !c.pref.translated && !c.file.is_translated {
239+
// check for always true/false match branch
240+
for mut expr in branch.exprs {
241+
mut check_expr := ast.InfixExpr{
242+
op: .eq
243+
left: node.cond
244+
right: expr
245+
}
246+
t_expr := c.checker_transformer.expr(mut check_expr)
247+
if t_expr is ast.BoolLiteral {
248+
if t_expr.val {
249+
c.note('match is always true', expr.pos())
250+
} else {
251+
c.note('match is always false', expr.pos())
252+
}
253+
}
254+
}
255+
}
256+
238257
if !node.is_comptime || (node.is_comptime && comptime_match_branch_result) {
239258
if node.is_expr {
240259
c.stmts_ending_with_expression(mut branch.stmts, c.expected_or_type)

0 commit comments

Comments
 (0)