parser: fix panic when single letter receiver parsed (#8381)
							parent
							
								
									5fc7eadd8b
								
							
						
					
					
						commit
						93b0d8ca64
					
				| 
						 | 
					@ -5296,7 +5296,7 @@ fn (mut c Checker) fn_decl(mut node ast.FnDecl) {
 | 
				
			||||||
			sym := c.table.get_type_symbol(arg.typ)
 | 
								sym := c.table.get_type_symbol(arg.typ)
 | 
				
			||||||
			if sym.kind == .placeholder
 | 
								if sym.kind == .placeholder
 | 
				
			||||||
				|| (sym.kind in [table.Kind.int_literal, .float_literal] && !c.is_builtin_mod) {
 | 
									|| (sym.kind in [table.Kind.int_literal, .float_literal] && !c.is_builtin_mod) {
 | 
				
			||||||
				c.error('unknown type `$sym.name`', node.pos)
 | 
									c.error('unknown type `$sym.name`', node.receiver_pos)
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -0,0 +1,3 @@
 | 
				
			||||||
 | 
					vlib/v/checker/tests/receiver_unknown_type_single_letter.vv:1:5: error: unknown type `A`
 | 
				
			||||||
 | 
					    1 | fn (p A) foo() {}
 | 
				
			||||||
 | 
					      |     ~~~
 | 
				
			||||||
| 
						 | 
					@ -0,0 +1 @@
 | 
				
			||||||
 | 
					fn (p A) foo() {}
 | 
				
			||||||
| 
						 | 
					@ -190,6 +190,7 @@ fn (mut p Parser) fn_decl() ast.FnDecl {
 | 
				
			||||||
	mut rec_mut := false
 | 
						mut rec_mut := false
 | 
				
			||||||
	mut params := []table.Param{}
 | 
						mut params := []table.Param{}
 | 
				
			||||||
	if p.tok.kind == .lpar {
 | 
						if p.tok.kind == .lpar {
 | 
				
			||||||
 | 
							p.is_parsing_receiver = true
 | 
				
			||||||
		lpar_pos := p.tok.position()
 | 
							lpar_pos := p.tok.position()
 | 
				
			||||||
		p.next() // (
 | 
							p.next() // (
 | 
				
			||||||
		is_method = true
 | 
							is_method = true
 | 
				
			||||||
| 
						 | 
					@ -246,6 +247,7 @@ fn (mut p Parser) fn_decl() ast.FnDecl {
 | 
				
			||||||
			typ: rec_type
 | 
								typ: rec_type
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		p.check(.rpar)
 | 
							p.check(.rpar)
 | 
				
			||||||
 | 
							p.is_parsing_receiver = false
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	mut name := ''
 | 
						mut name := ''
 | 
				
			||||||
	if p.tok.kind == .name {
 | 
						if p.tok.kind == .name {
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -373,7 +373,7 @@ pub fn (mut p Parser) parse_any_type(language table.Language, is_ptr bool, check
 | 
				
			||||||
					return table.int_literal_type
 | 
										return table.int_literal_type
 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
				else {
 | 
									else {
 | 
				
			||||||
					if name.len == 1 && name[0].is_capital() {
 | 
										if name.len == 1 && name[0].is_capital() && !p.is_parsing_receiver {
 | 
				
			||||||
						return p.parse_generic_template_type(name)
 | 
											return p.parse_generic_template_type(name)
 | 
				
			||||||
					}
 | 
										}
 | 
				
			||||||
					if p.peek_tok.kind == .lt {
 | 
										if p.peek_tok.kind == .lt {
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -29,48 +29,49 @@ mut:
 | 
				
			||||||
	scanner           &scanner.Scanner
 | 
						scanner           &scanner.Scanner
 | 
				
			||||||
	comments_mode     scanner.CommentsMode = .skip_comments
 | 
						comments_mode     scanner.CommentsMode = .skip_comments
 | 
				
			||||||
	// see comment in parse_file
 | 
						// see comment in parse_file
 | 
				
			||||||
	tok               token.Token
 | 
						tok                 token.Token
 | 
				
			||||||
	prev_tok          token.Token
 | 
						prev_tok            token.Token
 | 
				
			||||||
	peek_tok          token.Token
 | 
						peek_tok            token.Token
 | 
				
			||||||
	peek_tok2         token.Token
 | 
						peek_tok2           token.Token
 | 
				
			||||||
	peek_tok3         token.Token
 | 
						peek_tok3           token.Token
 | 
				
			||||||
	table             &table.Table
 | 
						table               &table.Table
 | 
				
			||||||
	language          table.Language
 | 
						language            table.Language
 | 
				
			||||||
	inside_if         bool
 | 
						inside_if           bool
 | 
				
			||||||
	inside_if_expr    bool
 | 
						inside_if_expr      bool
 | 
				
			||||||
	inside_ct_if_expr bool
 | 
						inside_ct_if_expr   bool
 | 
				
			||||||
	inside_or_expr    bool
 | 
						inside_or_expr      bool
 | 
				
			||||||
	inside_for        bool
 | 
						inside_for          bool
 | 
				
			||||||
	inside_fn         bool // true even with implicit main
 | 
						inside_fn           bool // true even with implicit main
 | 
				
			||||||
	inside_str_interp bool
 | 
						inside_str_interp   bool
 | 
				
			||||||
	or_is_handled     bool         // ignore `or` in this expression
 | 
						or_is_handled       bool         // ignore `or` in this expression
 | 
				
			||||||
	builtin_mod       bool         // are we in the `builtin` module?
 | 
						builtin_mod         bool         // are we in the `builtin` module?
 | 
				
			||||||
	mod               string       // current module name
 | 
						mod                 string       // current module name
 | 
				
			||||||
	is_manualfree     bool         // true when `[manualfree] module abc`, makes *all* fns in the current .v file, opt out of autofree
 | 
						is_manualfree       bool         // true when `[manualfree] module abc`, makes *all* fns in the current .v file, opt out of autofree
 | 
				
			||||||
	attrs             []table.Attr // attributes before next decl stmt
 | 
						attrs               []table.Attr // attributes before next decl stmt
 | 
				
			||||||
	expr_mod          string       // for constructing full type names in parse_type()
 | 
						expr_mod            string       // for constructing full type names in parse_type()
 | 
				
			||||||
	scope             &ast.Scope
 | 
						scope               &ast.Scope
 | 
				
			||||||
	global_scope      &ast.Scope
 | 
						global_scope        &ast.Scope
 | 
				
			||||||
	imports           map[string]string // alias => mod_name
 | 
						imports             map[string]string // alias => mod_name
 | 
				
			||||||
	ast_imports       []ast.Import      // mod_names
 | 
						ast_imports         []ast.Import      // mod_names
 | 
				
			||||||
	used_imports      []string // alias
 | 
						used_imports        []string // alias
 | 
				
			||||||
	auto_imports      []string // imports, the user does not need to specify
 | 
						auto_imports        []string // imports, the user does not need to specify
 | 
				
			||||||
	imported_symbols  map[string]string
 | 
						imported_symbols    map[string]string
 | 
				
			||||||
	is_amp            bool // for generating the right code for `&Foo{}`
 | 
						is_amp              bool // for generating the right code for `&Foo{}`
 | 
				
			||||||
	returns           bool
 | 
						returns             bool
 | 
				
			||||||
	inside_match      bool // to separate `match A { }` from `Struct{}`
 | 
						inside_match        bool // to separate `match A { }` from `Struct{}`
 | 
				
			||||||
	inside_select     bool // to allow `ch <- Struct{} {` inside `select`
 | 
						inside_select       bool // to allow `ch <- Struct{} {` inside `select`
 | 
				
			||||||
	inside_match_case bool // to separate `match_expr { }` from `Struct{}`
 | 
						inside_match_case   bool // to separate `match_expr { }` from `Struct{}`
 | 
				
			||||||
	inside_match_body bool // to fix eval not used TODO
 | 
						inside_match_body   bool // to fix eval not used TODO
 | 
				
			||||||
	inside_unsafe     bool
 | 
						inside_unsafe       bool
 | 
				
			||||||
	is_stmt_ident     bool // true while the beginning of a statement is an ident/selector
 | 
						is_stmt_ident       bool // true while the beginning of a statement is an ident/selector
 | 
				
			||||||
	expecting_type    bool // `is Type`, expecting type
 | 
						expecting_type      bool // `is Type`, expecting type
 | 
				
			||||||
	errors            []errors.Error
 | 
						errors              []errors.Error
 | 
				
			||||||
	warnings          []errors.Warning
 | 
						warnings            []errors.Warning
 | 
				
			||||||
	vet_errors        []vet.Error
 | 
						vet_errors          []vet.Error
 | 
				
			||||||
	cur_fn_name       string
 | 
						cur_fn_name         string
 | 
				
			||||||
	in_generic_params bool // indicates if parsing between `<` and `>` of a method/function
 | 
						in_generic_params   bool // indicates if parsing between `<` and `>` of a method/function
 | 
				
			||||||
	name_error        bool // indicates if the token is not a name or the name is on another line
 | 
						name_error          bool // indicates if the token is not a name or the name is on another line
 | 
				
			||||||
 | 
						is_parsing_receiver bool // indicates if parser is parsing receiver fn (x Xxx)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// for tests
 | 
					// for tests
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in New Issue