V: Can't pass literal int into function expecting a sum type that includes int

Created on 8 Oct 2020  路  7Comments  路  Source: vlang/v

V version: V full version: V 0.1.29 35a8346.30588e4
OS: linux, Debian GNU/Linux 9.13 (stretch) (VM)

What did you do?

$ cat microkanren-buggy2.v
// Steve Phillips / elimisteve
// 2020.10.05
module main

type Var = int | string

fn main() {
    println(is_num(5))
    println(is_num('Hello'))
}

fn is_num(v Var) bool {
    match v {
        int { return true }
        else { return false }
    }
}

$ v run microkanren-buggy2.v

What did you expect to see?

5
Hello

What did you see instead?

$ v run microkanren-buggy2.v
microkanren-buggy2.v:8:10: error: cannot use type `any_int` as type `Var` in argument 1 to `is_num`
    6 | 
    7 | fn main() {
    8 |     println(is_num(5))
      |             ~~~~~~~~~
    9 |     println(is_num('Hello'))
   10 | }

I'll note that this works for strings just fine; so far I just see ints as problematic when combined with sum types in this way.

Bug

Most helpful comment

As far as I know, the reason why this fails/hasn't been fixed yet is because of this case:

type Var = u16 | u64

fn is_num(v Var) bool {
    match v {
        u16 { return true }
        else { return false }
    }
}

println(is_num(5))

Should that print true or false? There is no way to tell unless you explicitly cast the literal into either type.

I guess one option would be automatically making literals int if that's a valid subtype, and require an explicit cast otherwise

All 7 comments

If you explicitly type cast it to int i.e. do println(is_num(int(5))) then it will work.

As far as I know, the reason why this fails/hasn't been fixed yet is because of this case:

type Var = u16 | u64

fn is_num(v Var) bool {
    match v {
        u16 { return true }
        else { return false }
    }
}

println(is_num(5))

Should that print true or false? There is no way to tell unless you explicitly cast the literal into either type.

I guess one option would be automatically making literals int if that's a valid subtype, and require an explicit cast otherwise

@Delta456 Yes, or doing

five := 5
println(is_num(five))

also works, thanks... but this is still a bug :slightly_smiling_face: .

@spaceface777 Good point, and yes that sounds good.

I guess one option would be automatically making literals int if that's a valid subtype, and require an explicit cast otherwise

I think if an integer literal could be more than one of a sum type's elements, then it should require a cast. If there's only one possible element match then it should work without a cast.

Speaking with @danieldaeschle about potential fixes for this issue (and #6748), we came up with the following solution:

  • if the only integer subtype of a sumtype is int (or if the only float subtype of a sumtype is f64), then cast literals to those types automatically
  • if not, require a cast, and show a better error message (i.e. "error: sumtype has multiple integer variants, please cast the literal to a specific integer type")

We thought it would offer a nice balance between convenience and explicitness, any suggestions?

@spaceface777 Sounds perfect :+1:

Was this page helpful?
0 / 5 - 0 ratings

Related issues

arg2das picture arg2das  路  3Comments

PavelVozenilek picture PavelVozenilek  路  3Comments

oleg-kachan picture oleg-kachan  路  3Comments

shouji-kazuo picture shouji-kazuo  路  3Comments

ArcDrake picture ArcDrake  路  3Comments