v icon indicating copy to clipboard operation
v copied to clipboard

Wrong type is inferred in generic

Open alexferl opened this issue 2 years ago • 1 comments

Describe the bug

Passing &Item[K, V] to V in the Interface doesn't infer the right type.

Expected Behavior

Should correctly infer the type as &Item[K, V] and not as int.

Current Behavior

v run main.v
cache.v:63:14: error: `int` has no property `value`
   61 |     }
   62 |
   63 |     return item.value, true
      |                 ~~~~~
   64 | }
   65 |
cache.v:72:19: error: cannot use `&Item[string, int]` as `int` in argument 2 to `Interface<K,Item>[string, Item[string, int]].set`
   70 |     }
   71 |     item := new_item(key, val)
   72 |     c.cache.set(key, item)
      |                      ~~~~
   73 | }
   74 |
cache.v:37:3: error: can not find method `get` on `Simple[string, int]`, needed for interface: `Interface<K,Item>`
   35 | fn new_options[K, V]() &CacheOptions[K, V] {
   36 |     return &CacheOptions[K, V]{
   37 |         cache: new_simple[K, &Item[K, V]]()
      |         ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   38 |     }
   39 | }

Reproduction Steps

module main

import sync
import time

pub interface Interface[K, V] {
	get(key K) (V, bool)
	set(key K, val V)
}

pub struct Item[K, V] {
	key   K
	value V
}

fn new_item[K, V](key K, val V) &Item[K, V] {
	return &Item[K, V]{
		key: key
		value: val
	}
}

pub struct Cache[K, V] {
mut:
	cache Interface[K, &Item[K, V]]
	mu    sync.Mutex
}

pub type CacheOption[K, V] = fn (o &CacheOptions[K, V])

struct CacheOptions[K, V] {
	cache Interface[K, &Item[K, V]]
}

fn new_options[K, V]() &CacheOptions[K, V] {
	return &CacheOptions[K, V]{
		cache: new_simple[K, &Item[K, V]]()
	}
}

pub fn new[K, V](opts ...CacheOption[K, V]) &Cache[K, V] {
	mut o := new_options[K, V]()
	for f in opts {
		f[K, V](o)
	}
	cache := &Cache[K, V]{
		cache: o.cache
	}
	return cache
}

pub fn (mut c Cache[K, V]) get(key K) (V, bool) {
	c.mu.@lock()
	defer {
		c.mu.unlock()
	}
	item, ok := c.cache.get(key)

	if !ok {
		return Item[K, V]{}.value, false
	}

	return item.value, true
}

pub fn (mut c Cache[K, V]) set(key K, val V) {
	c.mu.@lock()
	defer {
		c.mu.unlock()
	}
	item := new_item(key, val)
	c.cache.set(key, item)
}

pub struct Simple[K, V] {
	mut:
	items map[K]&Entry[V]
}

struct Entry[V] {
	val        V
	created_at time.Time
}

pub fn new_simple[K, V]() &Simple[K, V] {
	return &Simple[K, V]{
		items: map[K]&Entry[V]{}
	}
}

pub fn (mut s Simple[K, V]) set(k K, v V) {
	s.items[k] = &Entry[V]{
		val: v
		created_at: time.now()
	}
}

pub fn (s Simple[K, V]) get(k K) (V, bool) {
	got := s.items[k] or { return Entry[V]{}.val, false }
	return got.val, true
}

fn main() {
	mut c := new[string, int]()
	c.set('a', 1)
	v, ok := c.get('a')

	println('${v} ${ok}')
}

Possible Solution

No response

Additional Information/Context

No response

V version

V 0.4.0 ecca3b1

Environment details (OS name and version, etc.)

V full version: V 0.4.0 7d6fd9d.ecca3b1
OS: macos, macOS, 13.4.1, 22F770820d
Processor: 12 cpus, 64bit, little endian, Apple M2 Pro

getwd: /Users/alex/dev/container
vexe: /opt/homebrew/Cellar/vlang/0.4/libexec/v
vexe mtime: 2023-08-02 03:18:51

vroot: OK, value: /opt/homebrew/Cellar/vlang/0.4/libexec
VMODULES: OK, value: /Users/alex/.vmodules
VTMP: OK, value: /tmp/v_501

Git version: git version 2.39.2 (Apple Git-143)
Git vroot status: weekly.2023.30-59-gecca3b15
.git/config present: true

CC version: Apple clang version 14.0.3 (clang-1403.0.22.14.1)
thirdparty/tcc status: thirdparty-macos-arm64 a668e5a0

alexferl avatar Aug 02 '23 03:08 alexferl

The issue still persists.

Delta456 avatar Aug 03 '24 18:08 Delta456