E10032: a constructor the generic uses on T from a pure scope ('T()', or the copy constructor 'T(T)' a for-range uses) must be pure on the type used to parameterise it
What went wrong
The generic type uses a constructor of T from a PURE context, but the type used to parameterise it has no PURE constructor to serve it. Two uses do this:
- 'T()' called inside a pure method, constructor or function of the generic
- a for-range over T ('for item in first ... last') inside a pure scope - the range builds its counter as T(first) and each loop variable as T(counter), so it calls T's copy constructor T(T)
A pure generic can only call pure operations, and that requirement passes through to the type it is parameterised with.
How to fix it
- Mark the constructor of your type that the generic uses as pure - its no-argument constructor for 'T()', its copy constructor for a range (the [EXAMPLE] section below: a PureNoArgThing whose no-argument constructor is 'as pure', parameterising a pure PureHolder)
- Or parameterise with a type whose constructor is already pure.
- Or, if the generic does not need to be pure, drop 'as pure' from the generic operation that calls 'T()' or ranges over T.
Rationale
Purity in EK9 is checked, not advisory. A pure generic promises it mutates nothing; constructing T is part of what it does, so T's constructor has to keep that promise too, or the guarantee would be false after monomorphisation. A for-range is no exception: its copy constructor is a call like any other (on a concrete range type the same rule is E08130).
Common causes
- The type has a public no-argument constructor that is not marked pure
- The type's copy constructor is not pure and a pure generic ranges over T
- Parameterising a pure generic with a type designed for a non-pure context
See also
Examples
Every example is compiled by the EK9 compiler: the first fails exactly as captioned, the others fix it.
Fails with E10032: a constructor the generic uses on T from a pure scope ('T()', or the copy constructor 'T(T)' a for-range uses) must be pure on the type used to parameterise it
#!ek9 defines module error.e10032.bad defines class PureHolder of type T item as T? PureHolder() as pure item :=? T() PureHolder() as pure -> initial as T item :=? initial default operator ? NonPureNoArgThing content as String? NonPureNoArgThing() content :=? "default" default operator ? defines function tryNonPureNoArg() held <- PureHolder() of NonPureNoArgThing require held?
Fixed: Mark the no-argument constructor pure
#!ek9 defines module error.e10032.good defines class PureHolder of type T item as T? PureHolder() as pure item :=? T() PureHolder() as pure -> initial as T item :=? initial default operator ? PureNoArgThing content as String? PureNoArgThing() as pure content :=? "default" default operator ? defines function tryPureNoArg() held <- PureHolder() of PureNoArgThing require held?