checker: prohibit using non-lvalue as mut receiver (#10790)
parent
7c5f012cbc
commit
0d587d3580
|
@ -70,9 +70,10 @@ pub fn (mut b Builder) front_stages(v_files []string) ? {
|
||||||
util.timing_start('PARSE')
|
util.timing_start('PARSE')
|
||||||
b.parsed_files = parser.parse_files(v_files, b.table, b.pref, b.global_scope)
|
b.parsed_files = parser.parse_files(v_files, b.table, b.pref, b.global_scope)
|
||||||
b.parse_imports()
|
b.parse_imports()
|
||||||
util.get_timers().show('SCAN')
|
mut timers := util.get_timers()
|
||||||
util.get_timers().show('PARSE')
|
timers.show('SCAN')
|
||||||
util.get_timers().show_if_exists('PARSE stmt')
|
timers.show('PARSE')
|
||||||
|
timers.show_if_exists('PARSE stmt')
|
||||||
if b.pref.only_check_syntax {
|
if b.pref.only_check_syntax {
|
||||||
return error('stop_after_parser')
|
return error('stop_after_parser')
|
||||||
}
|
}
|
||||||
|
|
|
@ -43,7 +43,8 @@ pub fn compile(command string, pref &pref.Preferences) {
|
||||||
.js { b.compile_js() }
|
.js { b.compile_js() }
|
||||||
.native { b.compile_native() }
|
.native { b.compile_native() }
|
||||||
}
|
}
|
||||||
util.get_timers().show_remaining()
|
mut timers := util.get_timers()
|
||||||
|
timers.show_remaining()
|
||||||
if pref.is_stats {
|
if pref.is_stats {
|
||||||
compilation_time_micros := 1 + sw.elapsed().microseconds()
|
compilation_time_micros := 1 + sw.elapsed().microseconds()
|
||||||
scompilation_time_ms := util.bold('${f64(compilation_time_micros) / 1000.0:6.3f}')
|
scompilation_time_ms := util.bold('${f64(compilation_time_micros) / 1000.0:6.3f}')
|
||||||
|
|
|
@ -2106,6 +2106,9 @@ pub fn (mut c Checker) method_call(mut call_expr ast.CallExpr) ast.Type {
|
||||||
}
|
}
|
||||||
if method.params[0].is_mut {
|
if method.params[0].is_mut {
|
||||||
to_lock, pos := c.fail_if_immutable(call_expr.left)
|
to_lock, pos := c.fail_if_immutable(call_expr.left)
|
||||||
|
if !call_expr.left.is_lvalue() {
|
||||||
|
c.error('cannot pass expression as `mut`', call_expr.left.position())
|
||||||
|
}
|
||||||
// call_expr.is_mut = true
|
// call_expr.is_mut = true
|
||||||
if to_lock != '' && rec_share != .shared_t {
|
if to_lock != '' && rec_share != .shared_t {
|
||||||
c.error('$to_lock is `shared` and must be `lock`ed to be passed as `mut`',
|
c.error('$to_lock is `shared` and must be `lock`ed to be passed as `mut`',
|
||||||
|
|
|
@ -0,0 +1,5 @@
|
||||||
|
vlib/v/checker/tests/mut_receiver_lit.vv:10:1: error: cannot pass expression as `mut`
|
||||||
|
8 | }
|
||||||
|
9 |
|
||||||
|
10 | Box{}.set(0)
|
||||||
|
| ~~~~~
|
|
@ -0,0 +1,10 @@
|
||||||
|
struct Box {
|
||||||
|
mut:
|
||||||
|
value int
|
||||||
|
}
|
||||||
|
|
||||||
|
fn (mut box Box) set(value int) {
|
||||||
|
box.value = value
|
||||||
|
}
|
||||||
|
|
||||||
|
Box{}.set(0)
|
|
@ -537,11 +537,12 @@ fn (mut s Scanner) end_of_file() token.Token {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn (mut s Scanner) scan_all_tokens_in_buffer(mode CommentsMode) {
|
pub fn (mut s Scanner) scan_all_tokens_in_buffer(mode CommentsMode) {
|
||||||
util.get_timers().measure_pause('PARSE')
|
mut timers := util.get_timers()
|
||||||
|
timers.measure_pause('PARSE')
|
||||||
util.timing_start('SCAN')
|
util.timing_start('SCAN')
|
||||||
defer {
|
defer {
|
||||||
util.timing_measure_cumulative('SCAN')
|
util.timing_measure_cumulative('SCAN')
|
||||||
util.get_timers().measure_resume('PARSE')
|
timers.measure_resume('PARSE')
|
||||||
}
|
}
|
||||||
oldmode := s.comments_mode
|
oldmode := s.comments_mode
|
||||||
s.comments_mode = mode
|
s.comments_mode = mode
|
||||||
|
|
|
@ -1,30 +0,0 @@
|
||||||
struct Test {
|
|
||||||
mut:
|
|
||||||
val int
|
|
||||||
}
|
|
||||||
|
|
||||||
// this must return a reference, or else you'll get a C error
|
|
||||||
// TODO: add a proper checker check for that case
|
|
||||||
fn new(x int) &Test {
|
|
||||||
return &Test{x}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn (mut t Test) inc() &Test {
|
|
||||||
t.val++
|
|
||||||
return unsafe { t }
|
|
||||||
}
|
|
||||||
|
|
||||||
fn (mut t Test) add(x int) &Test {
|
|
||||||
t.val += x
|
|
||||||
return unsafe { t }
|
|
||||||
}
|
|
||||||
|
|
||||||
fn (mut t Test) div(x int) &Test {
|
|
||||||
t.val /= x
|
|
||||||
return unsafe { t }
|
|
||||||
}
|
|
||||||
|
|
||||||
fn test_method_call_chains() {
|
|
||||||
mut x := new(4).inc().inc().inc().inc().add(4).div(2).inc()
|
|
||||||
assert x.val == 7
|
|
||||||
}
|
|
|
@ -28,15 +28,18 @@ pub fn get_timers() &Timers {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn timing_start(label string) {
|
pub fn timing_start(label string) {
|
||||||
get_timers().start(label)
|
mut t := get_timers()
|
||||||
|
t.start(label)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn timing_measure(label string) {
|
pub fn timing_measure(label string) {
|
||||||
get_timers().show(label)
|
mut t := get_timers()
|
||||||
|
t.show(label)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn timing_measure_cumulative(label string) {
|
pub fn timing_measure_cumulative(label string) {
|
||||||
get_timers().measure_cumulative(label)
|
mut t := get_timers()
|
||||||
|
t.measure_cumulative(label)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn timing_set_should_print(should_print bool) {
|
pub fn timing_set_should_print(should_print bool) {
|
||||||
|
|
Loading…
Reference in New Issue