Fix v/parser: Failure to parse structs with fields typed as anonymous functions returning having an optional void (`?`) return type. (#5684)
* Handle optional void return type in function types in struct fields. * Add more testing for optional return types in struct fields. * Move language parsing into it's own function * Fix issue caused by not setting typ. * Fix test for structs containing anon fn with optional void return typespull/5687/head
parent
f6ab63f3a0
commit
8d035a446a
|
@ -98,25 +98,8 @@ pub fn (mut p Parser) parse_type_with_mut(is_mut bool) table.Type {
|
||||||
return typ
|
return typ
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn (mut p Parser) parse_type() table.Type {
|
// Parses any language indicators on a type.
|
||||||
// optional
|
pub fn (mut p Parser) parse_language() table.Language {
|
||||||
mut is_optional := false
|
|
||||||
if p.tok.kind == .question {
|
|
||||||
p.next()
|
|
||||||
is_optional = true
|
|
||||||
}
|
|
||||||
is_shared := p.tok.kind in [.key_shared, .key_rwshared]
|
|
||||||
is_atomic_or_rw := p.tok.kind in [.key_rwshared, .key_atomic]
|
|
||||||
mut nr_muls := 0
|
|
||||||
if p.tok.kind == .key_mut || is_shared || is_atomic_or_rw {
|
|
||||||
nr_muls++
|
|
||||||
p.next()
|
|
||||||
}
|
|
||||||
// &Type
|
|
||||||
for p.tok.kind == .amp {
|
|
||||||
nr_muls++
|
|
||||||
p.next()
|
|
||||||
}
|
|
||||||
|
|
||||||
language := if p.tok.lit == 'C' {
|
language := if p.tok.lit == 'C' {
|
||||||
table.Language.c
|
table.Language.c
|
||||||
|
@ -130,6 +113,40 @@ pub fn (mut p Parser) parse_type() table.Type {
|
||||||
p.next()
|
p.next()
|
||||||
p.check(.dot)
|
p.check(.dot)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return language
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn (mut p Parser) parse_type() table.Type {
|
||||||
|
// optional
|
||||||
|
mut is_optional := false
|
||||||
|
if p.tok.kind == .question {
|
||||||
|
line_nr := p.tok.line_nr
|
||||||
|
p.next()
|
||||||
|
is_optional = true
|
||||||
|
|
||||||
|
if p.tok.line_nr > line_nr {
|
||||||
|
mut typ := table.void_type
|
||||||
|
if is_optional {
|
||||||
|
typ = typ.set_flag(.optional)
|
||||||
|
}
|
||||||
|
return typ
|
||||||
|
}
|
||||||
|
}
|
||||||
|
is_shared := p.tok.kind in [.key_shared, .key_rwshared]
|
||||||
|
is_atomic_or_rw := p.tok.kind in [.key_rwshared, .key_atomic]
|
||||||
|
|
||||||
|
mut nr_muls := 0
|
||||||
|
if p.tok.kind == .key_mut || is_shared || is_atomic_or_rw {
|
||||||
|
nr_muls++
|
||||||
|
p.next()
|
||||||
|
}
|
||||||
|
// &Type
|
||||||
|
for p.tok.kind == .amp {
|
||||||
|
nr_muls++
|
||||||
|
p.next()
|
||||||
|
}
|
||||||
|
language := p.parse_language()
|
||||||
mut typ := table.void_type
|
mut typ := table.void_type
|
||||||
if p.tok.kind != .lcbr {
|
if p.tok.kind != .lcbr {
|
||||||
pos := p.tok.position()
|
pos := p.tok.position()
|
||||||
|
|
|
@ -279,3 +279,40 @@ fn test_optional_val_with_empty_or() {
|
||||||
ret_none() or {}
|
ret_none() or {}
|
||||||
assert true
|
assert true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn test_optional_void_return_types_of_anon_fn() {
|
||||||
|
f := fn(i int) ? {
|
||||||
|
if i == 0 {
|
||||||
|
return error("0")
|
||||||
|
}
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
f(0) or {
|
||||||
|
assert err == "0"
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct Foo {
|
||||||
|
f fn(int) ?
|
||||||
|
}
|
||||||
|
|
||||||
|
fn test_option_void_return_types_of_anon_fn_in_struct() {
|
||||||
|
foo := Foo {
|
||||||
|
f: fn(i int) ? {
|
||||||
|
if i == 0 {
|
||||||
|
return error("0")
|
||||||
|
}
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
foo.f(0) or {
|
||||||
|
assert err == "0"
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
|
@ -313,3 +313,28 @@ fn test_struct_with_default_values_no_init() {
|
||||||
assert s2.field_optional == 3
|
assert s2.field_optional == 3
|
||||||
assert s3.field_optional == 2
|
assert s3.field_optional == 2
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct FieldsWithOptionalVoidReturnType {
|
||||||
|
f fn() ?
|
||||||
|
g fn() ?
|
||||||
|
}
|
||||||
|
|
||||||
|
fn test_fields_anon_fn_with_optional_void_return_type() {
|
||||||
|
foo := FieldsWithOptionalVoidReturnType {
|
||||||
|
f: fn() ? {
|
||||||
|
return error("oops")
|
||||||
|
}
|
||||||
|
g: fn() ? {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
foo.f() or {
|
||||||
|
assert err == "oops"
|
||||||
|
}
|
||||||
|
|
||||||
|
foo.g() or {
|
||||||
|
assert false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue