Skip to content

Commit f510dc8

Browse files
authored
parser: remove the support for the obsolete generic fn call syntax f<T>() (first deprecated in 2022/11) (#26126)
1 parent c45c023 commit f510dc8

1 file changed

Lines changed: 36 additions & 49 deletions

File tree

‎vlib/v/parser/checks.v‎

Lines changed: 36 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -82,7 +82,7 @@ fn (p &Parser) is_array_type() bool {
8282
}
8383

8484
fn (mut p Parser) is_following_concrete_types() bool {
85-
if !(p.tok.kind in [.lt, .lsbr] && p.tok.is_next_to(p.prev_tok)) {
85+
if !(p.tok.kind == .lsbr && p.tok.is_next_to(p.prev_tok)) {
8686
return false
8787
}
8888
mut i := 1
@@ -113,34 +113,30 @@ fn (mut p Parser) is_following_concrete_types() bool {
113113
@[direct_array_access]
114114
fn (p &Parser) is_generic_struct_init() bool {
115115
lit0_is_capital := p.tok.kind != .eof && p.tok.lit.len > 0 && p.tok.lit[0].is_capital()
116-
if !lit0_is_capital || p.peek_tok.kind !in [.lt, .lsbr] {
116+
if !lit0_is_capital || p.peek_tok.kind != .lsbr {
117117
return false
118118
}
119-
if p.peek_tok.kind == .lt {
120-
return true
121-
} else {
122-
mut i := 2
123-
mut nested_sbr_count := 0
124-
for {
125-
cur_tok := p.peek_token(i)
126-
if cur_tok.kind == .eof
127-
|| cur_tok.kind !in [.amp, .dot, .comma, .name, .lpar, .rpar, .lsbr, .rsbr, .key_fn] {
128-
break
129-
}
130-
if cur_tok.kind == .lsbr {
131-
nested_sbr_count++
132-
} else if cur_tok.kind == .rsbr {
133-
if nested_sbr_count > 0 {
134-
nested_sbr_count--
135-
} else {
136-
if p.peek_token(i + 1).kind == .lcbr {
137-
return true
138-
}
139-
break
119+
mut i := 2
120+
mut nested_sbr_count := 0
121+
for {
122+
cur_tok := p.peek_token(i)
123+
if cur_tok.kind == .eof
124+
|| cur_tok.kind !in [.amp, .dot, .comma, .name, .lpar, .rpar, .lsbr, .rsbr, .key_fn] {
125+
break
126+
}
127+
if cur_tok.kind == .lsbr {
128+
nested_sbr_count++
129+
} else if cur_tok.kind == .rsbr {
130+
if nested_sbr_count > 0 {
131+
nested_sbr_count--
132+
} else {
133+
if p.peek_token(i + 1).kind == .lcbr {
134+
return true
140135
}
136+
break
141137
}
142-
i++
143138
}
139+
i++
144140
}
145141
return false
146142
}
@@ -150,22 +146,22 @@ fn (p &Parser) is_typename(t token.Token) bool {
150146
return t.kind == .name && (t.lit[0].is_capital() || p.table.known_type(t.lit))
151147
}
152148

153-
// heuristics to detect `func<T>()` from `var < expr`
154-
// 1. `f<[]` is generic(e.g. `f<[]int>`) because `var < []` is invalid
155-
// 2. `f<map[` is generic(e.g. `f<map[string]string>)
156-
// 3. `f<foo>` is generic because `v1 < foo > v2` is invalid syntax
157-
// 4. `f<foo<bar` is generic when bar is not generic T (f<foo<T>(), in contrast, is not generic!)
158-
// 5. `f<Foo,` is generic when Foo is typename.
159-
// otherwise it is not generic because it may be multi-value (e.g. `return f < foo, 0`).
160-
// 6. `f<mod.Foo>` is same as case 3
161-
// 7. `f<mod.Foo,` is same as case 5
149+
// heuristics to detect `func[T]()` from `var [ expr`
150+
// 1. `f[[]` is generic(e.g. `f[[]int]`) because `var [ []` is invalid
151+
// 2. `f[map[` is generic(e.g. `f[map[string]string])
152+
// 3. `f[foo]` is generic because `v1 [ foo ] v2` is invalid syntax
153+
// 4. `f[foo[bar` is generic when bar is not generic T (f[foo[T](), in contrast, is not generic!)
154+
// 5. `f[Foo,` is generic when Foo is typename.
155+
// otherwise it is not generic because it may be multi-value (e.g. `return f [ foo, 0`).
156+
// 6. `f[mod.Foo]` is same as case 3
157+
// 7. `f[mod.Foo,` is same as case 5
162158
// 8. if there is a &, ignore the & and see if it is a type
163159
// 9. otherwise, it's not generic
164160
// see also test_generic_detection in vlib/v/tests/generics_test.v
165161
@[direct_array_access]
166162
fn (p &Parser) is_generic_call() bool {
167163
lit0_is_capital := p.tok.kind != .eof && p.tok.lit.len > 0 && p.tok.lit[0].is_capital()
168-
if lit0_is_capital || p.peek_tok.kind !in [.lt, .lsbr] {
164+
if lit0_is_capital || p.peek_tok.kind != .lsbr {
169165
return false
170166
}
171167
mut tok2 := p.peek_token(2)
@@ -194,16 +190,7 @@ fn (p &Parser) is_generic_call() bool {
194190
// case 2
195191
return true
196192
}
197-
if p.peek_tok.kind == .lt {
198-
return match kind3 {
199-
.gt { true } // case 3
200-
.lt { !(tok4.lit.len == 1 && tok4.lit[0].is_capital()) } // case 4
201-
.comma { p.is_typename(tok2) } // case 5
202-
// case 6 and 7
203-
.dot { kind4 == .name && (kind5 == .gt || (kind5 == .comma && p.is_typename(tok4))) }
204-
else { false }
205-
}
206-
} else if p.peek_tok.kind == .lsbr {
193+
if p.peek_tok.kind == .lsbr {
207194
mut i := 3
208195
mut nested_sbr_count := 0
209196
for {
@@ -237,7 +224,7 @@ fn (p &Parser) is_generic_call() bool {
237224
return false
238225
}
239226

240-
const valid_tokens_inside_types = [token.Kind.lsbr, .rsbr, .name, .dot, .comma, .key_fn, .lt]
227+
const valid_tokens_inside_types = [token.Kind.lsbr, .rsbr, .name, .dot, .comma, .key_fn]
241228

242229
fn (mut p Parser) is_generic_cast() bool {
243230
if !ast.type_can_start_with_token(&p.tok) {
@@ -250,10 +237,10 @@ fn (mut p Parser) is_generic_cast() bool {
250237
i++
251238
tok := p.peek_token(i)
252239

253-
if tok.kind in [.lt, .lsbr] {
240+
if tok.kind == .lsbr {
254241
lt_count++
255242
level++
256-
} else if tok.kind in [.gt, .rsbr] {
243+
} else if tok.kind == .rsbr {
257244
level--
258245
}
259246
if lt_count > 0 && level == 0 {
@@ -265,10 +252,10 @@ fn (mut p Parser) is_generic_cast() bool {
265252
}
266253
}
267254
next_tok := p.peek_token(i + 1)
268-
// `next_tok` is the token following the closing `>` of the generic type: MyType<int>{
255+
// `next_tok` is the token following the closing `]` of the generic type: MyType[int]{
269256
// ^
270257
// if `next_tok` is a left paren, then the full expression looks something like
271-
// `Foo<string>(` or `Foo<mod.Type>(`, which are valid type casts - return true
258+
// `Foo[string](` or `Foo[mod.Type](`, which are valid type casts - return true
272259
if next_tok.kind == .lpar {
273260
return true
274261
}

0 commit comments

Comments
 (0)