E50030: types are not compatible with each other
What went wrong
You're trying to use one type where a different, incompatible type is expected. EK9 is strongly typed - types must match or be compatible via coercion.
The operators that return ONE of their operands - '?:', '<?', '>?' and the ternary 'condition <- this else that' - report this error at the operator when the operands share no type. Their result is one of the operands, so its type must be one the operands already have:
- the same type, or a subtype (including 'Any' when an operand is DECLARED as 'Any')
- one operand promoting ('#^') to the other's type Integer ?: Float -> Float
- the nearest common super class or trait KidA ?: KidB -> their super
Never an invented 'Any' and never a third type. Each of these is this error:
either <- count ?: text //Integer and String share only 'Any' shown <- letter ?: pattern //both promote to String; neither IS one known <- maybeCount ?: 0 //an 'Optional of Integer' is not an Integer
So are two types that each promote to the other ('ping ?: pong' - ambiguous), and two operands whose nearest common types are two unrelated traits (ambiguous too).
A List or Dict literal with no declared type (and a range, and a multi-source 'cat') takes the type its elements share by the same rule, plus one more step: a single type every element promotes to ([letter, pattern] is a List of String). Elements that share no type but 'Any', or share several equally near ones, are this error at the literal - never an invented 'List of Any':
mixed <- [1, "two"] //Integer and String share only 'Any' byName <- {"count": 1, "name": "two"}
A declared target supplies the element type, and any element that fits it is accepted:
//A declared target supplies the element type mixed as List of Any: [1, "two"] byName as Dict of (String, Any): {"count": 1, "name": "two"}
A target is a declared variable, property or returning variable, an assignment to one, or an enclosing declared literal. A literal passed straight as an argument has none (its type takes part in choosing an overload): declare a variable of the parameter's type and pass that.
A copy 'target :=: source' is only between objects of the same class (a copy into a Leaf through a Base-typed reference throws when the source is a different class). When the DECLARED types already prove it can never succeed - neither is the other's type, as two sibling classes 'Leaf' and 'Sibling' of one 'Base' - it is this error:
leaf :=: sibling //no object is both a Leaf and a Sibling
Worked examples
Compilable examples demonstrating this error and the correct fix:
- ek9 -q 39 (How do Integer and Float work in EK9?)
- ek9 -q 50 (How do function returns work without a return statement i...)
- ek9 -q 168 (How do I provide a fallback value when something might be...)
- ek9 -q 2061 (What type does 'a ?: b' have when a and b are different types?)
- ek9 -q 55 (How do I pass functions as delegates in EK9?)
- ek9 -q 124 (How do I group and aggregate collection data in EK9?)
[EK9 AUTOMATIC TYPE COERCION] Limited automatic promotion (one step, never chained):
- Integer → Float // OK - integers promote to floats
- Character → String // OK - characters promote to strings
- Byte → Integer // OK - but Byte does NOT reach Float (that would be two steps)
How to fix it
- Ensure types match exactly, or
- Use automatic coercion where supported
- Use explicit conversion constructors for other conversions
- For '?:', the '<?' family and the ternary, give both operands a type they share (each way is in good_forms.ek9 in the [EXAMPLE] section below):
- convert one explicitly ('$count' for a String, 'Float(count)')
- promote one explicitly with '#^' when the two types promote to each other
- assign one operand to a variable of the super or trait type wanted first
- for an 'Optional of T' use 'maybeCount.getOrDefault(0)' rather than '?:'
- For a List or Dict literal whose elements share no type, keep it to one type, or declare the element type you want: 'items as List of Any: [1, "two"]'
- For a copy between unrelated classes, copy from an object of the target's own class, or build the target from the source's values by hand (a constructor, or a copy you write yourself)
Common causes
- Assigning wrong type to variable
- Return type doesn't match declaration
- Parameter type doesn't match method signature
- Coalescing operators (?:) or a ternary with operands of different types
- A List or Dict literal mixing types that share only 'Any' with no declared element type
- A ternary in a stream 'map' returning a different type in each arm ('item > 1 <- item else "small"')
- A copy (':=:') between two sibling classes of one hierarchy
See also
Examples
Every example is compiled by the EK9 compiler: the first fails exactly as captioned, the others fix it.
Fails with E50030: types are not compatible with each other
#!ek9 defines module error.e50030.bad defines class Base as open id as Integer: 0 default operator Leaf extends Base as open default operator Sibling extends Base as open default operator defines function demo() <- rtn as Integer? text <- "42" rtn: text coalescing() -> count as Integer text as String letter as Character pattern as RegEx maybeCount as Optional of Integer <- rtn as String? either <- count ?: text //Integer and String share only 'Any' shown <- letter ?: pattern //both promote to String; neither IS one known <- maybeCount ?: 0 //an 'Optional of Integer' is not an Integer rtn: `${either} ${shown} ${known}` literals() <- rtn as String? mixed <- [1, "two"] //Integer and String share only 'Any' byName <- {"count": 1, "name": "two"} rtn: `${length mixed} ${length byName}` copies() -> leaf as Leaf sibling as Sibling leaf :=: sibling //no object is both a Leaf and a Sibling
Fixed: Give each value the type it is used as: convert it, declare the target, or copy from the same class
#!ek9 defines module error.e50030.good.fix defines class Base as open id as Integer: 0 default operator Leaf extends Base as open default operator Sibling extends Base as open default operator defines function demo() <- rtn as Integer? text <- "42" rtn: Integer(text) coalescing() -> count as Integer text as String letter as Character pattern as RegEx maybeCount as Optional of Integer <- rtn as String? either <- $count ?: text //convert one: both are a String shown <- $letter ?: $pattern //convert both to a String known <- maybeCount.getOrDefault(0) //an Optional supplies its own default rtn: `${either} ${shown} ${known}` literals() <- rtn as String? mixed as List of Any: [1, "two"] //a declared target supplies the element type byName as Dict of (String, Any): {"count": 1, "name": "two"} rtn: `${length mixed} ${length byName}` copies() -> leaf as Leaf source as Leaf leaf :=: source //a copy is between objects of the same class
Fixed: Convert explicitly
#!ek9 defines module error.e50030.good defines function demo() <- rtn as Integer? text <- "42" rtn: Integer(text)
Fixed: Give the operands a type they share, or declare the type a literal holds
#!ek9 defines module error.e50030.good.forms defines function coalescing() -> count as Integer amount as Float text as String letter as Character pattern as RegEx maybeCount as Optional of Integer <- rtn as String? //Integer promotes to Float: the result is a Float measure <- count ?: amount //Convert one operand explicitly either <- $count ?: text //A List literal takes the one type every element promotes to: a List of String shapes <- [letter, pattern] //An Optional supplies its own default known <- maybeCount.getOrDefault(0) rtn: `${measure} ${either} ${shapes} ${known}` literals() <- rtn as String? //A declared target supplies the element type mixed as List of Any: [1, "two"] byName as Dict of (String, Any): {"count": 1, "name": "two"} rtn: `${length mixed} ${length byName}`
Questions and answers
These Q&A entries show E50030 and its fix:
- Q39: How do Integer and Float work in EK9?
- Q50: How do function returns work without a return statement in EK9?
- Q55: How do I pass functions as delegates in EK9?
- Q124: How do I group and aggregate collection data in EK9?
- Q168: How do I provide a fallback value when something might be unset?
- Q235: What stream operations are available in EK9?
- Q243: How do coalescing operators handle unset values in EK9?
- Q245: How do I implement all the operators my custom type needs?
- Q254: What is the Any type and when should I use it?
- Q759: How do I assign a value and get a Boolean saying whether the new value is set?
- Q760: How do I use assign-if-unset :=? on an external object field?
- Q1144: Filter a list to items that are both positive and even.
- Q1218: Select the earlier time from two shift starts, and which one wins when they are equal?
- Q1395: Why is 'animals as List of Animal: [ Dog() ]' a List of Animal when '[ Dog() ]' on its own is a List of Dog?
- Q2061: What type does 'a ?: b' have when a and b are different types?