checker: ban unsafe pointer/fn comparison (#14462)
parent
d81fbb1ccd
commit
17bba712bd
|
@ -207,7 +207,7 @@ fn change_detection_loop(ocontext &Context) {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn (mut context Context) kill_pgroup() {
|
fn (mut context Context) kill_pgroup() {
|
||||||
if context.child_process == 0 {
|
if unsafe { context.child_process == 0 } {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if context.child_process.is_alive() {
|
if context.child_process.is_alive() {
|
||||||
|
|
|
@ -95,7 +95,7 @@ pub fn (mut s System) explode(x f32, y f32) {
|
||||||
|
|
||||||
pub fn (mut s System) free() {
|
pub fn (mut s System) free() {
|
||||||
for p in s.pool {
|
for p in s.pool {
|
||||||
if p == 0 {
|
if unsafe { p == 0 } {
|
||||||
print(ptr_str(p) + ' ouch')
|
print(ptr_str(p) + ' ouch')
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
@ -103,7 +103,7 @@ pub fn (mut s System) free() {
|
||||||
}
|
}
|
||||||
s.pool.clear()
|
s.pool.clear()
|
||||||
for p in s.bin {
|
for p in s.bin {
|
||||||
if p == 0 {
|
if unsafe { p == 0 } {
|
||||||
print(ptr_str(p) + ' ouch')
|
print(ptr_str(p) + ' ouch')
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
|
@ -32,9 +32,10 @@ mut:
|
||||||
[unsafe]
|
[unsafe]
|
||||||
fn vmemory_block_new(prev &VMemoryBlock, at_least isize) &VMemoryBlock {
|
fn vmemory_block_new(prev &VMemoryBlock, at_least isize) &VMemoryBlock {
|
||||||
mut v := unsafe { &VMemoryBlock(C.calloc(1, sizeof(VMemoryBlock))) }
|
mut v := unsafe { &VMemoryBlock(C.calloc(1, sizeof(VMemoryBlock))) }
|
||||||
if prev != 0 {
|
if unsafe { prev != 0 } {
|
||||||
v.id = prev.id + 1
|
v.id = prev.id + 1
|
||||||
}
|
}
|
||||||
|
|
||||||
v.previous = prev
|
v.previous = prev
|
||||||
block_size := if at_least < prealloc_block_size { prealloc_block_size } else { at_least }
|
block_size := if at_least < prealloc_block_size { prealloc_block_size } else { at_least }
|
||||||
v.start = unsafe { C.malloc(block_size) }
|
v.start = unsafe { C.malloc(block_size) }
|
||||||
|
@ -79,7 +80,7 @@ fn prealloc_vcleanup() {
|
||||||
// The second loop however should *not* allocate at all.
|
// The second loop however should *not* allocate at all.
|
||||||
mut nr_mallocs := i64(0)
|
mut nr_mallocs := i64(0)
|
||||||
mut mb := g_memory_block
|
mut mb := g_memory_block
|
||||||
for mb != 0 {
|
for unsafe { mb != 0 } {
|
||||||
nr_mallocs += mb.mallocs
|
nr_mallocs += mb.mallocs
|
||||||
eprintln('> freeing mb.id: ${mb.id:3} | cap: ${mb.cap:7} | rem: ${mb.remaining:7} | start: ${voidptr(mb.start)} | current: ${voidptr(mb.current)} | diff: ${u64(mb.current) - u64(mb.start):7} bytes | mallocs: $mb.mallocs')
|
eprintln('> freeing mb.id: ${mb.id:3} | cap: ${mb.cap:7} | rem: ${mb.remaining:7} | start: ${voidptr(mb.start)} | current: ${voidptr(mb.current)} | diff: ${u64(mb.current) - u64(mb.start):7} bytes | mallocs: $mb.mallocs')
|
||||||
mb = mb.previous
|
mb = mb.previous
|
||||||
|
|
|
@ -53,7 +53,7 @@ pub fn (cmd Command) str() string {
|
||||||
res << ' cb execute: $cmd.execute'
|
res << ' cb execute: $cmd.execute'
|
||||||
res << ' cb pre_execute: $cmd.pre_execute'
|
res << ' cb pre_execute: $cmd.pre_execute'
|
||||||
res << ' cb post_execute: $cmd.post_execute'
|
res << ' cb post_execute: $cmd.post_execute'
|
||||||
if cmd.parent == 0 {
|
if unsafe { cmd.parent == 0 } {
|
||||||
res << ' parent: &Command(0)'
|
res << ' parent: &Command(0)'
|
||||||
} else {
|
} else {
|
||||||
res << ' parent: &Command{$cmd.parent.name ...}'
|
res << ' parent: &Command{$cmd.parent.name ...}'
|
||||||
|
|
|
@ -49,7 +49,7 @@ pub fn print_help_for_command(help_cmd Command) ? {
|
||||||
}
|
}
|
||||||
print(cmd.help_message())
|
print(cmd.help_message())
|
||||||
} else {
|
} else {
|
||||||
if help_cmd.parent != 0 {
|
if unsafe { help_cmd.parent != 0 } {
|
||||||
print(help_cmd.parent.help_message())
|
print(help_cmd.parent.help_message())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -41,7 +41,7 @@ pub fn print_manpage_for_command(man_cmd Command) ? {
|
||||||
}
|
}
|
||||||
print(cmd.manpage())
|
print(cmd.manpage())
|
||||||
} else {
|
} else {
|
||||||
if man_cmd.parent != 0 {
|
if unsafe { man_cmd.parent != 0 } {
|
||||||
print(man_cmd.parent.manpage())
|
print(man_cmd.parent.manpage())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -55,7 +55,7 @@ pub fn (cmd Command) manpage() string {
|
||||||
mdoc += '.Os\n.Sh NAME\n.Nm ${cmd.full_name().replace(' ', '-')}\n.Nd $cmd.description\n'
|
mdoc += '.Os\n.Sh NAME\n.Nm ${cmd.full_name().replace(' ', '-')}\n.Nd $cmd.description\n'
|
||||||
mdoc += '.Sh SYNOPSIS\n'
|
mdoc += '.Sh SYNOPSIS\n'
|
||||||
mdoc += '.Nm $cmd.root().name\n'
|
mdoc += '.Nm $cmd.root().name\n'
|
||||||
if cmd.parent != 0 {
|
if unsafe { cmd.parent != 0 } {
|
||||||
mut parents := []Command{}
|
mut parents := []Command{}
|
||||||
if !cmd.parent.is_root() {
|
if !cmd.parent.is_root() {
|
||||||
parents.prepend(cmd.parent)
|
parents.prepend(cmd.parent)
|
||||||
|
@ -96,7 +96,7 @@ pub fn (cmd Command) manpage() string {
|
||||||
}
|
}
|
||||||
if cmd.commands.len > 0 {
|
if cmd.commands.len > 0 {
|
||||||
mdoc += '.Nm $cmd.root().name\n'
|
mdoc += '.Nm $cmd.root().name\n'
|
||||||
if cmd.parent != 0 {
|
if unsafe { cmd.parent != 0 } {
|
||||||
mut parents := []Command{}
|
mut parents := []Command{}
|
||||||
if !cmd.parent.is_root() {
|
if !cmd.parent.is_root() {
|
||||||
parents.prepend(cmd.parent)
|
parents.prepend(cmd.parent)
|
||||||
|
@ -158,7 +158,7 @@ pub fn (cmd Command) manpage() string {
|
||||||
if cmd.commands.len > 0 {
|
if cmd.commands.len > 0 {
|
||||||
mdoc += '.Sh SEE ALSO\n'
|
mdoc += '.Sh SEE ALSO\n'
|
||||||
mut cmds := []string{}
|
mut cmds := []string{}
|
||||||
if cmd.parent != 0 {
|
if unsafe { cmd.parent != 0 } {
|
||||||
cmds << cmd.parent.full_name().replace(' ', '-')
|
cmds << cmd.parent.full_name().replace(' ', '-')
|
||||||
}
|
}
|
||||||
for c in cmd.commands {
|
for c in cmd.commands {
|
||||||
|
|
|
@ -76,13 +76,13 @@ pub fn (mut bst BSTree<T>) insert(value T) bool {
|
||||||
// insert_helper walks the tree and inserts the given node.
|
// insert_helper walks the tree and inserts the given node.
|
||||||
fn (mut bst BSTree<T>) insert_helper(mut node BSTreeNode<T>, value T) bool {
|
fn (mut bst BSTree<T>) insert_helper(mut node BSTreeNode<T>, value T) bool {
|
||||||
if node.value < value {
|
if node.value < value {
|
||||||
if node.right != 0 && node.right.is_init {
|
if unsafe { node.right != 0 } && node.right.is_init {
|
||||||
return bst.insert_helper(mut node.right, value)
|
return bst.insert_helper(mut node.right, value)
|
||||||
}
|
}
|
||||||
node.right = new_node(node, value)
|
node.right = new_node(node, value)
|
||||||
return true
|
return true
|
||||||
} else if node.value > value {
|
} else if node.value > value {
|
||||||
if node.left != 0 && node.left.is_init {
|
if unsafe { node.left != 0 } && node.left.is_init {
|
||||||
return bst.insert_helper(mut node.left, value)
|
return bst.insert_helper(mut node.left, value)
|
||||||
}
|
}
|
||||||
node.left = new_node(node, value)
|
node.left = new_node(node, value)
|
||||||
|
@ -99,7 +99,7 @@ pub fn (bst &BSTree<T>) contains(value T) bool {
|
||||||
// contains_helper is a helper function to walk the tree, and return
|
// contains_helper is a helper function to walk the tree, and return
|
||||||
// the absence or presence of the `value`.
|
// the absence or presence of the `value`.
|
||||||
fn (bst &BSTree<T>) contains_helper(node &BSTreeNode<T>, value T) bool {
|
fn (bst &BSTree<T>) contains_helper(node &BSTreeNode<T>, value T) bool {
|
||||||
if node == 0 || !node.is_init {
|
if unsafe { node == 0 } || !node.is_init {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
if node.value < value {
|
if node.value < value {
|
||||||
|
@ -124,12 +124,12 @@ fn (mut bst BSTree<T>) remove_helper(mut node BSTreeNode<T>, value T, left bool)
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
if node.value == value {
|
if node.value == value {
|
||||||
if node.left != 0 && node.left.is_init {
|
if unsafe { node.left != 0 } && node.left.is_init {
|
||||||
// In order to remove the element we need to bring up as parent the max of the
|
// In order to remove the element we need to bring up as parent the max of the
|
||||||
// left sub-tree.
|
// left sub-tree.
|
||||||
mut max_node := bst.get_max_from_right(node.left)
|
mut max_node := bst.get_max_from_right(node.left)
|
||||||
node.bind(mut max_node, true)
|
node.bind(mut max_node, true)
|
||||||
} else if node.right != 0 && node.right.is_init {
|
} else if unsafe { node.right != 0 } && node.right.is_init {
|
||||||
// Bring up the element with the minimum value in the right sub-tree.
|
// Bring up the element with the minimum value in the right sub-tree.
|
||||||
mut min_node := bst.get_min_from_left(node.right)
|
mut min_node := bst.get_min_from_left(node.right)
|
||||||
node.bind(mut min_node, false)
|
node.bind(mut min_node, false)
|
||||||
|
@ -153,11 +153,11 @@ fn (mut bst BSTree<T>) remove_helper(mut node BSTreeNode<T>, value T, left bool)
|
||||||
|
|
||||||
// get_max_from_right returns the max element of the BST following the right branch.
|
// get_max_from_right returns the max element of the BST following the right branch.
|
||||||
fn (bst &BSTree<T>) get_max_from_right(node &BSTreeNode<T>) &BSTreeNode<T> {
|
fn (bst &BSTree<T>) get_max_from_right(node &BSTreeNode<T>) &BSTreeNode<T> {
|
||||||
if node == 0 {
|
if unsafe { node == 0 } {
|
||||||
return new_none_node<T>(false)
|
return new_none_node<T>(false)
|
||||||
}
|
}
|
||||||
right_node := node.right
|
right_node := node.right
|
||||||
if right_node == 0 || !right_node.is_init {
|
if unsafe { right_node == 0 } || !right_node.is_init {
|
||||||
return node
|
return node
|
||||||
}
|
}
|
||||||
return bst.get_max_from_right(right_node)
|
return bst.get_max_from_right(right_node)
|
||||||
|
@ -165,11 +165,11 @@ fn (bst &BSTree<T>) get_max_from_right(node &BSTreeNode<T>) &BSTreeNode<T> {
|
||||||
|
|
||||||
// get_min_from_left returns the min element of the BST by following the left branch.
|
// get_min_from_left returns the min element of the BST by following the left branch.
|
||||||
fn (bst &BSTree<T>) get_min_from_left(node &BSTreeNode<T>) &BSTreeNode<T> {
|
fn (bst &BSTree<T>) get_min_from_left(node &BSTreeNode<T>) &BSTreeNode<T> {
|
||||||
if node == 0 {
|
if unsafe { node == 0 } {
|
||||||
return new_none_node<T>(false)
|
return new_none_node<T>(false)
|
||||||
}
|
}
|
||||||
left_node := node.left
|
left_node := node.left
|
||||||
if left_node == 0 || !left_node.is_init {
|
if unsafe { left_node == 0 } || !left_node.is_init {
|
||||||
return node
|
return node
|
||||||
}
|
}
|
||||||
return bst.get_min_from_left(left_node)
|
return bst.get_min_from_left(left_node)
|
||||||
|
@ -177,7 +177,7 @@ fn (bst &BSTree<T>) get_min_from_left(node &BSTreeNode<T>) &BSTreeNode<T> {
|
||||||
|
|
||||||
// is_empty checks if the BST is empty
|
// is_empty checks if the BST is empty
|
||||||
pub fn (bst &BSTree<T>) is_empty() bool {
|
pub fn (bst &BSTree<T>) is_empty() bool {
|
||||||
return bst.root == 0
|
return unsafe { bst.root == 0 }
|
||||||
}
|
}
|
||||||
|
|
||||||
// in_order_traversal traverses the BST in order, and returns the result as an array.
|
// in_order_traversal traverses the BST in order, and returns the result as an array.
|
||||||
|
@ -189,7 +189,7 @@ pub fn (bst &BSTree<T>) in_order_traversal() []T {
|
||||||
|
|
||||||
// in_order_traversal_helper helps traverse the BST, and accumulates the result in the `result` array.
|
// in_order_traversal_helper helps traverse the BST, and accumulates the result in the `result` array.
|
||||||
fn (bst &BSTree<T>) in_order_traversal_helper(node &BSTreeNode<T>, mut result []T) {
|
fn (bst &BSTree<T>) in_order_traversal_helper(node &BSTreeNode<T>, mut result []T) {
|
||||||
if node == 0 || !node.is_init {
|
if unsafe { node == 0 } || !node.is_init {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
bst.in_order_traversal_helper(node.left, mut result)
|
bst.in_order_traversal_helper(node.left, mut result)
|
||||||
|
@ -207,7 +207,7 @@ pub fn (bst &BSTree<T>) post_order_traversal() []T {
|
||||||
// post_order_traversal_helper is a helper function that traverses the BST in post order,
|
// post_order_traversal_helper is a helper function that traverses the BST in post order,
|
||||||
// accumulating the result in an array.
|
// accumulating the result in an array.
|
||||||
fn (bst &BSTree<T>) post_order_traversal_helper(node &BSTreeNode<T>, mut result []T) {
|
fn (bst &BSTree<T>) post_order_traversal_helper(node &BSTreeNode<T>, mut result []T) {
|
||||||
if node == 0 || !node.is_init {
|
if unsafe { node == 0 } || !node.is_init {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -226,7 +226,7 @@ pub fn (bst &BSTree<T>) pre_order_traversal() []T {
|
||||||
// pre_order_traversal_helper is a helper function to traverse the BST
|
// pre_order_traversal_helper is a helper function to traverse the BST
|
||||||
// in pre order and accumulates the results in an array.
|
// in pre order and accumulates the results in an array.
|
||||||
fn (bst &BSTree<T>) pre_order_traversal_helper(node &BSTreeNode<T>, mut result []T) {
|
fn (bst &BSTree<T>) pre_order_traversal_helper(node &BSTreeNode<T>, mut result []T) {
|
||||||
if node == 0 || !node.is_init {
|
if unsafe { node == 0 } || !node.is_init {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
result << node.value
|
result << node.value
|
||||||
|
@ -236,7 +236,7 @@ fn (bst &BSTree<T>) pre_order_traversal_helper(node &BSTreeNode<T>, mut result [
|
||||||
|
|
||||||
// get_node is a helper method to ge the internal rapresentation of the node with the `value`.
|
// get_node is a helper method to ge the internal rapresentation of the node with the `value`.
|
||||||
fn (bst &BSTree<T>) get_node(node &BSTreeNode<T>, value T) &BSTreeNode<T> {
|
fn (bst &BSTree<T>) get_node(node &BSTreeNode<T>, value T) &BSTreeNode<T> {
|
||||||
if node == 0 || !node.is_init {
|
if unsafe { node == 0 } || !node.is_init {
|
||||||
return new_none_node<T>(false)
|
return new_none_node<T>(false)
|
||||||
}
|
}
|
||||||
if node.value == value {
|
if node.value == value {
|
||||||
|
|
|
@ -251,7 +251,7 @@ pub fn (mut list DoublyLinkedList<T>) delete(idx int) {
|
||||||
pub fn (list DoublyLinkedList<T>) str() string {
|
pub fn (list DoublyLinkedList<T>) str() string {
|
||||||
mut result_array := []T{}
|
mut result_array := []T{}
|
||||||
mut node := list.head
|
mut node := list.head
|
||||||
for node != 0 {
|
for unsafe { node != 0 } {
|
||||||
result_array << node.data
|
result_array << node.data
|
||||||
node = node.next
|
node = node.next
|
||||||
}
|
}
|
||||||
|
|
|
@ -29,11 +29,11 @@ pub fn (list LinkedList<T>) first() ?T {
|
||||||
|
|
||||||
// last returns the last element of the linked list
|
// last returns the last element of the linked list
|
||||||
pub fn (list LinkedList<T>) last() ?T {
|
pub fn (list LinkedList<T>) last() ?T {
|
||||||
if list.head == 0 {
|
if unsafe { list.head == 0 } {
|
||||||
return error('Linked list is empty')
|
return error('Linked list is empty')
|
||||||
} else {
|
} else {
|
||||||
mut node := list.head
|
mut node := list.head
|
||||||
for node.next != 0 {
|
for unsafe { node.next != 0 } {
|
||||||
node = node.next
|
node = node.next
|
||||||
}
|
}
|
||||||
return node.data
|
return node.data
|
||||||
|
@ -42,12 +42,12 @@ pub fn (list LinkedList<T>) last() ?T {
|
||||||
|
|
||||||
// index returns the element at the given index of the linked list
|
// index returns the element at the given index of the linked list
|
||||||
pub fn (list LinkedList<T>) index(idx int) ?T {
|
pub fn (list LinkedList<T>) index(idx int) ?T {
|
||||||
if list.head == 0 {
|
if unsafe { list.head == 0 } {
|
||||||
return error('Linked list is empty')
|
return error('Linked list is empty')
|
||||||
} else {
|
} else {
|
||||||
mut node := list.head
|
mut node := list.head
|
||||||
mut iterations := 0
|
mut iterations := 0
|
||||||
for node.next != 0 && iterations < idx {
|
for unsafe { node.next != 0 } && iterations < idx {
|
||||||
node = node.next
|
node = node.next
|
||||||
iterations++
|
iterations++
|
||||||
}
|
}
|
||||||
|
@ -64,12 +64,12 @@ pub fn (mut list LinkedList<T>) push(item T) {
|
||||||
new_node := &ListNode<T>{
|
new_node := &ListNode<T>{
|
||||||
data: item
|
data: item
|
||||||
}
|
}
|
||||||
if list.head == 0 {
|
if unsafe { list.head == 0 } {
|
||||||
// first node case
|
// first node case
|
||||||
list.head = new_node
|
list.head = new_node
|
||||||
} else {
|
} else {
|
||||||
mut node := list.head
|
mut node := list.head
|
||||||
for node.next != 0 {
|
for unsafe { node.next != 0 } {
|
||||||
node = node.next
|
node = node.next
|
||||||
}
|
}
|
||||||
node.next = new_node
|
node.next = new_node
|
||||||
|
@ -79,17 +79,17 @@ pub fn (mut list LinkedList<T>) push(item T) {
|
||||||
|
|
||||||
// pop removes the last element of the linked list
|
// pop removes the last element of the linked list
|
||||||
pub fn (mut list LinkedList<T>) pop() ?T {
|
pub fn (mut list LinkedList<T>) pop() ?T {
|
||||||
if list.head == 0 {
|
if unsafe { list.head == 0 } {
|
||||||
return error('Linked list is empty')
|
return error('Linked list is empty')
|
||||||
}
|
}
|
||||||
mut node := list.head
|
mut node := list.head
|
||||||
mut to_return := node.data
|
mut to_return := node.data
|
||||||
if node.next == 0 {
|
if unsafe { node.next == 0 } {
|
||||||
// first node case
|
// first node case
|
||||||
// set to null
|
// set to null
|
||||||
list.head = voidptr(0)
|
list.head = voidptr(0)
|
||||||
} else {
|
} else {
|
||||||
for node.next.next != 0 {
|
for unsafe { node.next.next != 0 } {
|
||||||
node = node.next
|
node = node.next
|
||||||
}
|
}
|
||||||
to_return = node.next.data
|
to_return = node.next.data
|
||||||
|
@ -102,7 +102,7 @@ pub fn (mut list LinkedList<T>) pop() ?T {
|
||||||
|
|
||||||
// shift removes the first element of the linked list
|
// shift removes the first element of the linked list
|
||||||
pub fn (mut list LinkedList<T>) shift() ?T {
|
pub fn (mut list LinkedList<T>) shift() ?T {
|
||||||
if list.head == 0 {
|
if unsafe { list.head == 0 } {
|
||||||
return error('Linked list is empty')
|
return error('Linked list is empty')
|
||||||
} else {
|
} else {
|
||||||
list.len -= 1
|
list.len -= 1
|
||||||
|
@ -149,7 +149,7 @@ pub fn (mut list LinkedList<T>) prepend(item T) {
|
||||||
pub fn (list LinkedList<T>) str() string {
|
pub fn (list LinkedList<T>) str() string {
|
||||||
mut result_array := []T{}
|
mut result_array := []T{}
|
||||||
mut node := list.head
|
mut node := list.head
|
||||||
for node != 0 {
|
for unsafe { node != 0 } {
|
||||||
result_array << node.data
|
result_array << node.data
|
||||||
node = node.next
|
node = node.next
|
||||||
}
|
}
|
||||||
|
|
|
@ -32,7 +32,7 @@ fn test_access_parent() {
|
||||||
mut dom := parse(generate_temp_html())
|
mut dom := parse(generate_temp_html())
|
||||||
div_tags := dom.get_tag('div')
|
div_tags := dom.get_tag('div')
|
||||||
parent := div_tags[0].parent
|
parent := div_tags[0].parent
|
||||||
assert parent != 0
|
assert unsafe { parent != 0 }
|
||||||
for div_tag in div_tags {
|
for div_tag in div_tags {
|
||||||
assert div_tag.parent == parent
|
assert div_tag.parent == parent
|
||||||
}
|
}
|
||||||
|
|
|
@ -176,7 +176,7 @@ fn (mut p Process) win_write_string(idx int, s string) {
|
||||||
|
|
||||||
fn (mut p Process) win_read_string(idx int, maxbytes int) (string, int) {
|
fn (mut p Process) win_read_string(idx int, maxbytes int) (string, int) {
|
||||||
mut wdata := &WProcess(p.wdata)
|
mut wdata := &WProcess(p.wdata)
|
||||||
if wdata == 0 {
|
if unsafe { wdata == 0 } {
|
||||||
return '', 0
|
return '', 0
|
||||||
}
|
}
|
||||||
mut rhandle := &u32(0)
|
mut rhandle := &u32(0)
|
||||||
|
@ -207,7 +207,7 @@ fn (mut p Process) win_read_string(idx int, maxbytes int) (string, int) {
|
||||||
|
|
||||||
fn (mut p Process) win_slurp(idx int) string {
|
fn (mut p Process) win_slurp(idx int) string {
|
||||||
mut wdata := &WProcess(p.wdata)
|
mut wdata := &WProcess(p.wdata)
|
||||||
if wdata == 0 {
|
if unsafe { wdata == 0 } {
|
||||||
return ''
|
return ''
|
||||||
}
|
}
|
||||||
mut rhandle := &u32(0)
|
mut rhandle := &u32(0)
|
||||||
|
|
|
@ -645,7 +645,7 @@ pub fn channel_select(mut channels []&Channel, dir []Direction, mut objrefs []vo
|
||||||
unsafe {
|
unsafe {
|
||||||
*subscr[i].prev = subscr[i].nxt
|
*subscr[i].prev = subscr[i].nxt
|
||||||
}
|
}
|
||||||
if subscr[i].nxt != 0 {
|
if unsafe { subscr[i].nxt != 0 } {
|
||||||
subscr[i].nxt.prev = subscr[i].prev
|
subscr[i].nxt.prev = subscr[i].prev
|
||||||
// just in case we have missed a semaphore during restore
|
// just in case we have missed a semaphore during restore
|
||||||
subscr[i].nxt.sem.post()
|
subscr[i].nxt.sem.post()
|
||||||
|
@ -659,7 +659,7 @@ pub fn channel_select(mut channels []&Channel, dir []Direction, mut objrefs []vo
|
||||||
unsafe {
|
unsafe {
|
||||||
*subscr[i].prev = subscr[i].nxt
|
*subscr[i].prev = subscr[i].nxt
|
||||||
}
|
}
|
||||||
if subscr[i].nxt != 0 {
|
if unsafe { subscr[i].nxt != 0 } {
|
||||||
subscr[i].nxt.prev = subscr[i].prev
|
subscr[i].nxt.prev = subscr[i].prev
|
||||||
subscr[i].nxt.sem.post()
|
subscr[i].nxt.sem.post()
|
||||||
}
|
}
|
||||||
|
|
|
@ -21,7 +21,7 @@ mut:
|
||||||
}
|
}
|
||||||
|
|
||||||
fn restore_terminal_state() {
|
fn restore_terminal_state() {
|
||||||
if ui.ctx_ptr != 0 {
|
if unsafe { ui.ctx_ptr != 0 } {
|
||||||
if ui.ctx_ptr.cfg.use_alternate_buffer {
|
if ui.ctx_ptr.cfg.use_alternate_buffer {
|
||||||
// clear the terminal and set the cursor to the origin
|
// clear the terminal and set the cursor to the origin
|
||||||
print('\x1b[2J\x1b[3J')
|
print('\x1b[2J\x1b[3J')
|
||||||
|
@ -84,7 +84,7 @@ pub fn init(cfg Config) &Context {
|
||||||
for code in ctx.cfg.reset {
|
for code in ctx.cfg.reset {
|
||||||
os.signal_opt(code, fn (_ os.Signal) {
|
os.signal_opt(code, fn (_ os.Signal) {
|
||||||
mut c := ui.ctx_ptr
|
mut c := ui.ctx_ptr
|
||||||
if c != 0 {
|
if unsafe { c != 0 } {
|
||||||
c.cleanup()
|
c.cleanup()
|
||||||
}
|
}
|
||||||
exit(0)
|
exit(0)
|
||||||
|
|
|
@ -44,7 +44,7 @@ fn restore_terminal_state_signal(_ os.Signal) {
|
||||||
fn restore_terminal_state() {
|
fn restore_terminal_state() {
|
||||||
termios_reset()
|
termios_reset()
|
||||||
mut c := ctx_ptr
|
mut c := ctx_ptr
|
||||||
if c != 0 {
|
if unsafe { c != 0 } {
|
||||||
c.paused = true
|
c.paused = true
|
||||||
load_title()
|
load_title()
|
||||||
}
|
}
|
||||||
|
@ -121,7 +121,7 @@ fn (mut ctx Context) termios_setup() ? {
|
||||||
os.signal_opt(.tstp, restore_terminal_state_signal) or {}
|
os.signal_opt(.tstp, restore_terminal_state_signal) or {}
|
||||||
os.signal_opt(.cont, fn (_ os.Signal) {
|
os.signal_opt(.cont, fn (_ os.Signal) {
|
||||||
mut c := ctx_ptr
|
mut c := ctx_ptr
|
||||||
if c != 0 {
|
if unsafe { c != 0 } {
|
||||||
c.termios_setup() or { panic(err) }
|
c.termios_setup() or { panic(err) }
|
||||||
c.window_height, c.window_width = get_terminal_size()
|
c.window_height, c.window_width = get_terminal_size()
|
||||||
mut event := &Event{
|
mut event := &Event{
|
||||||
|
@ -136,7 +136,7 @@ fn (mut ctx Context) termios_setup() ? {
|
||||||
for code in ctx.cfg.reset {
|
for code in ctx.cfg.reset {
|
||||||
os.signal_opt(code, fn (_ os.Signal) {
|
os.signal_opt(code, fn (_ os.Signal) {
|
||||||
mut c := ctx_ptr
|
mut c := ctx_ptr
|
||||||
if c != 0 {
|
if unsafe { c != 0 } {
|
||||||
c.cleanup()
|
c.cleanup()
|
||||||
}
|
}
|
||||||
exit(0)
|
exit(0)
|
||||||
|
@ -145,7 +145,7 @@ fn (mut ctx Context) termios_setup() ? {
|
||||||
|
|
||||||
os.signal_opt(.winch, fn (_ os.Signal) {
|
os.signal_opt(.winch, fn (_ os.Signal) {
|
||||||
mut c := ctx_ptr
|
mut c := ctx_ptr
|
||||||
if c != 0 {
|
if unsafe { c != 0 } {
|
||||||
c.window_height, c.window_width = get_terminal_size()
|
c.window_height, c.window_width = get_terminal_size()
|
||||||
|
|
||||||
mut event := &Event{
|
mut event := &Event{
|
||||||
|
@ -200,7 +200,7 @@ fn termios_reset() {
|
||||||
C.tcsetattr(C.STDIN_FILENO, C.TCSAFLUSH, &ui.termios_at_startup)
|
C.tcsetattr(C.STDIN_FILENO, C.TCSAFLUSH, &ui.termios_at_startup)
|
||||||
print('\x1b[?1003l\x1b[?1006l\x1b[?25h')
|
print('\x1b[?1003l\x1b[?1006l\x1b[?25h')
|
||||||
c := ctx_ptr
|
c := ctx_ptr
|
||||||
if c != 0 && c.cfg.use_alternate_buffer {
|
if unsafe { c != 0 } && c.cfg.use_alternate_buffer {
|
||||||
print('\x1b[?1049l')
|
print('\x1b[?1049l')
|
||||||
}
|
}
|
||||||
os.flush()
|
os.flush()
|
||||||
|
@ -267,7 +267,7 @@ fn (mut ctx Context) parse_events() {
|
||||||
ctx.shift(1)
|
ctx.shift(1)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if event != 0 {
|
if unsafe { event != 0 } {
|
||||||
ctx.event(event)
|
ctx.event(event)
|
||||||
nr_iters = 0
|
nr_iters = 0
|
||||||
}
|
}
|
||||||
|
|
|
@ -547,6 +547,15 @@ pub fn (t &Table) type_kind(typ Type) Kind {
|
||||||
return t.sym(typ).kind
|
return t.sym(typ).kind
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn (t &Table) type_is_for_pointer_arithmetic(typ Type) bool {
|
||||||
|
typ_sym := t.sym(typ)
|
||||||
|
if typ_sym.kind == .struct_ {
|
||||||
|
return false
|
||||||
|
} else {
|
||||||
|
return typ.is_any_kind_of_pointer() || typ.is_int_valptr()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub enum Kind {
|
pub enum Kind {
|
||||||
placeholder
|
placeholder
|
||||||
void
|
void
|
||||||
|
|
|
@ -592,6 +592,13 @@ pub fn (mut c Checker) infix_expr(mut node ast.InfixExpr) ast.Type {
|
||||||
}
|
}
|
||||||
c.error('infix expr: cannot use `$right_sym.name` (right expression) as `$left_sym.name`',
|
c.error('infix expr: cannot use `$right_sym.name` (right expression) as `$left_sym.name`',
|
||||||
left_right_pos)
|
left_right_pos)
|
||||||
|
} else if left_type.is_ptr() {
|
||||||
|
for_ptr_op := c.table.type_is_for_pointer_arithmetic(left_type)
|
||||||
|
if left_sym.language == .v && !c.inside_unsafe && !for_ptr_op && right_type.is_int() {
|
||||||
|
sugg := ' (you can use it inside an `unsafe` block)'
|
||||||
|
c.error('infix expr: cannot use `$right_sym.name` (right expression) as `$left_sym.name` $sugg',
|
||||||
|
left_right_pos)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
/*
|
/*
|
||||||
if (node.left is ast.InfixExpr &&
|
if (node.left is ast.InfixExpr &&
|
||||||
|
|
|
@ -0,0 +1,7 @@
|
||||||
|
vlib/v/checker/tests/checker_comparison_between_obj_and_int.vv:10:5: error: infix expr: cannot use `int literal` (right expression) as `Foo` (you can use it inside an `unsafe` block)
|
||||||
|
8 |
|
||||||
|
9 | fn insert_helper(mut node Foo) {
|
||||||
|
10 | if node == 0 {
|
||||||
|
| ~~~~~~~~~
|
||||||
|
11 | }
|
||||||
|
12 | }
|
|
@ -0,0 +1,14 @@
|
||||||
|
struct Foo {}
|
||||||
|
|
||||||
|
// inside a unsafe block it is valid
|
||||||
|
fn insert_helper_unsafe(mut node Foo) {
|
||||||
|
if unsafe { node == 0 } {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn insert_helper(mut node Foo) {
|
||||||
|
if node == 0 {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {}
|
|
@ -288,7 +288,7 @@ fn (mut g Gen) comptime_if(node ast.IfExpr) {
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// Only wrap the contents in {} if we're inside a function, not on the top level scope
|
// Only wrap the contents in {} if we're inside a function, not on the top level scope
|
||||||
should_create_scope := g.fn_decl != 0
|
should_create_scope := unsafe { g.fn_decl != 0 }
|
||||||
if should_create_scope {
|
if should_create_scope {
|
||||||
g.writeln('{')
|
g.writeln('{')
|
||||||
}
|
}
|
||||||
|
|
|
@ -717,7 +717,7 @@ fn (mut g Gen) method_call(node ast.CallExpr) {
|
||||||
g.checker_bug('CallExpr.receiver_type is 0 in method_call', node.pos)
|
g.checker_bug('CallExpr.receiver_type is 0 in method_call', node.pos)
|
||||||
}
|
}
|
||||||
mut unwrapped_rec_type := node.receiver_type
|
mut unwrapped_rec_type := node.receiver_type
|
||||||
if g.cur_fn != 0 && g.cur_fn.generic_names.len > 0 { // in generic fn
|
if unsafe { g.cur_fn != 0 } && g.cur_fn.generic_names.len > 0 { // in generic fn
|
||||||
unwrapped_rec_type = g.unwrap_generic(node.receiver_type)
|
unwrapped_rec_type = g.unwrap_generic(node.receiver_type)
|
||||||
} else { // in non-generic fn
|
} else { // in non-generic fn
|
||||||
sym := g.table.sym(node.receiver_type)
|
sym := g.table.sym(node.receiver_type)
|
||||||
|
|
|
@ -18,7 +18,8 @@ fn (mut g Gen) index_expr(node ast.IndexExpr) {
|
||||||
} else if sym.kind == .map {
|
} else if sym.kind == .map {
|
||||||
g.index_of_map(node, sym)
|
g.index_of_map(node, sym)
|
||||||
} else if sym.kind == .string && !node.left_type.is_ptr() {
|
} else if sym.kind == .string && !node.left_type.is_ptr() {
|
||||||
is_direct_array_access := (g.fn_decl != 0 && g.fn_decl.is_direct_arr) || node.is_direct
|
is_direct_array_access := (unsafe { g.fn_decl != 0 } && g.fn_decl.is_direct_arr)
|
||||||
|
|| node.is_direct
|
||||||
if is_direct_array_access {
|
if is_direct_array_access {
|
||||||
g.expr(node.left)
|
g.expr(node.left)
|
||||||
g.write('.str[ ')
|
g.write('.str[ ')
|
||||||
|
@ -174,7 +175,8 @@ fn (mut g Gen) index_of_array(node ast.IndexExpr, sym ast.TypeSymbol) {
|
||||||
// `vals[i].field = x` is an exception and requires `array_get`:
|
// `vals[i].field = x` is an exception and requires `array_get`:
|
||||||
// `(*(Val*)array_get(vals, i)).field = x;`
|
// `(*(Val*)array_get(vals, i)).field = x;`
|
||||||
if g.is_assign_lhs && node.is_setter {
|
if g.is_assign_lhs && node.is_setter {
|
||||||
is_direct_array_access := (g.fn_decl != 0 && g.fn_decl.is_direct_arr) || node.is_direct
|
is_direct_array_access := (unsafe { g.fn_decl != 0 } && g.fn_decl.is_direct_arr)
|
||||||
|
|| node.is_direct
|
||||||
is_op_assign := g.assign_op != .assign && info.elem_type != ast.string_type
|
is_op_assign := g.assign_op != .assign && info.elem_type != ast.string_type
|
||||||
if is_direct_array_access {
|
if is_direct_array_access {
|
||||||
g.write('(($elem_type_str*)')
|
g.write('(($elem_type_str*)')
|
||||||
|
@ -233,7 +235,8 @@ fn (mut g Gen) index_of_array(node ast.IndexExpr, sym ast.TypeSymbol) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
is_direct_array_access := (g.fn_decl != 0 && g.fn_decl.is_direct_arr) || node.is_direct
|
is_direct_array_access := (unsafe { g.fn_decl != 0 } && g.fn_decl.is_direct_arr)
|
||||||
|
|| node.is_direct
|
||||||
// do not clone inside `opt_ok(opt_ok(&(string[]) {..})` before returns
|
// do not clone inside `opt_ok(opt_ok(&(string[]) {..})` before returns
|
||||||
needs_clone := info.elem_type == ast.string_type_idx && g.is_autofree && !(g.inside_return
|
needs_clone := info.elem_type == ast.string_type_idx && g.is_autofree && !(g.inside_return
|
||||||
&& g.fn_decl.return_type.has_flag(.optional)) && !g.is_assign_lhs
|
&& g.fn_decl.return_type.has_flag(.optional)) && !g.is_assign_lhs
|
||||||
|
@ -335,7 +338,7 @@ fn (mut g Gen) index_of_fixed_array(node ast.IndexExpr, sym ast.TypeSymbol) {
|
||||||
g.expr(node.left)
|
g.expr(node.left)
|
||||||
}
|
}
|
||||||
g.write('[')
|
g.write('[')
|
||||||
direct := g.fn_decl != 0 && g.fn_decl.is_direct_arr
|
direct := unsafe { g.fn_decl != 0 } && g.fn_decl.is_direct_arr
|
||||||
if (direct || node.index is ast.IntegerLiteral) || g.pref.translated {
|
if (direct || node.index is ast.IntegerLiteral) || g.pref.translated {
|
||||||
g.expr(node.index)
|
g.expr(node.index)
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -91,7 +91,8 @@ fn (mut g Gen) match_expr(node ast.MatchExpr) {
|
||||||
typ := g.table.final_sym(node.cond_type)
|
typ := g.table.final_sym(node.cond_type)
|
||||||
if node.is_sum_type {
|
if node.is_sum_type {
|
||||||
g.match_expr_sumtype(node, is_expr, cond_var, tmp_var)
|
g.match_expr_sumtype(node, is_expr, cond_var, tmp_var)
|
||||||
} else if typ.kind == .enum_ && g.loop_depth == 0 && node.branches.len > 5 && g.fn_decl != 0 { // do not optimize while in top-level
|
} else if typ.kind == .enum_ && g.loop_depth == 0 && node.branches.len > 5
|
||||||
|
&& unsafe { g.fn_decl != 0 } { // do not optimize while in top-level
|
||||||
g.match_expr_switch(node, is_expr, cond_var, tmp_var, typ)
|
g.match_expr_switch(node, is_expr, cond_var, tmp_var, typ)
|
||||||
} else {
|
} else {
|
||||||
g.match_expr_classic(node, is_expr, cond_var, tmp_var)
|
g.match_expr_classic(node, is_expr, cond_var, tmp_var)
|
||||||
|
|
|
@ -16,7 +16,7 @@ fn (mut g Gen) unwrap_generic(typ ast.Type) ast.Type {
|
||||||
non-mut to make sure no one else can accidentally mutates the table.
|
non-mut to make sure no one else can accidentally mutates the table.
|
||||||
*/
|
*/
|
||||||
mut muttable := unsafe { &ast.Table(g.table) }
|
mut muttable := unsafe { &ast.Table(g.table) }
|
||||||
if t_typ := muttable.resolve_generic_to_concrete(typ, if g.cur_fn != 0 {
|
if t_typ := muttable.resolve_generic_to_concrete(typ, if unsafe { g.cur_fn != 0 } {
|
||||||
g.cur_fn.generic_names
|
g.cur_fn.generic_names
|
||||||
} else {
|
} else {
|
||||||
[]string{}
|
[]string{}
|
||||||
|
|
|
@ -45,7 +45,7 @@ fn (mut g JsGen) js_mname(name_ string) string {
|
||||||
''
|
''
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if g.ns == 0 {
|
} else if unsafe { g.ns == 0 } {
|
||||||
name
|
name
|
||||||
} else if ns == g.ns.name {
|
} else if ns == g.ns.name {
|
||||||
name.split('.').last()
|
name.split('.').last()
|
||||||
|
@ -222,7 +222,7 @@ fn (mut g JsGen) method_call(node ast.CallExpr) {
|
||||||
g.get_str_fn(rec_type)
|
g.get_str_fn(rec_type)
|
||||||
}
|
}
|
||||||
mut unwrapped_rec_type := node.receiver_type
|
mut unwrapped_rec_type := node.receiver_type
|
||||||
if g.fn_decl != 0 && g.fn_decl.generic_names.len > 0 { // in generic fn
|
if unsafe { g.fn_decl != 0 } && g.fn_decl.generic_names.len > 0 { // in generic fn
|
||||||
unwrapped_rec_type = g.unwrap_generic(node.receiver_type)
|
unwrapped_rec_type = g.unwrap_generic(node.receiver_type)
|
||||||
} else { // in non-generic fn
|
} else { // in non-generic fn
|
||||||
sym := g.table.sym(node.receiver_type)
|
sym := g.table.sym(node.receiver_type)
|
||||||
|
|
|
@ -412,7 +412,7 @@ fn (g &JsGen) get_all_test_function_names() []string {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn (mut g JsGen) enter_namespace(name string) {
|
pub fn (mut g JsGen) enter_namespace(name string) {
|
||||||
if g.namespaces[name] == 0 {
|
if unsafe { g.namespaces[name] == 0 } {
|
||||||
// create a new namespace
|
// create a new namespace
|
||||||
ns := &Namespace{
|
ns := &Namespace{
|
||||||
name: name
|
name: name
|
||||||
|
@ -521,7 +521,7 @@ pub fn (mut g JsGen) dec_indent() {
|
||||||
|
|
||||||
[inline]
|
[inline]
|
||||||
pub fn (mut g JsGen) write(s string) {
|
pub fn (mut g JsGen) write(s string) {
|
||||||
if g.ns == 0 {
|
if unsafe { g.ns == 0 } {
|
||||||
verror('g.write: not in a namespace')
|
verror('g.write: not in a namespace')
|
||||||
}
|
}
|
||||||
g.gen_indent()
|
g.gen_indent()
|
||||||
|
@ -530,7 +530,7 @@ pub fn (mut g JsGen) write(s string) {
|
||||||
|
|
||||||
[inline]
|
[inline]
|
||||||
pub fn (mut g JsGen) writeln(s string) {
|
pub fn (mut g JsGen) writeln(s string) {
|
||||||
if g.ns == 0 {
|
if unsafe { g.ns == 0 } {
|
||||||
verror('g.writeln: not in a namespace')
|
verror('g.writeln: not in a namespace')
|
||||||
}
|
}
|
||||||
g.gen_indent()
|
g.gen_indent()
|
||||||
|
@ -2449,7 +2449,8 @@ fn (mut g JsGen) match_expr(node ast.MatchExpr) {
|
||||||
typ := g.table.final_sym(node.cond_type)
|
typ := g.table.final_sym(node.cond_type)
|
||||||
if node.is_sum_type {
|
if node.is_sum_type {
|
||||||
g.match_expr_sumtype(node, is_expr, cond_var, tmp_var)
|
g.match_expr_sumtype(node, is_expr, cond_var, tmp_var)
|
||||||
} else if typ.kind == .enum_ && !g.inside_loop && node.branches.len > 5 && g.fn_decl != 0 { // do not optimize while in top-level
|
} else if typ.kind == .enum_ && !g.inside_loop && node.branches.len > 5
|
||||||
|
&& unsafe { g.fn_decl != 0 } { // do not optimize while in top-level
|
||||||
g.match_expr_switch(node, is_expr, cond_var, tmp_var, typ)
|
g.match_expr_switch(node, is_expr, cond_var, tmp_var, typ)
|
||||||
} else {
|
} else {
|
||||||
g.match_expr_classic(node, is_expr, cond_var, tmp_var)
|
g.match_expr_classic(node, is_expr, cond_var, tmp_var)
|
||||||
|
@ -3691,7 +3692,7 @@ fn (mut g JsGen) unwrap_generic(typ ast.Type) ast.Type {
|
||||||
non-mut to make sure no one else can accidentally mutates the table.
|
non-mut to make sure no one else can accidentally mutates the table.
|
||||||
*/
|
*/
|
||||||
mut muttable := unsafe { &ast.Table(g.table) }
|
mut muttable := unsafe { &ast.Table(g.table) }
|
||||||
if t_typ := muttable.resolve_generic_to_concrete(typ, if g.fn_decl != 0 {
|
if t_typ := muttable.resolve_generic_to_concrete(typ, if unsafe { g.fn_decl != 0 } {
|
||||||
g.fn_decl.generic_names
|
g.fn_decl.generic_names
|
||||||
} else {
|
} else {
|
||||||
[]string{}
|
[]string{}
|
||||||
|
|
|
@ -93,7 +93,7 @@ pub fn (mut m Main) run() ?string {
|
||||||
}
|
}
|
||||||
res += pcdep.description
|
res += pcdep.description
|
||||||
}
|
}
|
||||||
if pc != 0 {
|
if unsafe { pc != 0 } {
|
||||||
pc.extend(pcdep)?
|
pc.extend(pcdep)?
|
||||||
} else {
|
} else {
|
||||||
pc = pcdep
|
pc = pcdep
|
||||||
|
|
|
@ -15,7 +15,7 @@ pub fn list_new<T>() List<T> {
|
||||||
|
|
||||||
pub fn (mut l List<T>) add(value T) {
|
pub fn (mut l List<T>) add(value T) {
|
||||||
mut node := &ListNode<T>{value, 0}
|
mut node := &ListNode<T>{value, 0}
|
||||||
if l.head == 0 {
|
if unsafe { l.head == 0 } {
|
||||||
l.head = node
|
l.head = node
|
||||||
} else {
|
} else {
|
||||||
node.next = l.head
|
node.next = l.head
|
||||||
|
|
|
@ -56,7 +56,7 @@ fn test_struct_pointer_casts_with_field_selectors() {
|
||||||
// &Struct cast and selecting .x
|
// &Struct cast and selecting .x
|
||||||
assert true
|
assert true
|
||||||
}
|
}
|
||||||
if &&Struct(pss) != 0 {
|
if unsafe { &&Struct(pss) != 0 } {
|
||||||
// &&Struct
|
// &&Struct
|
||||||
assert true
|
assert true
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue