Skip to content

Explicitly set optional types conflict with try? in calls to resolver #40

Open
@yakovmanshin

Description

@yakovmanshin

The following expression looks valid but always returns nil:

let retrievedValue: Int? = try? resolver.value(for: key)

A number of factors contribute to such an outcome:

  • FeatureFlagResolver’s value(for:) method uses generics, and therefore cannot take advantage of Swift’s type inference—the output type should be specified externally;
  • The same method throws, and calls to it require try, try?, or try!, where try?, which returns an optional, is nearly always the preferred option;
  • At the same time, feature flag values themselves cannot be optional: before returning a retrieved value, the resolver validates it, and throws FeatureFlagResolverError.optionalValuesNotAllowed is it’s an optional;
  • In the expression above, Int? is used to denote try?’s return type (always an optional) but is interpreted by the resolver as the type of the feature flag value;
  • The resolver sees an optional type and throws FeatureFlagResolverError.optionalValuesNotAllowed which is then silenced by try? (i.e. the error is replaced with nil).

This issue only occurs when using try?, and attempting to replace it with a do / try / catch block to inspect the error (see below) does not help in reproducing it: inside a do block, try doesn’t return an optional, so the resolver is not confused about the type.

do {
    let retrievedValue: Int = try resolver.value(for: key)
} catch {
    print(error)
}

Right now, I see no clear solution to the problem, which allows preserve both generics and explicit errors in value(for:).

The following code works properly (and it’s actually used in FeatureFlag). However, the fix is super unintuitive.

let retrievedValue = try? resolver.value(for: key) as Int

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn’t workinghelp wantedExtra attention is needed

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions