E06131: an alias or constrained type is made from a copy of its base value, so the base needs a public copy constructor - one parameter of exactly its own type
What went wrong
An alias or constrained type ('X as Base', with or without 'constrain as') is always made from a copy of a Base value, and that copy is made by the base's public copy constructor - a constructor with one parameter of exactly the base type. The base you named has none, or it is not public, or it is only inherited from a super type (which cannot copy the base's own fields).
How to fix it
- Give the base type a public copy constructor - one parameter of exactly the base type. Decide in it how deep the copy goes: copy each field you do not want shared (a List field copied with its own constructor, for example). There is no generated form; the copy is yours to write. The [EXAMPLE] section below shows the wrong bases and a base with its copy constructor.
- Or alias or constrain a different base. Only 3 of the 18 genera may be constrained, and the base must have a public copy constructor.
Rationale
'Squad(original)' reads as "a Squad made from this value". If the copy were made behind the scenes ('Base()' then ':=:'), it would be shallow and nobody would have written it: a List inside 'original' would still be shared, and a change to 'original' would show through the Squad. Requiring the copy constructor makes the copy visible and puts its depth in the author's hands - the same rule a range type follows (E08272). A constraint is also re-checked on the value copied in, so the copy is what the constraint guards.
Common causes
- Base type declares constructors but none of them is a copy constructor
- Base has a copy constructor that is not public
- Base inherits a copy constructor from its super type but declares none of its own
- Relying on 'default operator' (its ':=:') to make the copy - it no longer does
See also
Examples
Every example is compiled by the EK9 compiler: the first fails exactly as captioned, the others fix it.
Fails with E06131: an alias or constrained type is made from a copy of its base value, so the base needs a public copy constructor - one parameter of exactly its own type
#!ek9 defines module error.e06131.bad defines type Squad as Team WrappedGuarded as Guarded WrappedDerived as Derived defines record //A no-argument constructor and 'default operator' (so ':=:'), but no copy constructor. Team name as String: String() members as List of String: List() default operator defines class Base as open a as String: String() Base() as pure a :=? "x" Base() as pure -> other as Base a :=? String(other.a) default operator ? //Its only copy constructor is private. Guarded text as String: String() Guarded() as pure text :=? "x" private Guarded() as pure -> other as Guarded text :=? String(other.text) default operator ? //Inherits Base's copy constructor, which copies a Base - not a Derived. Derived is Base extra as String: String() Derived() as pure super() extra :=? "y" default operator ?
Fixed: Give the base a public copy constructor, copying as deeply as it needs
#!ek9 defines module error.e06131.good defines type Squad as Team defines record Team name as String: String() members as List of String: List() Team() name: String() members: List() //The copy constructor: a new list, so a Squad made from a Team does not share its members. Team() -> other as Team name: String(other.name) members: List() members += other.members default operator