ast, parser, checker: fix generic fn in builtin module (#12769)
							parent
							
								
									dbe67c688f
								
							
						
					
					
						commit
						7fc9e614a3
					
				| 
						 | 
				
			
			@ -1153,8 +1153,12 @@ pub fn (t &Table) mktyp(typ Type) Type {
 | 
			
		|||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
pub fn (mut t Table) register_fn_generic_types(fn_name string) {
 | 
			
		||||
	t.fn_generic_types[fn_name] = [][]Type{}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
pub fn (mut t Table) register_fn_concrete_types(fn_name string, types []Type) bool {
 | 
			
		||||
	mut a := t.fn_generic_types[fn_name]
 | 
			
		||||
	mut a := t.fn_generic_types[fn_name] or { return false }
 | 
			
		||||
	if types in a {
 | 
			
		||||
		return false
 | 
			
		||||
	}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1986,17 +1986,15 @@ pub fn (mut c Checker) method_call(mut node ast.CallExpr) ast.Type {
 | 
			
		|||
		// c.error('`void` type has no methods', node.left.position())
 | 
			
		||||
		return ast.void_type
 | 
			
		||||
	}
 | 
			
		||||
	mut has_generic := false // x.foo<T>() instead of x.foo<int>()
 | 
			
		||||
	mut concrete_types := []ast.Type{}
 | 
			
		||||
	for concrete_type in node.concrete_types {
 | 
			
		||||
		if concrete_type.has_flag(.generic) {
 | 
			
		||||
			has_generic = true
 | 
			
		||||
			concrete_types << c.unwrap_generic(concrete_type)
 | 
			
		||||
		} else {
 | 
			
		||||
			concrete_types << concrete_type
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	if has_generic {
 | 
			
		||||
	if concrete_types.len > 0 {
 | 
			
		||||
		if c.table.register_fn_concrete_types(node.name, concrete_types) {
 | 
			
		||||
			c.need_recheck_generic_fns = true
 | 
			
		||||
		}
 | 
			
		||||
| 
						 | 
				
			
			@ -2539,13 +2537,17 @@ pub fn (mut c Checker) fn_call(mut node ast.CallExpr, mut continue_check &bool)
 | 
			
		|||
		c.error('generic fn using generic types cannot be called outside of generic fn',
 | 
			
		||||
			node.pos)
 | 
			
		||||
	}
 | 
			
		||||
	if has_generic {
 | 
			
		||||
	if concrete_types.len > 0 {
 | 
			
		||||
		mut no_exists := true
 | 
			
		||||
		if c.mod != '' && !fn_name.contains('.') {
 | 
			
		||||
			// Need to prepend the module when adding a generic type to a function
 | 
			
		||||
			no_exists = c.table.register_fn_concrete_types(c.mod + '.' + fn_name, concrete_types)
 | 
			
		||||
		} else {
 | 
			
		||||
		if fn_name.contains('.') {
 | 
			
		||||
			no_exists = c.table.register_fn_concrete_types(fn_name, concrete_types)
 | 
			
		||||
		} else {
 | 
			
		||||
			no_exists = c.table.register_fn_concrete_types(c.mod + '.' + fn_name, concrete_types)
 | 
			
		||||
			// if the generic fn does not exist in the current fn calling module, continue
 | 
			
		||||
			// to look in builtin module
 | 
			
		||||
			if !no_exists {
 | 
			
		||||
				no_exists = c.table.register_fn_concrete_types(fn_name, concrete_types)
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
		if no_exists {
 | 
			
		||||
			c.need_recheck_generic_fns = true
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -40,14 +40,6 @@ pub fn (mut p Parser) call_expr(language ast.Language, mod string) ast.CallExpr
 | 
			
		|||
		p.expr_mod = ''
 | 
			
		||||
		concrete_types = p.parse_concrete_types()
 | 
			
		||||
		concrete_list_pos = concrete_list_pos.extend(p.prev_tok.position())
 | 
			
		||||
		// In case of `foo<T>()`
 | 
			
		||||
		// T is unwrapped and registered in the checker.
 | 
			
		||||
		full_generic_fn_name := if fn_name.contains('.') { fn_name } else { p.prepend_mod(fn_name) }
 | 
			
		||||
		has_generic := concrete_types.any(it.has_flag(.generic))
 | 
			
		||||
		if !has_generic {
 | 
			
		||||
			// will be added in checker
 | 
			
		||||
			p.table.register_fn_concrete_types(full_generic_fn_name, concrete_types)
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	p.check(.lpar)
 | 
			
		||||
	args := p.call_args()
 | 
			
		||||
| 
						 | 
				
			
			@ -528,6 +520,9 @@ fn (mut p Parser) fn_decl() ast.FnDecl {
 | 
			
		|||
		scope: p.scope
 | 
			
		||||
		label_names: p.label_names
 | 
			
		||||
	}
 | 
			
		||||
	if generic_names.len > 0 {
 | 
			
		||||
		p.table.register_fn_generic_types(name)
 | 
			
		||||
	}
 | 
			
		||||
	p.label_names = []
 | 
			
		||||
	p.close_scope()
 | 
			
		||||
	return fn_decl
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in New Issue