# # Test of using variables before assigning them # # Copyright © 2022-2024 Samuel Lidén Borell # # Permission is hereby granted, free of charge, to any person obtaining a copy # of this software and associated documentation files (the "Software"), to deal # in the Software without restriction, including without limitation the rights # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell # copies of the Software, and to permit persons to whom the Software is # furnished to do so, subject to the following conditions: # # The above copyright notice and this permission notice shall be included in # all copies or substantial portions of the Software. # # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN # THE SOFTWARE. # func test_definedness_return() -> bool { bool b # ERROR .12: error: Variable is (or might be) unassigned at this point return b } func test_definedness_init() -> bool { bool b # ERROR .14: error: Variable is (or might be) unassigned at this point bool c = b return c } func test_definedness_many() -> bool { bool b = true bool c = false bool d bool e = true bool dummy = b or c or e # ERROR .12: error: Variable is (or might be) unassigned at this point return d or dummy } func test_definedness_assign() -> bool { var bool c bool b # ERROR .9: error: Variable is (or might be) unassigned at this point c = b return c } func test_definedness_if(bool choice) -> bool { bool b if choice { b = true } # ERROR .12: error: Variable is (or might be) unassigned at this point return b } func test_definedness_else1(bool choice) -> bool { bool b if choice { b = true } else { } # ERROR .12: error: Variable is (or might be) unassigned at this point return b } func test_definedness_else2(bool choice) -> bool { bool b if choice { } else { b = true } # ERROR .12: error: Variable is (or might be) unassigned at this point return b } func test_definedness_else3(bool choice) -> bool { bool b if choice { b = true } else { # ERROR .16: error: Variable is (or might be) unassigned at this point return b } return false } func test_definedness_elseother1(bool choice) -> bool { bool b bool c if choice { b = true } else { c = false } # ERROR .12: error: Variable is (or might be) unassigned at this point return b } func test_definedness_elseother2(bool choice) -> bool { bool b bool c if choice { c = true } else { b = false } # ERROR .12: error: Variable is (or might be) unassigned at this point return b } func test_definedness_elseif1(int choice) -> bool { bool b if choice == 1 { b = true } else if choice == 2 { } else { b = true } # ERROR .12: error: Variable is (or might be) unassigned at this point return b } func test_definedness_elseif2(int choice) -> bool { bool b if choice == 1 { b = true } else if choice == 2 { b = false } else if choice == 3 { } else if choice == 4 { b = true } else { b = true } # ERROR .12: error: Variable is (or might be) unassigned at this point return b } func test_definedness_elseif3(int choice) -> bool { bool b if choice == 1 { b = true } else if choice == 2 { b = false } else if choice == 3 { } else if choice == 4 { b = true } else { b = true } # ERROR .12: error: Variable is (or might be) unassigned at this point return b } func test_definedness_elseif4(int choice) -> bool { bool b if choice == 1 { b = true } else if choice == 2 { b = false } # ERROR .32: error: Variable is (or might be) unassigned at this point else if choice == 3 return b return true } func test_definedness_while(int choice) -> bool { bool b while true { if choice == 1 break b = false break } # ERROR .12: error: Variable is (or might be) unassigned at this point return b } func test_definedness_dowhile(int choice) -> bool { bool b do { if choice == 1 break b = false } while false # ERROR .12: error: Variable is (or might be) unassigned at this point return b } func test_definedness_goto1(int num, bool flag) -> int { var int a var int b if num == 1 { goto other } else if num == 2 { a = 2 # ERROR .7: error: Jumping to this goto target might unset a variable other: b = 20 } else { a = 3 b = 30 } if flag return b return a } func test_definedness_goto2(int num, bool flag) -> int { var int a var int b var int c do { a = 1 goto loop2 } while true while true { b = 2 if num == b continue return 99 loop2: if num == 2 continue c = 3 goto out } out: # a,c set, but not b if num == 1 { b = 22 } goto nextone nextone: while num < 0 { b = 222 break } if flag return a else if num == 2 return c else { # ERROR .16: error: Variable is (or might be) unassigned at this point return b } } func test_definedness_struct_usage() { var ClosedTypeVer t var ClosedTypeVer u # ERROR .5: error: Variable is (or might be) unassigned at this point t.x = 123 # ERROR .9: error: Variable is (or might be) unassigned at this point u = t # ERROR .17: error: Variable is (or might be) unassigned at this point var int i = t.x } type OptTest = struct { ?ref OptTest next int x } func return_opt_struct() -> ?ref ClosedTypeVer { return none } func return_opt_array() -> ?ref [3]byte { return none } func take_nonopt_param(ref ClosedTypeVer non_opt) { } func test_definedness_nullability(?ref ClosedTypeVer param) { var ClosedTypeVer t = (.x = 123) var ?ref var ClosedTypeVer opt = none var ref var ClosedTypeVer nonopt = refto t # ERROR .5: error: Variable might be 'none' at this point opt.x = 123 # ERROR .14: error: Variable might be 'none' at this point nonopt = opt # ERROR .17: error: Variable might be 'none' at this point var int i = opt.x if opt == none { # ERROR .9: error: Variable might be 'none' at this point opt.x = 123 } if param == none { # ERROR .16: error: Variable might be 'none' at this point assert param.x == 123 } if param != none { # dummy } else { # ERROR .16: error: Variable might be 'none' at this point assert param.x == 123 } if param != none { # dummy } else if opt != none { # ERROR .16: error: Variable might be 'none' at this point assert param.x == 123 } # ERROR .23: error: Variable might be 'none' at this point take_nonopt_param(param) # ERROR .25: error: Can't access value of optional type without none-check if return_opt_struct().x == 123 { # ERROR .31: error: Can't access value of optional type without none-check } else if return_opt_array()[2] == 123 { } OptTest ot = (.next=none, .x=1111) # ERROR .15: error: Can't access value of optional type without none-check assert ot.next.x != 2222 ?ref OptTest otptr = refto ot # this must be var, because otherwise it gets replaced # with a literal none in all occurrences var ?ref OptTest otptr2 = none assert otptr.x == 1111 # ERROR .12: error: Variable might be 'none' at this point assert otptr2.x == 1111 otptr = none # ERROR .12: error: Variable might be 'none' at this point assert otptr.x == 1111 # ERROR .16: error: Variable might be 'none' at this point ot = deref otptr2 # ERROR .11: error: Variable might be 'none' at this point deref otptr2 = ot otptr2 = refto ot assert otptr2.x == 1111 usize ind = 1 var ?ref usize indptr = none var [3]byte arr = [11,22,33] # ERROR .15: error: Variable might be 'none' at this point arr[deref indptr] = 44 indptr = refto ind arr[deref indptr] = 55 }