checker: do not allow defining methods on types from other modules

pull/5102/head
Alexander Medvednikov 2020-05-28 15:23:17 +02:00
parent 1d0ebfb691
commit 01dbb25a37
8 changed files with 32 additions and 16 deletions

View File

@ -254,7 +254,8 @@ pub fn (mut v Builder) cc_msvc() {
// Not all of these are needed (but the compiler should discard them if they are not used)
// these are the defaults used by msbuild and visual studio
mut real_libs := ['kernel32.lib', 'user32.lib', 'advapi32.lib']
sflags := v.get_os_cflags().msvc_string_flags()
//sflags := v.get_os_cflags().msvc_string_flags()
sflags := msvc_string_flags(v.get_os_cflags())
real_libs << sflags.real_libs
inc_paths := sflags.inc_paths
lib_paths := sflags.lib_paths
@ -359,7 +360,8 @@ mut:
other_flags []string
}
fn (cflags []cflag.CFlag) msvc_string_flags() MsvcStringFlags {
//pub fn (cflags []CFlag) msvc_string_flags() MsvcStringFlags {
pub fn msvc_string_flags(cflags []cflag.CFlag) MsvcStringFlags {
mut real_libs := []string{}
mut inc_paths := []string{}
mut lib_paths := []string{}
@ -405,3 +407,4 @@ fn (cflags []cflag.CFlag) msvc_string_flags() MsvcStringFlags {
other_flags: other_flags
}
}

View File

@ -32,15 +32,15 @@ pub fn (cf &CFlag) format() string {
}
// TODO: implement msvc specific c_options_before_target and c_options_after_target ...
fn (cflags []CFlag) c_options_before_target_msvc() string {
pub fn (cflags []CFlag) c_options_before_target_msvc() string {
return ''
}
fn (cflags []CFlag) c_options_after_target_msvc() string {
pub fn (cflags []CFlag) c_options_after_target_msvc() string {
return ''
}
fn (cflags []CFlag) c_options_before_target() string {
pub fn (cflags []CFlag) c_options_before_target() string {
// -I flags, optimization flags and so on
mut args := []string{}
for flag in cflags {
@ -51,7 +51,7 @@ fn (cflags []CFlag) c_options_before_target() string {
return args.join(' ')
}
fn (cflags []CFlag) c_options_after_target() string {
pub fn (cflags []CFlag) c_options_after_target() string {
// -l flags (libs)
mut args := []string{}
for flag in cflags {
@ -62,7 +62,7 @@ fn (cflags []CFlag) c_options_after_target() string {
return args.join(' ')
}
fn (cflags []CFlag) c_options_without_object_files() string {
pub fn (cflags []CFlag) c_options_without_object_files() string {
mut args := []string{}
for flag in cflags {
if flag.value.ends_with('.o') || flag.value.ends_with('.obj') {
@ -73,7 +73,7 @@ fn (cflags []CFlag) c_options_without_object_files() string {
return args.join(' ')
}
fn (cflags []CFlag) c_options_only_object_files() string {
pub fn (cflags []CFlag) c_options_only_object_files() string {
mut args := []string{}
for flag in cflags {
if flag.value.ends_with('.o') || flag.value.ends_with('.obj') {

View File

@ -731,7 +731,7 @@ pub fn (mut c Checker) call_method(mut call_expr ast.CallExpr) table.Type {
table.FnType { ret_type = it.func.return_type }
else { ret_type = arg_type }
}
call_expr.return_type = c.table.find_or_register_array(ret_type, 1)
call_expr.return_type = c.table.find_or_register_array(ret_type, 1, c.mod)
} else if method_name == 'clone' {
// need to return `array_xxx` instead of `array`
// in ['clone', 'str'] {
@ -1415,7 +1415,8 @@ pub fn (mut c Checker) array_init(mut array_init ast.ArrayInit) table.Type {
idx := c.table.find_or_register_array_fixed(elem_type, array_init.exprs.len, 1)
array_init.typ = table.new_type(idx)
} else {
idx := c.table.find_or_register_array(elem_type, 1)
sym := c.table.get_type_symbol(elem_type)
idx := c.table.find_or_register_array(elem_type, 1, sym.mod)
array_init.typ = table.new_type(idx)
}
array_init.elem_type = elem_type
@ -2268,7 +2269,7 @@ pub fn (mut c Checker) index_expr(mut node ast.IndexExpr) table.Type {
// fixed_array[1..2] => array
if typ_sym.kind == .array_fixed {
elem_type := c.table.value_type(typ)
idx := c.table.find_or_register_array(elem_type, 1)
idx := c.table.find_or_register_array(elem_type, 1, c.mod)
return table.new_type(idx)
}
}
@ -2438,6 +2439,11 @@ fn (mut c Checker) fn_decl(it ast.FnDecl) {
// if sym.has_method(it.name) {
// c.warn('duplicate method `$it.name`', it.pos)
// }
// Do not allow to modify types from other modules
if sym.mod != c.mod && !c.is_builtin_mod && sym.mod != '' { // TODO remove != ''
c.warn('cannot define methods on types from other modules (' + 'current module is `$c.mod`, `$sym.name` is from `$sym.mod`)',
it.pos)
}
}
if it.language == .v {
// Make sure all types are valid

View File

@ -27,9 +27,10 @@ fn (mut p Parser) array_init() ast.ArrayInit {
if p.tok.kind in [.name, .amp] && p.tok.line_nr == line_nr {
elem_type_pos = p.tok.position()
elem_type = p.parse_type()
sym := p.table.get_type_symbol(elem_type)
// this is set here becasue its a known type, others could be the
// result of expr so we do those in checker
idx := p.table.find_or_register_array(elem_type, 1)
idx := p.table.find_or_register_array(elem_type, 1, sym.mod)
array_type = table.new_type(idx)
has_type = true
}

View File

@ -159,10 +159,12 @@ fn (mut p Parser) fn_decl() ast.FnDecl {
// TODO: talk to alex, should mut be parsed with the type like this?
// or should it be a property of the arg, like this ptr/mut becomes indistinguishable
rec_type = p.parse_type_with_mut(rec_mut)
/*
sym := p.table.get_type_symbol(rec_type)
if sym.mod != p.mod && sym.mod != '' {
p.error('cannot define methods on types from other modules (current module is `$p.mod`, `$sym.name` is from `$sym.mod`)')
if sym.mod != p.mod { // && sym.mod != '' {
p.warn('cannot define methods on types from other modules (current module is `$p.mod`, `$sym.name` is from `$sym.mod`)')
}
*/
if is_amp && rec_mut {
p.error('use `(mut f Foo)` or `(f &Foo)` instead of `(mut f &Foo)`')
}

View File

@ -13,6 +13,7 @@ pub fn (mut p Parser) parse_array_type() table.Type {
p.next()
p.check(.rsbr)
elem_type := p.parse_type()
//sym := p.table.get_type_symbol(elem_type)
idx := p.table.find_or_register_array_fixed(elem_type, size, 1)
return table.new_type(idx)
}
@ -29,7 +30,8 @@ pub fn (mut p Parser) parse_array_type() table.Type {
p.check(.rsbr)
nr_dims++
}
idx := p.table.find_or_register_array(elem_type, nr_dims)
sym := p.table.get_type_symbol(elem_type)
idx := p.table.find_or_register_array(elem_type, nr_dims, sym.mod)
return table.new_type(idx)
}

View File

@ -189,6 +189,7 @@ fn (mut p Parser) struct_decl() ast.StructDecl {
// with the real struct type info parsed from builtin
ret = p.table.register_builtin_type_symbol(t)
} else {
// println('reg type symbol $name mod=$p.mod')
ret = p.table.register_type_symbol(t)
}
if ret == -1 {

View File

@ -325,7 +325,7 @@ pub fn (mut t Table) find_or_register_map(key_type, value_type Type) int {
return t.register_type_symbol(map_typ)
}
pub fn (mut t Table) find_or_register_array(elem_type Type, nr_dims int) int {
pub fn (mut t Table) find_or_register_array(elem_type Type, nr_dims int, mod string) int {
name := t.array_name(elem_type, nr_dims)
// existing
existing_idx := t.type_idxs[name]
@ -341,6 +341,7 @@ pub fn (mut t Table) find_or_register_array(elem_type Type, nr_dims int) int {
elem_type: elem_type
nr_dims: nr_dims
}
mod: mod
}
return t.register_type_symbol(array_type)
}