checker: do not allow direct initialization of builtin types (s := string{})
parent
f648e3f10d
commit
2f1810634e
|
@ -24,7 +24,7 @@ pub fn decode(data string) []byte {
|
||||||
unsafe {
|
unsafe {
|
||||||
buffer := malloc(size)
|
buffer := malloc(size)
|
||||||
n := decode_in_buffer(data, buffer)
|
n := decode_in_buffer(data, buffer)
|
||||||
return array{element_size: 1, data: buffer, len: n, cap: size}
|
return buffer.vbytes(n)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -70,7 +70,8 @@ fn alloc_and_encode(src byteptr, len int) string {
|
||||||
// the a base64 url encoded `string` passed in `data`.
|
// the a base64 url encoded `string` passed in `data`.
|
||||||
pub fn url_decode(data string) []byte {
|
pub fn url_decode(data string) []byte {
|
||||||
mut result := data.replace_each(['-', '+', '_', '/'])
|
mut result := data.replace_each(['-', '+', '_', '/'])
|
||||||
match result.len % 4 { // Pad with trailing '='s
|
match result.len % 4 {
|
||||||
|
// Pad with trailing '='s
|
||||||
2 { result += '==' } // 2 pad chars
|
2 { result += '==' } // 2 pad chars
|
||||||
3 { result += '=' } // 1 pad char
|
3 { result += '=' } // 1 pad char
|
||||||
else {} // no padding
|
else {} // no padding
|
||||||
|
@ -81,7 +82,8 @@ pub fn url_decode(data string) []byte {
|
||||||
// url_decode_str is the string variant of url_decode
|
// url_decode_str is the string variant of url_decode
|
||||||
pub fn url_decode_str(data string) string {
|
pub fn url_decode_str(data string) string {
|
||||||
mut result := data.replace_each(['-', '+', '_', '/'])
|
mut result := data.replace_each(['-', '+', '_', '/'])
|
||||||
match result.len % 4 { // Pad with trailing '='s
|
match result.len % 4 {
|
||||||
|
// Pad with trailing '='s
|
||||||
2 { result += '==' } // 2 pad chars
|
2 { result += '==' } // 2 pad chars
|
||||||
3 { result += '=' } // 1 pad char
|
3 { result += '=' } // 1 pad char
|
||||||
else {} // no padding
|
else {} // no padding
|
||||||
|
@ -132,19 +134,19 @@ pub fn decode_in_buffer(data &string, buffer byteptr) int {
|
||||||
mut char_c := 0
|
mut char_c := 0
|
||||||
mut char_d := 0
|
mut char_d := 0
|
||||||
if i < input_length {
|
if i < input_length {
|
||||||
char_a = index[unsafe { d[i] }]
|
char_a = base64.index[unsafe { d[i] }]
|
||||||
i++
|
i++
|
||||||
}
|
}
|
||||||
if i < input_length {
|
if i < input_length {
|
||||||
char_b = index[unsafe { d[i] }]
|
char_b = base64.index[unsafe { d[i] }]
|
||||||
i++
|
i++
|
||||||
}
|
}
|
||||||
if i < input_length {
|
if i < input_length {
|
||||||
char_c = index[unsafe { d[i] }]
|
char_c = base64.index[unsafe { d[i] }]
|
||||||
i++
|
i++
|
||||||
}
|
}
|
||||||
if i < input_length {
|
if i < input_length {
|
||||||
char_d = index[unsafe { d[i] }]
|
char_d = base64.index[unsafe { d[i] }]
|
||||||
i++
|
i++
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -180,7 +182,7 @@ fn encode_from_buffer(dest byteptr, src byteptr, src_len int) int {
|
||||||
|
|
||||||
mut d := src
|
mut d := src
|
||||||
mut b := dest
|
mut b := dest
|
||||||
mut etable := byteptr(enc_table.str)
|
mut etable := byteptr(base64.enc_table.str)
|
||||||
for i < input_length {
|
for i < input_length {
|
||||||
mut octet_a := 0
|
mut octet_a := 0
|
||||||
mut octet_b := 0
|
mut octet_b := 0
|
||||||
|
@ -210,7 +212,7 @@ fn encode_from_buffer(dest byteptr, src byteptr, src_len int) int {
|
||||||
j += 4
|
j += 4
|
||||||
}
|
}
|
||||||
|
|
||||||
padding_length := ending_table[input_length % 3]
|
padding_length := base64.ending_table[input_length % 3]
|
||||||
for i = 0; i < padding_length; i++ {
|
for i = 0; i < padding_length; i++ {
|
||||||
unsafe {
|
unsafe {
|
||||||
b[output_length - 1 - i] = `=`
|
b[output_length - 1 - i] = `=`
|
||||||
|
|
|
@ -483,7 +483,7 @@ pub fn read_file_array<T>(path string) []T {
|
||||||
a := T{}
|
a := T{}
|
||||||
tsize := int(sizeof(a))
|
tsize := int(sizeof(a))
|
||||||
// prepare for reading, get current file size
|
// prepare for reading, get current file size
|
||||||
mut fp := vfopen(path, 'rb') or { return array{} }
|
mut fp := vfopen(path, 'rb') or { return []T{} }
|
||||||
C.fseek(fp, 0, C.SEEK_END)
|
C.fseek(fp, 0, C.SEEK_END)
|
||||||
fsize := C.ftell(fp)
|
fsize := C.ftell(fp)
|
||||||
C.rewind(fp)
|
C.rewind(fp)
|
||||||
|
@ -492,13 +492,15 @@ pub fn read_file_array<T>(path string) []T {
|
||||||
buf := unsafe { malloc(fsize) }
|
buf := unsafe { malloc(fsize) }
|
||||||
C.fread(buf, fsize, 1, fp)
|
C.fread(buf, fsize, 1, fp)
|
||||||
C.fclose(fp)
|
C.fclose(fp)
|
||||||
return array{
|
return unsafe {
|
||||||
|
array{
|
||||||
element_size: tsize
|
element_size: tsize
|
||||||
data: buf
|
data: buf
|
||||||
len: len
|
len: len
|
||||||
cap: len
|
cap: len
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub fn on_segfault(f voidptr) {
|
pub fn on_segfault(f voidptr) {
|
||||||
$if windows {
|
$if windows {
|
||||||
|
|
|
@ -1248,7 +1248,6 @@ pub fn (expr Expr) is_blank_ident() bool {
|
||||||
pub fn (expr Expr) position() token.Position {
|
pub fn (expr Expr) position() token.Position {
|
||||||
// all uncommented have to be implemented
|
// all uncommented have to be implemented
|
||||||
match expr {
|
match expr {
|
||||||
// KEKW2
|
|
||||||
AnonFn {
|
AnonFn {
|
||||||
return expr.decl.pos
|
return expr.decl.pos
|
||||||
}
|
}
|
||||||
|
|
|
@ -463,6 +463,16 @@ pub fn (mut c Checker) struct_init(mut struct_init ast.StructInit) table.Type {
|
||||||
utyp := c.unwrap_generic(struct_init.typ)
|
utyp := c.unwrap_generic(struct_init.typ)
|
||||||
c.ensure_type_exists(utyp, struct_init.pos) or {}
|
c.ensure_type_exists(utyp, struct_init.pos) or {}
|
||||||
type_sym := c.table.get_type_symbol(utyp)
|
type_sym := c.table.get_type_symbol(utyp)
|
||||||
|
// Make sure the first letter is capital, do not allow e.g. `x := string{}`,
|
||||||
|
// but `x := T{}` is ok.
|
||||||
|
if !c.is_builtin_mod && !c.inside_unsafe && type_sym.language == .v
|
||||||
|
&& c.cur_generic_types.len == 0 {
|
||||||
|
pos := type_sym.name.last_index('.') or { -1 }
|
||||||
|
first_letter := type_sym.name[pos + 1]
|
||||||
|
if !first_letter.is_capital() {
|
||||||
|
c.error('cannot initialize builtin type `$type_sym.name`', struct_init.pos)
|
||||||
|
}
|
||||||
|
}
|
||||||
if type_sym.kind == .sum_type && struct_init.fields.len == 1 {
|
if type_sym.kind == .sum_type && struct_init.fields.len == 1 {
|
||||||
sexpr := struct_init.fields[0].expr.str()
|
sexpr := struct_init.fields[0].expr.str()
|
||||||
c.error('cast to sum type using `${type_sym.name}($sexpr)` not `$type_sym.name{$sexpr}`',
|
c.error('cast to sum type using `${type_sym.name}($sexpr)` not `$type_sym.name{$sexpr}`',
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
vlib/v/checker/tests/check_generic_int_init.vv:2:9: error: type `int` is private
|
vlib/v/checker/tests/check_generic_int_init.vv:2:9: error: cannot initialize builtin type `int`
|
||||||
1 | fn test<T>() T {
|
1 | fn test<T>() T {
|
||||||
2 | return T{}
|
2 | return T{}
|
||||||
| ~~~
|
| ~~~
|
||||||
|
|
|
@ -31,7 +31,7 @@ fn test_ct_expressions() {
|
||||||
|
|
||||||
fn generic_t_is<O>() O {
|
fn generic_t_is<O>() O {
|
||||||
$if O is string {
|
$if O is string {
|
||||||
return 'It\'s a string!'
|
return "It's a string!"
|
||||||
} $else {
|
} $else {
|
||||||
return O{}
|
return O{}
|
||||||
}
|
}
|
||||||
|
@ -41,13 +41,13 @@ fn generic_t_is<O>() O {
|
||||||
struct GenericTIsTest {}
|
struct GenericTIsTest {}
|
||||||
|
|
||||||
fn test_generic_t_is() {
|
fn test_generic_t_is() {
|
||||||
assert generic_t_is<string>() == 'It\'s a string!'
|
assert generic_t_is<string>() == "It's a string!"
|
||||||
assert generic_t_is<GenericTIsTest>() == GenericTIsTest{}
|
assert generic_t_is<GenericTIsTest>() == GenericTIsTest{}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn generic_t_is2<T>() ?T {
|
fn generic_t_is2<T>() ?T {
|
||||||
$if T is string {
|
$if T is string {
|
||||||
return 'It\'s a string!'
|
return "It's a string!"
|
||||||
} $else {
|
} $else {
|
||||||
return T{}
|
return T{}
|
||||||
}
|
}
|
||||||
|
@ -62,7 +62,7 @@ fn test_generic_t_is2() {
|
||||||
assert false
|
assert false
|
||||||
GenericTIsTest{}
|
GenericTIsTest{}
|
||||||
}
|
}
|
||||||
assert res == 'It\'s a string!'
|
assert res == "It's a string!"
|
||||||
assert res2 == GenericTIsTest{}
|
assert res2 == GenericTIsTest{}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -123,4 +123,3 @@ fn test_generic_t_is_with_else_if() {
|
||||||
x := generic_t_is_with_else_if<User>()
|
x := generic_t_is_with_else_if<User>()
|
||||||
assert x == ['name', 'age']
|
assert x == ['name', 'age']
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue