From 8225622da5d5a31fee4024476bc52eb433aaadf0 Mon Sep 17 00:00:00 2001 From: yuyi Date: Mon, 12 Dec 2022 15:22:56 +0800 Subject: [PATCH] checker: check smartcasting requires either an immutable value, or an explicit mut keyword before the value (#16654) --- vlib/v/checker/fn.v | 10 ++++++ .../tests/incorrect_smartcast3_err.out | 28 +++++++++++++++ .../checker/tests/incorrect_smartcast3_err.vv | 34 +++++++++++++++++++ 3 files changed, 72 insertions(+) create mode 100644 vlib/v/checker/tests/incorrect_smartcast3_err.out create mode 100644 vlib/v/checker/tests/incorrect_smartcast3_err.vv diff --git a/vlib/v/checker/fn.v b/vlib/v/checker/fn.v index 9c6546d4f2..c86af5079f 100644 --- a/vlib/v/checker/fn.v +++ b/vlib/v/checker/fn.v @@ -1925,6 +1925,16 @@ fn (mut c Checker) method_call(mut node ast.CallExpr) ast.Type { return info.func.return_type } } + if left_sym.kind in [.struct_, .aggregate, .interface_, .sum_type] { + if c.smartcast_mut_pos != token.Pos{} { + c.note('smartcasting requires either an immutable value, or an explicit mut keyword before the value', + c.smartcast_mut_pos) + } + if c.smartcast_cond_pos != token.Pos{} { + c.note('smartcast can only be used on the ident or selector, e.g. match foo, match foo.bar', + c.smartcast_cond_pos) + } + } if left_type != ast.void_type { suggestion := util.new_suggestion(method_name, left_sym.methods.map(it.name)) c.error(suggestion.say(unknown_method_msg), node.pos) diff --git a/vlib/v/checker/tests/incorrect_smartcast3_err.out b/vlib/v/checker/tests/incorrect_smartcast3_err.out new file mode 100644 index 0000000000..96a6471a1f --- /dev/null +++ b/vlib/v/checker/tests/incorrect_smartcast3_err.out @@ -0,0 +1,28 @@ +vlib/v/checker/tests/incorrect_smartcast3_err.vv:25:5: notice: smartcasting requires either an immutable value, or an explicit mut keyword before the value + 23 | + 24 | mut r := la.regex + 25 | if r is RE { + | ^ + 26 | println(r) + 27 | println(r.matches_string(item)) +vlib/v/checker/tests/incorrect_smartcast3_err.vv:30:8: notice: smartcasting requires either an immutable value, or an explicit mut keyword before the value + 28 | } + 29 | + 30 | match r { + | ^ + 31 | RE { r.matches_string(item) } + 32 | else {} +vlib/v/checker/tests/incorrect_smartcast3_err.vv:27:13: error: unknown method or field: `OurRegex.matches_string` + 25 | if r is RE { + 26 | println(r) + 27 | println(r.matches_string(item)) + | ~~~~~~~~~~~~~~~~~~~~ + 28 | } + 29 | +vlib/v/checker/tests/incorrect_smartcast3_err.vv:31:10: error: unknown method or field: `OurRegex.matches_string` + 29 | + 30 | match r { + 31 | RE { r.matches_string(item) } + | ~~~~~~~~~~~~~~~~~~~~ + 32 | else {} + 33 | } diff --git a/vlib/v/checker/tests/incorrect_smartcast3_err.vv b/vlib/v/checker/tests/incorrect_smartcast3_err.vv new file mode 100644 index 0000000000..e8a7220d7b --- /dev/null +++ b/vlib/v/checker/tests/incorrect_smartcast3_err.vv @@ -0,0 +1,34 @@ +module main + +import regex { RE, regex_opt } + +pub struct EmptyRegex { +} + +type OurRegex = EmptyRegex | RE + +pub struct ListArgs { +pub mut: + regex OurRegex +} + +fn main() { + query := r'(c(pa)+z ?)+' + mut re := regex_opt(query) or { panic(err) } + + item := 'sss' + mut la := ListArgs{ + regex: re + } + + mut r := la.regex + if r is RE { + println(r) + println(r.matches_string(item)) + } + + match r { + RE { r.matches_string(item) } + else {} + } +}