Skip to content

Commit 305e4a2

Browse files
fix: address review regressions in interface upcasts and vfmt attrs
1 parent 667d829 commit 305e4a2

6 files changed

Lines changed: 53 additions & 10 deletions

File tree

vlib/v/ast/attr.v

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,14 +28,15 @@ pub:
2828
// original call-style metadata for `@[foo(...)]`, used by vfmt
2929
call_name string
3030
call_arg_name string
31+
call_arg_idx int = -1
3132
pub mut:
3233
ct_expr Expr // .kind == comptime_define, for [if !name]
3334
ct_evaled bool // whether ct_skip has been evaluated already
3435
ct_skip bool // is the comptime expr *false*, filled by checker
3536
}
3637

3738
pub fn (a &Attr) debug() string {
38-
return 'Attr{ name: "${a.name}", has_arg: ${a.has_arg}, arg: "${a.arg}", kind: ${a.kind}, ct_expr: ${a.ct_expr}, ct_opt: ${a.ct_opt}, ct_skip: ${a.ct_skip}, call_name: "${a.call_name}", call_arg_name: "${a.call_arg_name}" }'
39+
return 'Attr{ name: "${a.name}", has_arg: ${a.has_arg}, arg: "${a.arg}", kind: ${a.kind}, ct_expr: ${a.ct_expr}, ct_opt: ${a.ct_opt}, ct_skip: ${a.ct_skip}, call_name: "${a.call_name}", call_arg_name: "${a.call_arg_name}", call_arg_idx: ${a.call_arg_idx} }'
3940
}
4041

4142
// str returns the string representation without square brackets

vlib/v/checker/checker.v

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6201,7 +6201,17 @@ fn (mut c Checker) fail_if_unreadable(expr ast.Expr, typ ast.Type, what string)
62016201
}
62026202

62036203
fn (mut c Checker) interface_embeds_interface(interface_type ast.Type, embedded_interface_type ast.Type) bool {
6204+
mut visited := map[int]bool{}
6205+
return c.interface_embeds_interface_recursive(interface_type, embedded_interface_type, mut
6206+
visited)
6207+
}
6208+
6209+
fn (mut c Checker) interface_embeds_interface_recursive(interface_type ast.Type, embedded_interface_type ast.Type, mut visited map[int]bool) bool {
62046210
u_interface_type := c.unwrap_generic(interface_type)
6211+
if visited[u_interface_type.idx()] {
6212+
return false
6213+
}
6214+
visited[u_interface_type.idx()] = true
62056215
embedded_idx := c.unwrap_generic(embedded_interface_type).idx()
62066216
final_embedded_idx := c.table.final_sym(embedded_interface_type).idx
62076217
if iface_decl := c.table.interfaces[u_interface_type] {
@@ -6211,6 +6221,11 @@ fn (mut c Checker) interface_embeds_interface(interface_type ast.Type, embedded_
62116221
|| c.table.final_sym(embed_typ).idx == final_embedded_idx {
62126222
return true
62136223
}
6224+
if c.interface_embeds_interface_recursive(embed_typ, embedded_interface_type, mut
6225+
visited)
6226+
{
6227+
return true
6228+
}
62146229
}
62156230
}
62166231
return false

vlib/v/fmt/attrs.v

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -141,8 +141,10 @@ fn attr_call_group_str(attrs []ast.Attr) string {
141141
if attrs.len == 0 {
142142
return ''
143143
}
144+
mut ordered_attrs := attrs.clone()
145+
ordered_attrs.sort(a.call_arg_idx < b.call_arg_idx)
144146
mut args := []string{}
145-
for attr in attrs {
147+
for attr in ordered_attrs {
146148
if !attr.has_arg {
147149
continue
148150
}

vlib/v/fmt/tests/attribute_call_syntax_keep.vv

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,12 @@ fn old_positional() {}
77
@[deprecated(msg: 'use new_fn instead', after: '2999-10-10')]
88
fn old_named() {}
99

10+
@[foo(bar: 'x', 123)]
11+
fn mixed_named_positional() {}
12+
13+
@[foo(123, bar: 'x')]
14+
fn mixed_positional_named() {}
15+
1016
struct Config {
1117
flag bool @[custom(flag: true, count: 2)]
1218
value string @[xml(name: 'cfg'); raw]

vlib/v/parser/attribute.v

Lines changed: 17 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -43,10 +43,12 @@ fn (mut p Parser) parse_attr_call(name string, is_at bool, apos token.Pos) []ast
4343
mut base_arg := ''
4444
mut base_quote := u8(`'`)
4545
mut base_arg_name := ''
46+
mut base_call_arg_idx := -1
4647
mut base_has_arg := false
4748
mut attrs := []ast.Attr{}
4849
mut has_base_arg := false
4950
mut positional_arg_idx := 1
51+
mut call_arg_idx := 0
5052
for p.tok.kind !in [.rpar, .eof] {
5153
mut is_named := false
5254
mut arg_name := ''
@@ -68,6 +70,7 @@ fn (mut p Parser) parse_attr_call(name string, is_at bool, apos token.Pos) []ast
6870
base_kind = kind
6971
base_quote = quote
7072
base_arg_name = arg_name
73+
base_call_arg_idx = call_arg_idx
7174
has_base_arg = true
7275
} else {
7376
attrs << ast.Attr{
@@ -80,27 +83,32 @@ fn (mut p Parser) parse_attr_call(name string, is_at bool, apos token.Pos) []ast
8083
has_at: is_at
8184
call_name: name
8285
call_arg_name: arg_name
86+
call_arg_idx: call_arg_idx
8387
}
8488
}
8589
} else if !has_base_arg {
8690
base_has_arg = true
8791
base_arg = arg
8892
base_kind = kind
8993
base_quote = quote
94+
base_arg_name = arg_name
95+
base_call_arg_idx = call_arg_idx
9096
has_base_arg = true
9197
} else {
9298
attrs << ast.Attr{
93-
name: '${name}_${positional_arg_idx}'
94-
has_arg: true
95-
arg: arg
96-
kind: kind
97-
quote: quote
98-
pos: apos.extend(p.prev_tok.pos())
99-
has_at: is_at
100-
call_name: name
99+
name: '${name}_${positional_arg_idx}'
100+
has_arg: true
101+
arg: arg
102+
kind: kind
103+
quote: quote
104+
pos: apos.extend(p.prev_tok.pos())
105+
has_at: is_at
106+
call_name: name
107+
call_arg_idx: call_arg_idx
101108
}
102109
positional_arg_idx++
103110
}
111+
call_arg_idx++
104112
if p.tok.kind == .comma {
105113
p.next()
106114
continue
@@ -118,6 +126,7 @@ fn (mut p Parser) parse_attr_call(name string, is_at bool, apos token.Pos) []ast
118126
has_at: is_at
119127
call_name: name
120128
call_arg_name: base_arg_name
129+
call_arg_idx: base_call_arg_idx
121130
}
122131
attrs.insert(0, base_attr)
123132
return attrs

vlib/v/tests/interfaces/interface_embedding_implicit_upcast_test.v

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,10 @@ interface Solid {
55
Base
66
}
77

8+
interface Dense {
9+
Solid
10+
}
11+
812
struct Empty {
913
}
1014

@@ -20,4 +24,10 @@ fn test_interface_embedding_implicit_upcast() {
2024
base = solid
2125
assert base is Empty
2226
assert (solid as Base) is Empty
27+
28+
dense := Dense(Empty{})
29+
assert greet(dense)
30+
base = dense
31+
assert base is Empty
32+
assert (dense as Base) is Empty
2333
}

0 commit comments

Comments
 (0)