Would it not be possible to have anonymous union types that convert to a broader union type automatically?
This would avoid partially instanciated enum while allowing the same kind of uses, no? template makeError(code: int): enum of Le: string = result.Le = codeToString(code) proc myFunction(): Either[string, int] = let code = readFile(myVar) if isError(code): return makeError(code) return Either.Ri(myVar.toInt()) Run Also, why not completely anonymous union types based on the different branch types? type ErrorString = string template makeError(code: int): ErrorString = result = codeToString(code) proc myFunction(): enum[ErrorString, int] = let code = readFile(myVar) if isError(code): return makeError(code) return myVar.toInt() Run The discriminant would then just be the type information.