checker: verify interface is not used as receiver
							parent
							
								
									7d32476841
								
							
						
					
					
						commit
						0f8ed84333
					
				| 
						 | 
					@ -206,6 +206,7 @@ pub:
 | 
				
			||||||
	is_variadic   bool
 | 
						is_variadic   bool
 | 
				
			||||||
	is_anon       bool
 | 
						is_anon       bool
 | 
				
			||||||
	receiver      Field
 | 
						receiver      Field
 | 
				
			||||||
 | 
						receiver_pos  token.Position
 | 
				
			||||||
	is_method     bool
 | 
						is_method     bool
 | 
				
			||||||
	rec_mut       bool // is receiver mutable
 | 
						rec_mut       bool // is receiver mutable
 | 
				
			||||||
	is_c          bool
 | 
						is_c          bool
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1385,12 +1385,15 @@ fn (mut c Checker) stmt(node ast.Stmt) {
 | 
				
			||||||
			c.check_expr_opt_call(it.expr, etype, false)
 | 
								c.check_expr_opt_call(it.expr, etype, false)
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		ast.FnDecl {
 | 
							ast.FnDecl {
 | 
				
			||||||
			// if it.is_method {
 | 
								if it.is_method {
 | 
				
			||||||
			// sym := c.table.get_type_symbol(it.receiver.typ)
 | 
									sym := c.table.get_type_symbol(it.receiver.typ)
 | 
				
			||||||
 | 
									if sym.kind == .interface_ {
 | 
				
			||||||
 | 
										c.error('interaces cannot be used as method receiver', it.receiver_pos)
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
				// if sym.has_method(it.name) {
 | 
									// if sym.has_method(it.name) {
 | 
				
			||||||
				// c.warn('duplicate method `$it.name`', it.pos)
 | 
									// c.warn('duplicate method `$it.name`', it.pos)
 | 
				
			||||||
				// }
 | 
									// }
 | 
				
			||||||
			// }
 | 
								}
 | 
				
			||||||
			if !it.is_c {
 | 
								if !it.is_c {
 | 
				
			||||||
				// Make sure all types are valid
 | 
									// Make sure all types are valid
 | 
				
			||||||
				for arg in it.args {
 | 
									for arg in it.args {
 | 
				
			||||||
| 
						 | 
					@ -1748,7 +1751,8 @@ pub fn (mut c Checker) ident(ident mut ast.Ident) table.Type {
 | 
				
			||||||
					if sym.info is table.FnType {
 | 
										if sym.info is table.FnType {
 | 
				
			||||||
						// anon/local fn assigned to new variable uses this
 | 
											// anon/local fn assigned to new variable uses this
 | 
				
			||||||
						info := sym.info as table.FnType
 | 
											info := sym.info as table.FnType
 | 
				
			||||||
						fn_type := table.new_type(c.table.find_or_register_fn_type(info.func, true, true))
 | 
											fn_type := table.new_type(c.table.find_or_register_fn_type(info.func,
 | 
				
			||||||
 | 
												true, true))
 | 
				
			||||||
						ident.kind = .function
 | 
											ident.kind = .function
 | 
				
			||||||
						ident.info = ast.IdentFn{
 | 
											ident.info = ast.IdentFn{
 | 
				
			||||||
							typ: fn_type
 | 
												typ: fn_type
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -0,0 +1,6 @@
 | 
				
			||||||
 | 
					vlib/v/checker/tests/no_interface_receiver.v:5:5: error: interaces cannot be used as method receiver
 | 
				
			||||||
 | 
					    3 | }
 | 
				
			||||||
 | 
					    4 |
 | 
				
			||||||
 | 
					    5 | fn (a Animal) str() {}
 | 
				
			||||||
 | 
					      |     ~~~~~~~~
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -0,0 +1,5 @@
 | 
				
			||||||
 | 
					interface Animal {
 | 
				
			||||||
 | 
						speak()
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					fn (a Animal) str() {}
 | 
				
			||||||
| 
						 | 
					@ -109,6 +109,7 @@ fn (mut p Parser) fn_decl() ast.FnDecl {
 | 
				
			||||||
	// Receiver?
 | 
						// Receiver?
 | 
				
			||||||
	mut rec_name := ''
 | 
						mut rec_name := ''
 | 
				
			||||||
	mut is_method := false
 | 
						mut is_method := false
 | 
				
			||||||
 | 
						mut receiver_pos := token.Position{}
 | 
				
			||||||
	mut rec_type := table.void_type
 | 
						mut rec_type := table.void_type
 | 
				
			||||||
	mut rec_mut := false
 | 
						mut rec_mut := false
 | 
				
			||||||
	mut args := []table.Arg{}
 | 
						mut args := []table.Arg{}
 | 
				
			||||||
| 
						 | 
					@ -119,11 +120,13 @@ fn (mut p Parser) fn_decl() ast.FnDecl {
 | 
				
			||||||
		if rec_mut {
 | 
							if rec_mut {
 | 
				
			||||||
			p.next() // `mut`
 | 
								p.next() // `mut`
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
							rec_start_pos := p.tok.position()
 | 
				
			||||||
		rec_name = p.check_name()
 | 
							rec_name = p.check_name()
 | 
				
			||||||
		if !rec_mut {
 | 
							if !rec_mut {
 | 
				
			||||||
			rec_mut = p.tok.kind == .key_mut
 | 
								rec_mut = p.tok.kind == .key_mut
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		is_amp := p.tok.kind == .amp
 | 
							is_amp := p.tok.kind == .amp
 | 
				
			||||||
 | 
							receiver_pos = rec_start_pos.extend(p.tok.position())
 | 
				
			||||||
		// if rec_mut {
 | 
							// if rec_mut {
 | 
				
			||||||
		// p.check(.key_mut)
 | 
							// p.check(.key_mut)
 | 
				
			||||||
		// }
 | 
							// }
 | 
				
			||||||
| 
						 | 
					@ -256,6 +259,7 @@ fn (mut p Parser) fn_decl() ast.FnDecl {
 | 
				
			||||||
			name: rec_name
 | 
								name: rec_name
 | 
				
			||||||
			typ: rec_type
 | 
								typ: rec_type
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
							receiver_pos: receiver_pos
 | 
				
			||||||
		is_method: is_method
 | 
							is_method: is_method
 | 
				
			||||||
		rec_mut: rec_mut
 | 
							rec_mut: rec_mut
 | 
				
			||||||
		is_c: is_c
 | 
							is_c: is_c
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in New Issue