mirror of
https://github.com/vlang/v.git
synced 2023-08-10 21:13:21 +03:00
ast.table: cleanup type_implements_interface() (#10643)
This commit is contained in:
parent
a33a2ba095
commit
abbf71c794
@ -1099,9 +1099,7 @@ pub fn (mut t Table) bitsize_to_type(bit_size int) Type {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn (mut table Table) does_type_implement_interface(typ Type, inter_typ Type) bool {
|
pub fn (mut t Table) does_type_implement_interface(typ Type, inter_typ Type) bool {
|
||||||
// TODO: merge with c.type_implements, which also does error reporting in addition
|
|
||||||
// to checking.
|
|
||||||
utyp := typ
|
utyp := typ
|
||||||
if utyp.idx() == inter_typ.idx() {
|
if utyp.idx() == inter_typ.idx() {
|
||||||
// same type -> already casted to the interface
|
// same type -> already casted to the interface
|
||||||
@ -1111,40 +1109,44 @@ fn (mut table Table) does_type_implement_interface(typ Type, inter_typ Type) boo
|
|||||||
// `none` "implements" the Error interface
|
// `none` "implements" the Error interface
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
typ_sym := table.get_type_symbol(utyp)
|
typ_sym := t.get_type_symbol(utyp)
|
||||||
if typ_sym.language != .v {
|
if typ_sym.language != .v {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
mut inter_sym := table.get_type_symbol(inter_typ)
|
mut inter_sym := t.get_type_symbol(inter_typ)
|
||||||
if typ_sym.kind == .interface_ && inter_sym.kind == .interface_ {
|
if typ_sym.kind == .interface_ && inter_sym.kind == .interface_ {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
// do not check the same type more than once
|
|
||||||
if mut inter_sym.info is Interface {
|
if mut inter_sym.info is Interface {
|
||||||
for t in inter_sym.info.types {
|
// do not check the same type more than once
|
||||||
if t.idx() == utyp.idx() {
|
for tt in inter_sym.info.types {
|
||||||
|
if tt.idx() == utyp.idx() {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
// verify methods
|
||||||
imethods := if inter_sym.kind == .interface_ {
|
for imethod in inter_sym.info.methods {
|
||||||
(inter_sym.info as Interface).methods
|
if method := typ_sym.find_method(imethod.name) {
|
||||||
} else {
|
msg := t.is_same_method(imethod, method)
|
||||||
inter_sym.methods
|
if msg.len > 0 {
|
||||||
}
|
return false
|
||||||
for imethod in imethods {
|
}
|
||||||
if method := typ_sym.find_method(imethod.name) {
|
continue
|
||||||
msg := table.is_same_method(imethod, method)
|
|
||||||
if msg.len > 0 {
|
|
||||||
return false
|
|
||||||
}
|
}
|
||||||
continue
|
return false
|
||||||
}
|
}
|
||||||
return false
|
// verify fields
|
||||||
}
|
|
||||||
if mut inter_sym.info is Interface {
|
|
||||||
for ifield in inter_sym.info.fields {
|
for ifield in inter_sym.info.fields {
|
||||||
if field := table.find_field_with_embeds(typ_sym, ifield.name) {
|
if ifield.typ == voidptr_type {
|
||||||
|
// Allow `voidptr` fields in interfaces for now. (for example
|
||||||
|
// to enable .db check in vweb)
|
||||||
|
if t.struct_has_field(typ_sym, ifield.name) {
|
||||||
|
continue
|
||||||
|
} else {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if field := t.find_field_with_embeds(typ_sym, ifield.name) {
|
||||||
if ifield.typ != field.typ {
|
if ifield.typ != field.typ {
|
||||||
return false
|
return false
|
||||||
} else if ifield.is_mut && !(field.is_mut || field.is_global) {
|
} else if ifield.is_mut && !(field.is_mut || field.is_global) {
|
||||||
@ -1158,8 +1160,9 @@ fn (mut table Table) does_type_implement_interface(typ Type, inter_typ Type) boo
|
|||||||
if !inter_sym.info.types.contains(voidptr_type) {
|
if !inter_sym.info.types.contains(voidptr_type) {
|
||||||
inter_sym.info.types << voidptr_type
|
inter_sym.info.types << voidptr_type
|
||||||
}
|
}
|
||||||
|
return true
|
||||||
}
|
}
|
||||||
return true
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
// resolve_generic_to_concrete resolves generics to real types T => int.
|
// resolve_generic_to_concrete resolves generics to real types T => int.
|
||||||
@ -1325,88 +1328,3 @@ pub fn (mut t Table) generic_struct_insts_to_concrete() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn (mut table Table) type_implements_interface(utyp Type, interface_type Type) bool {
|
|
||||||
$if debug_interface_type_implements ? {
|
|
||||||
eprintln('> Table.type_implements_inteface typ: $utyp.debug() | interface_typ: $interface_type.debug()')
|
|
||||||
}
|
|
||||||
// utyp := c.unwrap_generic(typ)
|
|
||||||
typ_sym := table.get_type_symbol(utyp)
|
|
||||||
mut inter_sym := table.get_type_symbol(interface_type)
|
|
||||||
// do not check the same type more than once
|
|
||||||
if mut inter_sym.info is Interface {
|
|
||||||
for t in inter_sym.info.types {
|
|
||||||
if t.idx() == utyp.idx() {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// styp := table.type_to_str(utyp)
|
|
||||||
if utyp.idx() == interface_type.idx() {
|
|
||||||
// same type -> already casted to the interface
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
if interface_type.idx() == error_type_idx && utyp.idx() == none_type_idx {
|
|
||||||
// `none` "implements" the Error interface
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
if typ_sym.kind == .interface_ && inter_sym.kind == .interface_ {
|
|
||||||
return false
|
|
||||||
// error('cannot implement interface `$inter_sym.name` with a different interface `$styp`',
|
|
||||||
// pos)
|
|
||||||
}
|
|
||||||
imethods := if inter_sym.kind == .interface_ {
|
|
||||||
(inter_sym.info as Interface).methods
|
|
||||||
} else {
|
|
||||||
inter_sym.methods
|
|
||||||
}
|
|
||||||
// Verify methods
|
|
||||||
for imethod in imethods {
|
|
||||||
if method := typ_sym.find_method(imethod.name) {
|
|
||||||
msg := table.is_same_method(imethod, method)
|
|
||||||
if msg.len > 0 {
|
|
||||||
// sig := table.fn_signature(imethod, skip_receiver: true)
|
|
||||||
// add_error_detail('$inter_sym.name has `$sig`')
|
|
||||||
// c.error('`$styp` incorrectly implements method `$imethod.name` of interface `$inter_sym.name`: $msg',
|
|
||||||
// pos)
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
// c.error("`$styp` doesn't implement method `$imethod.name` of interface `$inter_sym.name`",
|
|
||||||
// pos)
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
// Verify fields
|
|
||||||
if mut inter_sym.info is Interface {
|
|
||||||
for ifield in inter_sym.info.fields {
|
|
||||||
if ifield.typ == voidptr_type {
|
|
||||||
// Allow `voidptr` fields in interfaces for now. (for example
|
|
||||||
// to enable .db check in vweb)
|
|
||||||
if table.struct_has_field(typ_sym, ifield.name) {
|
|
||||||
continue
|
|
||||||
} else {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if field := table.find_field_with_embeds(typ_sym, ifield.name) {
|
|
||||||
if ifield.typ != field.typ {
|
|
||||||
// exp := table.type_to_str(ifield.typ)
|
|
||||||
// got := table.type_to_str(field.typ)
|
|
||||||
// c.error('`$styp` incorrectly implements field `$ifield.name` of interface `$inter_sym.name`, expected `$exp`, got `$got`',
|
|
||||||
// pos)
|
|
||||||
return false
|
|
||||||
} else if ifield.is_mut && !(field.is_mut || field.is_global) {
|
|
||||||
// c.error('`$styp` incorrectly implements interface `$inter_sym.name`, field `$ifield.name` must be mutable',
|
|
||||||
// pos)
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
// c.error("`$styp` doesn't implement field `$ifield.name` of interface `$inter_sym.name`",
|
|
||||||
// pos)
|
|
||||||
}
|
|
||||||
inter_sym.info.types << utyp
|
|
||||||
}
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
@ -6123,7 +6123,7 @@ pub fn (mut c Checker) if_expr(mut node ast.IfExpr) ast.Type {
|
|||||||
&& sym.kind == .interface_ {
|
&& sym.kind == .interface_ {
|
||||||
// is interface
|
// is interface
|
||||||
checked_type := c.unwrap_generic(left.typ)
|
checked_type := c.unwrap_generic(left.typ)
|
||||||
should_skip = !c.table.type_implements_interface(checked_type,
|
should_skip = !c.table.does_type_implement_interface(checked_type,
|
||||||
got_type)
|
got_type)
|
||||||
} else if left is ast.TypeNode {
|
} else if left is ast.TypeNode {
|
||||||
is_comptime_type_is_expr = true
|
is_comptime_type_is_expr = true
|
||||||
|
@ -328,7 +328,7 @@ fn (mut g Gen) comp_if_cond(cond ast.Expr) bool {
|
|||||||
checked_type := g.unwrap_generic(left.typ)
|
checked_type := g.unwrap_generic(left.typ)
|
||||||
// TODO PERF this check is run twice (also in the checker)
|
// TODO PERF this check is run twice (also in the checker)
|
||||||
// store the result in a field
|
// store the result in a field
|
||||||
is_true := g.table.type_implements_interface(checked_type,
|
is_true := g.table.does_type_implement_interface(checked_type,
|
||||||
got_type)
|
got_type)
|
||||||
// true // exp_type in interface_sym.info.types
|
// true // exp_type in interface_sym.info.types
|
||||||
if cond.op == .key_is {
|
if cond.op == .key_is {
|
||||||
|
Loading…
Reference in New Issue
Block a user