From 58a76344cb85ed2a78f76911d961a55708b5b22e Mon Sep 17 00:00:00 2001 From: Nick Treleaven Date: Wed, 27 Jan 2021 12:52:52 +0000 Subject: [PATCH] checker: avoid SelectorExpr filter on Ident unless it's a generic type name (#8357) --- vlib/v/checker/checker.v | 3 ++- vlib/v/parser/fn.v | 18 ++---------------- vlib/v/util/scanning.v | 6 ++++++ 3 files changed, 10 insertions(+), 17 deletions(-) diff --git a/vlib/v/checker/checker.v b/vlib/v/checker/checker.v index 4c13b40458..5bc1f8b06c 100644 --- a/vlib/v/checker/checker.v +++ b/vlib/v/checker/checker.v @@ -2050,7 +2050,8 @@ pub fn (mut c Checker) selector_expr(mut selector_expr ast.SelectorExpr) table.T match mut selector_expr.expr { ast.Ident { name := selector_expr.expr.name - valid_generic := c.cur_fn.generic_params.filter(it.name == name).len != 0 + valid_generic := util.is_generic_type_name(name) + && c.cur_fn.generic_params.filter(it.name == name).len != 0 if valid_generic { name_type = table.Type(c.table.find_type_idx(name)).set_flag(.generic) } diff --git a/vlib/v/parser/fn.v b/vlib/v/parser/fn.v index 4c3b2bd301..df1b06a1e1 100644 --- a/vlib/v/parser/fn.v +++ b/vlib/v/parser/fn.v @@ -449,7 +449,7 @@ fn (mut p Parser) parse_generic_params() []ast.GenericParam { if name.len > 1 { p.error('generic parameter name needs to be exactly one char') } - if is_generic_name_reserved(p.tok.lit) { + if !util.is_generic_type_name(p.tok.lit) { p.error('`$p.tok.lit` is a reserved name and cannot be used for generics') } if name in param_names { @@ -467,23 +467,9 @@ fn (mut p Parser) parse_generic_params() []ast.GenericParam { return param_names.map(ast.GenericParam{it}) } -// is_valid_generic_character returns true if the character is reserved for someting else. -fn is_generic_name_reserved(name string) bool { - // C is used for cinterop - if name == 'C' { - return true - } - return false -} - -// is_generic_name returns true if the current token is a generic name. -fn is_generic_name(name string) bool { - return name.len == 1 && name.is_capital() && !is_generic_name_reserved(name) -} - // is_generic_name returns true if the current token is a generic name. fn (p Parser) is_generic_name() bool { - return p.tok.kind == .name && is_generic_name(p.tok.lit) + return p.tok.kind == .name && util.is_generic_type_name(p.tok.lit) } fn (mut p Parser) anon_fn() ast.AnonFn { diff --git a/vlib/v/util/scanning.v b/vlib/v/util/scanning.v index 072f7145d0..e17a39e804 100644 --- a/vlib/v/util/scanning.v +++ b/vlib/v/util/scanning.v @@ -38,6 +38,12 @@ pub fn good_type_name(s string) bool { return true } +// is_generic_type_name returns true if the current token is a generic type name. +[inline] +pub fn is_generic_type_name(name string) bool { + return name.len == 1 && name.is_capital() && name != 'C' +} + pub fn cescaped_path(s string) string { return s.replace('\\', '\\\\') }