checker: check generic struct init without type parameter (#13404)
parent
356ccf247f
commit
4be3c92640
|
@ -46,7 +46,7 @@ pub fn (list DoublyLinkedList<T>) last() ?T {
|
||||||
|
|
||||||
// push_back adds an element to the end of the linked list
|
// push_back adds an element to the end of the linked list
|
||||||
pub fn (mut list DoublyLinkedList<T>) push_back(item T) {
|
pub fn (mut list DoublyLinkedList<T>) push_back(item T) {
|
||||||
mut new_node := &DoublyListNode{
|
mut new_node := &DoublyListNode<T>{
|
||||||
data: item
|
data: item
|
||||||
}
|
}
|
||||||
if list.is_empty() {
|
if list.is_empty() {
|
||||||
|
@ -63,7 +63,7 @@ pub fn (mut list DoublyLinkedList<T>) push_back(item T) {
|
||||||
|
|
||||||
// push_front adds an element to the beginning of the linked list
|
// push_front adds an element to the beginning of the linked list
|
||||||
pub fn (mut list DoublyLinkedList<T>) push_front(item T) {
|
pub fn (mut list DoublyLinkedList<T>) push_front(item T) {
|
||||||
mut new_node := &DoublyListNode{
|
mut new_node := &DoublyListNode<T>{
|
||||||
data: item
|
data: item
|
||||||
}
|
}
|
||||||
if list.is_empty() {
|
if list.is_empty() {
|
||||||
|
@ -149,7 +149,7 @@ fn (mut list DoublyLinkedList<T>) insert_back(idx int, item T) {
|
||||||
// |next|---->|next|
|
// |next|---->|next|
|
||||||
// |prev|<----|prev|
|
// |prev|<----|prev|
|
||||||
// ------ ------
|
// ------ ------
|
||||||
new := &DoublyListNode{
|
new := &DoublyListNode<T>{
|
||||||
data: item
|
data: item
|
||||||
next: node
|
next: node
|
||||||
prev: prev
|
prev: prev
|
||||||
|
@ -176,7 +176,7 @@ fn (mut list DoublyLinkedList<T>) insert_front(idx int, item T) {
|
||||||
// |next|---->|next|
|
// |next|---->|next|
|
||||||
// |prev|<----|prev|
|
// |prev|<----|prev|
|
||||||
// ------ ------
|
// ------ ------
|
||||||
new := &DoublyListNode{
|
new := &DoublyListNode<T>{
|
||||||
data: item
|
data: item
|
||||||
next: next
|
next: next
|
||||||
prev: node
|
prev: node
|
||||||
|
|
|
@ -61,7 +61,7 @@ pub fn (list LinkedList<T>) index(idx int) ?T {
|
||||||
|
|
||||||
// push adds an element to the end of the linked list
|
// push adds an element to the end of the linked list
|
||||||
pub fn (mut list LinkedList<T>) push(item T) {
|
pub fn (mut list LinkedList<T>) push(item T) {
|
||||||
new_node := &ListNode{
|
new_node := &ListNode<T>{
|
||||||
data: item
|
data: item
|
||||||
}
|
}
|
||||||
if list.head == 0 {
|
if list.head == 0 {
|
||||||
|
@ -124,7 +124,7 @@ pub fn (mut list LinkedList<T>) insert(idx int, item T) ? {
|
||||||
|
|
||||||
if idx == 0 {
|
if idx == 0 {
|
||||||
// first node case
|
// first node case
|
||||||
list.head = &ListNode{
|
list.head = &ListNode<T>{
|
||||||
data: item
|
data: item
|
||||||
next: node
|
next: node
|
||||||
}
|
}
|
||||||
|
@ -132,7 +132,7 @@ pub fn (mut list LinkedList<T>) insert(idx int, item T) ? {
|
||||||
for i := 0; i < idx - 1; i++ {
|
for i := 0; i < idx - 1; i++ {
|
||||||
node = node.next
|
node = node.next
|
||||||
}
|
}
|
||||||
node.next = &ListNode{
|
node.next = &ListNode<T>{
|
||||||
data: item
|
data: item
|
||||||
next: node.next
|
next: node.next
|
||||||
}
|
}
|
||||||
|
|
|
@ -397,9 +397,10 @@ pub mut:
|
||||||
|
|
||||||
pub struct StructInit {
|
pub struct StructInit {
|
||||||
pub:
|
pub:
|
||||||
pos token.Pos
|
pos token.Pos
|
||||||
name_pos token.Pos
|
name_pos token.Pos
|
||||||
is_short bool
|
is_short bool
|
||||||
|
is_short_syntax bool
|
||||||
pub mut:
|
pub mut:
|
||||||
unresolved bool
|
unresolved bool
|
||||||
pre_comments []Comment
|
pre_comments []Comment
|
||||||
|
|
|
@ -131,9 +131,14 @@ pub fn (mut c Checker) struct_init(mut node ast.StructInit) ast.Type {
|
||||||
struct_sym := c.table.sym(node.typ)
|
struct_sym := c.table.sym(node.typ)
|
||||||
if struct_sym.info is ast.Struct {
|
if struct_sym.info is ast.Struct {
|
||||||
if struct_sym.info.generic_types.len > 0 && struct_sym.info.concrete_types.len == 0
|
if struct_sym.info.generic_types.len > 0 && struct_sym.info.concrete_types.len == 0
|
||||||
&& c.table.cur_concrete_types.len == 0 {
|
&& !node.is_short_syntax {
|
||||||
c.error('generic struct init must specify type parameter, e.g. Foo<int>',
|
if c.table.cur_concrete_types.len == 0 {
|
||||||
node.pos)
|
c.error('generic struct init must specify type parameter, e.g. Foo<int>',
|
||||||
|
node.pos)
|
||||||
|
} else if node.generic_types.len == 0 {
|
||||||
|
c.error('generic struct init must specify type parameter, e.g. Foo<T>',
|
||||||
|
node.pos)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if node.generic_types.len > 0 && struct_sym.info.generic_types != node.generic_types {
|
if node.generic_types.len > 0 && struct_sym.info.generic_types != node.generic_types {
|
||||||
c.table.replace_generic_type(node.typ, node.generic_types)
|
c.table.replace_generic_type(node.typ, node.generic_types)
|
||||||
|
|
|
@ -12,10 +12,4 @@ vlib/v/checker/tests/generic_fn_decl_without_generic_names_err.vv:32:1: error: g
|
||||||
| ~~~~~~~~~~~~~~
|
| ~~~~~~~~~~~~~~
|
||||||
33 | println("hi")
|
33 | println("hi")
|
||||||
34 | }
|
34 | }
|
||||||
vlib/v/checker/tests/generic_fn_decl_without_generic_names_err.vv:23:9: error: cannot use `Generic` as type `Generic<Concrete>` in return argument
|
|
||||||
21 | go g_worker(g)
|
|
||||||
22 |
|
|
||||||
23 | return g
|
|
||||||
| ^
|
|
||||||
24 | }
|
|
||||||
25 |
|
|
||||||
|
|
|
@ -14,7 +14,7 @@ fn main() {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn create_generic_t<T>() Generic<T> {
|
fn create_generic_t<T>() Generic<T> {
|
||||||
g := Generic{
|
g := Generic<T>{
|
||||||
ch: chan T{}
|
ch: chan T{}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -5,3 +5,10 @@ vlib/v/checker/tests/generics_fn_return_generic_struct_err.vv:13:32: error: retu
|
||||||
| ~~~~~~~~~~~~~~~~~~~~
|
| ~~~~~~~~~~~~~~~~~~~~
|
||||||
14 | d := GenericChannelStruct{
|
14 | d := GenericChannelStruct{
|
||||||
15 | ch: chan T{}
|
15 | ch: chan T{}
|
||||||
|
vlib/v/checker/tests/generics_fn_return_generic_struct_err.vv:14:7: error: generic struct init must specify type parameter, e.g. Foo<T>
|
||||||
|
12 |
|
||||||
|
13 | pub fn new_channel_struct<T>() GenericChannelStruct {
|
||||||
|
14 | d := GenericChannelStruct{
|
||||||
|
| ~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
15 | ch: chan T{}
|
||||||
|
16 | }
|
||||||
|
|
|
@ -12,3 +12,45 @@ vlib/v/checker/tests/generics_struct_init_err.vv:67:8: error: generic struct ini
|
||||||
| ~~~~~~~~~~~~~~
|
| ~~~~~~~~~~~~~~
|
||||||
68 | assert ret == -6
|
68 | assert ret == -6
|
||||||
69 | }
|
69 | }
|
||||||
|
vlib/v/checker/tests/generics_struct_init_err.vv:22:7: error: generic struct init must specify type parameter, e.g. Foo<T>
|
||||||
|
20 |
|
||||||
|
21 | fn holder_call_1<T>(func T, a int) int {
|
||||||
|
22 | h := FnHolder1{func}
|
||||||
|
| ~~~~~~~~~~~~~~~
|
||||||
|
23 | return h.call(a)
|
||||||
|
24 | }
|
||||||
|
vlib/v/checker/tests/generics_struct_init_err.vv:27:7: error: generic struct init must specify type parameter, e.g. Foo<T>
|
||||||
|
25 |
|
||||||
|
26 | fn holder_call_2<T>(func T, a int) int {
|
||||||
|
27 | h := FnHolder2{func}
|
||||||
|
| ~~~~~~~~~~~~~~~
|
||||||
|
28 | return h.call(a)
|
||||||
|
29 | }
|
||||||
|
vlib/v/checker/tests/generics_struct_init_err.vv:33:7: error: generic struct init must specify type parameter, e.g. Foo<T>
|
||||||
|
31 | fn holder_call_11<T>(func T, a int) int {
|
||||||
|
32 | f := func
|
||||||
|
33 | h := FnHolder1{f}
|
||||||
|
| ~~~~~~~~~~~~
|
||||||
|
34 | return h.call(a)
|
||||||
|
35 | }
|
||||||
|
vlib/v/checker/tests/generics_struct_init_err.vv:39:7: error: generic struct init must specify type parameter, e.g. Foo<T>
|
||||||
|
37 | fn holder_call_21<T>(func T, a int) int {
|
||||||
|
38 | f := func
|
||||||
|
39 | h := FnHolder2{f}
|
||||||
|
| ~~~~~~~~~~~~
|
||||||
|
40 | return h.call(a)
|
||||||
|
41 | }
|
||||||
|
vlib/v/checker/tests/generics_struct_init_err.vv:44:9: error: generic struct init must specify type parameter, e.g. Foo<T>
|
||||||
|
42 |
|
||||||
|
43 | fn holder_call_12<T>(func T, a int) int {
|
||||||
|
44 | return FnHolder1{func}.call(a)
|
||||||
|
| ~~~~~~~~~~~~~~~
|
||||||
|
45 | }
|
||||||
|
46 |
|
||||||
|
vlib/v/checker/tests/generics_struct_init_err.vv:48:9: error: generic struct init must specify type parameter, e.g. Foo<T>
|
||||||
|
46 |
|
||||||
|
47 | fn holder_call_22<T>(func T, a int) int {
|
||||||
|
48 | return FnHolder2{func}.call(a)
|
||||||
|
| ~~~~~~~~~~~~~~~
|
||||||
|
49 | }
|
||||||
|
50 |
|
||||||
|
|
|
@ -426,6 +426,7 @@ fn (mut p Parser) struct_init(typ_str string, short_syntax bool) ast.StructInit
|
||||||
name_pos: first_pos
|
name_pos: first_pos
|
||||||
pos: first_pos.extend(if short_syntax { p.tok.pos() } else { p.prev_tok.pos() })
|
pos: first_pos.extend(if short_syntax { p.tok.pos() } else { p.prev_tok.pos() })
|
||||||
is_short: no_keys
|
is_short: no_keys
|
||||||
|
is_short_syntax: short_syntax
|
||||||
pre_comments: pre_comments
|
pre_comments: pre_comments
|
||||||
generic_types: p.struct_init_generic_types
|
generic_types: p.struct_init_generic_types
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,33 +19,33 @@ fn (self FnHolder2<T>) call(a int) int {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn holder_call_1<T>(func T, a int) int {
|
fn holder_call_1<T>(func T, a int) int {
|
||||||
h := FnHolder1{func}
|
h := FnHolder1<T>{func}
|
||||||
return h.call(a)
|
return h.call(a)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn holder_call_2<T>(func T, a int) int {
|
fn holder_call_2<T>(func T, a int) int {
|
||||||
h := FnHolder2{func}
|
h := FnHolder2<T>{func}
|
||||||
return h.call(a)
|
return h.call(a)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn holder_call_11<T>(func T, a int) int {
|
fn holder_call_11<T>(func T, a int) int {
|
||||||
f := func
|
f := func
|
||||||
h := FnHolder1{f}
|
h := FnHolder1<T>{f}
|
||||||
return h.call(a)
|
return h.call(a)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn holder_call_21<T>(func T, a int) int {
|
fn holder_call_21<T>(func T, a int) int {
|
||||||
f := func
|
f := func
|
||||||
h := FnHolder2{f}
|
h := FnHolder2<T>{f}
|
||||||
return h.call(a)
|
return h.call(a)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn holder_call_12<T>(func T, a int) int {
|
fn holder_call_12<T>(func T, a int) int {
|
||||||
return FnHolder1{func}.call(a)
|
return FnHolder1<T>{func}.call(a)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn holder_call_22<T>(func T, a int) int {
|
fn holder_call_22<T>(func T, a int) int {
|
||||||
return FnHolder2{func}.call(a)
|
return FnHolder2<T>{func}.call(a)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn test_generic_struct_with_anon_fn_parameter() {
|
fn test_generic_struct_with_anon_fn_parameter() {
|
||||||
|
|
Loading…
Reference in New Issue