pull/14006/merge
Vincenzo Palazzo 2022-04-14 17:50:02 +03:00 committed by GitHub
commit 7af42e03b8
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 147 additions and 53 deletions

View File

@ -687,3 +687,33 @@ pub fn (mut c Checker) infer_fn_generic_types(func ast.Fn, mut node ast.CallExpr
c.need_recheck_generic_fns = true
}
}
// generic_type_has_concrete_type make sure that the generics is declared with a type
// `Type<int>` and not `Type<T>`.
fn (mut c Checker) generic_type_has_declared_with_concrete_type(typ ast.Type) bool {
return c.concrete_type_in_generic_type(typ).len > 0
}
fn (mut c Checker) concrete_type_in_generic_type(typ ast.Type) []ast.Type {
if typ.has_flag(.generic) /*true*/ {
//println('Chekcing generics ${c.table.type_to_str(typ)}')
unwrap_typ := c.unwrap_generic(typ)
//println('---> Generic inside ${c.table.type_to_str(unwrap_typ)}')
unwrap_sym := c.table.sym(unwrap_typ)
match unwrap_sym.info {
ast.Struct, ast.SumType, ast.Interface {
//println('Concrete types ${unwrap_sym.info.concrete_types}')
return unwrap_sym.info.concrete_types
}
ast.Alias {
return c.concrete_type_in_generic_type(unwrap_sym.info.parent_type)
}
else {
//println(unwrap_sym.info)
//println('****** no match found')
}
}
}
return []ast.Type{}
}

View File

@ -2464,17 +2464,6 @@ fn (mut c Checker) stmts_ending_with_expression(stmts []ast.Stmt) {
c.scope_returns = false
}
pub fn (mut c Checker) unwrap_generic(typ ast.Type) ast.Type {
if typ.has_flag(.generic) {
if t_typ := c.table.resolve_generic_to_concrete(typ, c.table.cur_fn.generic_names,
c.table.cur_concrete_types)
{
return t_typ
}
}
return typ
}
// TODO node must be mut
pub fn (mut c Checker) expr(node_ ast.Expr) ast.Type {
c.expr_level++
@ -4159,48 +4148,6 @@ fn (mut c Checker) trace(fbase string, message string) {
}
}
fn (mut c Checker) ensure_type_exists(typ ast.Type, pos token.Pos) ? {
if typ == 0 {
c.error('unknown type', pos)
return
}
sym := c.table.sym(typ)
match sym.kind {
.placeholder {
if sym.language == .v && !sym.name.starts_with('C.') {
c.error(util.new_suggestion(sym.name, c.table.known_type_names()).say('unknown type `$sym.name`'),
pos)
return
}
}
.int_literal, .float_literal {
// Separate error condition for `int_literal` and `float_literal` because `util.suggestion` may give different
// suggestions due to f32 comparision issue.
if !c.is_builtin_mod {
msg := if sym.kind == .int_literal {
'unknown type `$sym.name`.\nDid you mean `int`?'
} else {
'unknown type `$sym.name`.\nDid you mean `f64`?'
}
c.error(msg, pos)
return
}
}
.array {
c.ensure_type_exists((sym.info as ast.Array).elem_type, pos) ?
}
.array_fixed {
c.ensure_type_exists((sym.info as ast.ArrayFixed).elem_type, pos) ?
}
.map {
info := sym.info as ast.Map
c.ensure_type_exists(info.key_type, pos) ?
c.ensure_type_exists(info.value_type, pos) ?
}
else {}
}
}
pub fn (mut c Checker) fail_if_unreadable(expr ast.Expr, typ ast.Type, what string) {
mut pos := token.Pos{}
match expr {

View File

@ -0,0 +1,34 @@
type ParseRes = Result<[]Token, ParseErr>
// Token type is unknown
//struct Token {}
struct ParseErr {}
type Opt<T> = None<T> | Some<T>
struct None<T> {}
struct Some<T> {
value T
}
type Result<T, U> = Err<U> | Ok<T>
struct Ok<T> {
value T
}
struct Err<U> {
value U
}
fn test_report() {
r := Opt<ParseRes>(None<ParseRes>{})
match r {
Some<ParseRes> {
rx := r.value
}
None<ParseRes> {}
}
}

View File

@ -0,0 +1,83 @@
module checker
import v.ast
import v.token
import v.util
// unwrap_generic unwrap the concrete type.
fn (mut c Checker) unwrap_generic(typ ast.Type) ast.Type {
if typ.has_flag(.generic) {
if t_typ := c.table.resolve_generic_to_concrete(typ, c.table.cur_fn.generic_names,
c.table.cur_concrete_types)
{
return t_typ
}
}
return typ
}
// ensure_type_exists check if the type was found somewhere before.
fn (mut c Checker) ensure_type_exists(typ ast.Type, pos token.Pos) ? {
if typ == 0 {
c.error('unknown type', pos)
return
}
sym := c.table.sym(typ)
match sym.kind {
.placeholder {
if sym.language == .v && !sym.name.starts_with('C.') {
c.error(util.new_suggestion(sym.name, c.table.known_type_names()).say('unknown type `$sym.name`'),
pos)
return
}
}
.int_literal, .float_literal {
// Separate error condition for `int_literal` and `float_literal` because `util.suggestion` may give different
// suggestions due to f32 comparision issue.
if !c.is_builtin_mod {
msg := if sym.kind == .int_literal {
'unknown type `$sym.name`.\nDid you mean `int`?'
} else {
'unknown type `$sym.name`.\nDid you mean `f64`?'
}
c.error(msg, pos)
return
}
}
.array {
c.ensure_type_exists((sym.info as ast.Array).elem_type, pos) ?
}
.array_fixed {
c.ensure_type_exists((sym.info as ast.ArrayFixed).elem_type, pos) ?
}
.map {
info := sym.info as ast.Map
c.ensure_type_exists(info.key_type, pos) ?
c.ensure_type_exists(info.value_type, pos) ?
}
.struct_ {
concrete_typs := c.concrete_type_in_generic_type(typ)
if concrete_typs.len > 0 {
for concrete_typ in concrete_typs {
//println('From Generics type ${c.table.type_to_str(concrete_typ)}')
c.ensure_type_exists(concrete_typ, pos) ?
}
}
}
.alias {
info := sym.info as ast.Alias
//println('Base type ${c.table.type_to_str(typ)}')
//println('Parent type ${c.table.type_to_str(info.parent_type)}')
c.ensure_type_exists(info.parent_type, pos) ?
}
.sum_type {
info := sym.info as ast.SumType
//println('Sum type ${c.table.type_to_str(typ)}')
for variant_typ in info.variants {
//println('Variant type -> ${c.table.type_to_str(variant_typ)}')
c.ensure_type_exists(variant_typ, pos) ?
}
}
else {}
}
}