grain icon indicating copy to clipboard operation
grain copied to clipboard

Compiler warning if two types have any field names in common

Open cician opened this issue 4 years ago • 4 comments

The compiler emits a warning for the following program. Unless there's something fundamental I don't understand about Grain's type system, I think the two record types should coexist peacefully and stay independent of each other if I use explicit type annotations.

record A {
  a: Number
}

record B {
  a: Number,
  b: Number
}

let a = {
  a: 1
} : A

let b = {
  a: 1,
  b: 2
} : B

let c = b.a // Warning: a belongs to several types: B A The first one was selected. Please disambiguate if this is wrong.

Same happens in this case:

let f = (x: B) => {
  let c = b.a
}

cician avatar Jul 10 '21 19:07 cician

To follow up on this, is there any way to get this warning to go away? I ran into this same situation and have tried disambiguating in various ways but the warning still shows

alex-snezhko avatar Aug 13 '22 03:08 alex-snezhko

To follow up on this, is there any way to get this warning to go away? I ran into this same situation and have tried disambiguating in various ways but the warning still shows

you can do

{ recordInfo } : Type

which should prevent the warning.

spotandjake avatar Aug 13 '22 03:08 spotandjake

This project looks really interesting!

you can do { recordInfo } : Type which should prevent the warning

Could you clarify further? Considering the following code:

record Person { id: Number }
record Company { id: Number }

let person = { id: 123 }: Person
let company = { id: 123 }: Company

print(person.id)
print(company.id) // For some reason this gives a warning even though the preceding line is considered fine

I'm guessing it's a compiler bug that person.id is allowed whereas company.id is not. Is that right?

And assuming so it's possible to work around by disambiguating manually, what's the correct syntax for the final line in this sample?

SteveSandersonMS avatar May 02 '23 22:05 SteveSandersonMS

The name of this issue has been changed because this isnt exclusive to records.

Record Issue

The initial issue references Records which can be handled just by adding a : TypeName after the record definition.

as @SteveSandersonMS referenced above with print(company.id) this scenario there does not seem to be a way to silence the error.

Enums

Enums have the same issue take the example program here:

module Test

enum NodeA {
  Same, // Same
  DiffB,
}
enum NodeB {
  Same, // Same
  DiffA,
}
let a = Same: NodeB
match (a) {
  DiffA => void,
  Same => void,
}

as can be seen in the sample program we are able to dissambiguate at the deffinition the same way we do for records Same: NodeB but we are not able to dissambiguate at the match statement leaving a warning on the line Same => void.

A note is lets say you had a program like:

enum Status {
  Success,
  Failure,
}
let x = Success
match (x) {
  Sucess => void,
  Failure => void,
}

you would get an error on the line Failure => void because of the exception Failure in pervasives.

Work Arrounds

for now in the case of records with the same fields and defining enums you can just append : TypeName after initializaton as stated and displayed above. As per pattern matching there is not a work arround so if you want the error to go away unfortunately you will have to change the name of your variant until this is fixed.

spotandjake avatar May 27 '23 22:05 spotandjake

Fixed in #2072

ospencer avatar Apr 05 '24 20:04 ospencer