Can a generic class have a non-generic nested type?

Is there a way to do something like the following where Bar is namespaced to Foo, but not generic
(Bar doesn't use G in any way)

class Foo<G> where G:CustomStringConvertible {
    struct Bar {
        var something:Bool
    }
}

var test = Foo.Bar(something:true)

this errors with 'Generic parameter 'G' could not be inferred', but I want to say 'ignore G - you don't need it!'

I can pull Bar out of Foo and make it independent - but the namespacing is useful and meaningful in the case where I'm wanting to use it.

1 Like

Define Bar elsewhere and use a typealias:

struct Bar_ {
  var something:Bool
};
class Foo<G> where G:CustomStringConvertible { 
  typealias Bar = Bar_
}
var test = Foo.Bar(something: true)

Edit: also note that you shouldn't use CustomStringConvertible as a constraint, all values can be printed using string interpolation.

1 Like

that doesn't work unfortunately; I still get 'Generic parameter 'G' could not be inferred'

re the CustomStringConvertible constraint; I'm not actually using that - it is just the first thing that sprang to mind for a minimal example.

Oh.
I tested it, using an old version of the repl, which must differ sufficiently from the main compiler.
perhaps this will work?

struct Bar_ {}
class Foo<G> {}
// arbitrary constant type
extension Foo where G == Bool { 
  typealias Bar = Bar_
}

I wonder if it would be possible for the compiler to recognize that the nested type doesn't depend on the generic parameter, and therefore treat the nested type as non-generic. That would also mean that you'd have to be permitted to say Foo.Bar without being required to specify G.

struct Bar_ {}
class Foo {}
// arbitrary constant type
extension Foo where G == Bool {
typealias Bar = Bar_
}

No joy with that either I'm afraid. (I'm using Xcode 12.5.1)
Same error (unable to infer G)

It seems that there just isn't such a thing as Foo. only Foo<specify the generic>

Any other likely workarounds?

I'm not thinking of any, sorry. :slightly_frowning_face:

thanks for trying

This would require seeing all method bodies on the class, which might not even be possible if there are extensions that add new methods from outside the module, or in other source files. It's not worth the complexity. If you don't want a nested type to capture generic arguments, it should not be a nested type.

8 Likes

Throw Any in front.

It is a terrible solution, but not as terrible as the language not having the feature. :stuck_out_tongue_closed_eyes:

My prediction is that this will get solved along with nested protocols and their inverse.

public enum AnyOptional {
  public class UnwrapError: Error {
    public init() { }
  }
}
public enum AnyCaseIterable<Case> {
  public enum AllCasesError: Error {
    /// No `AllCases.Index` corresponds to this case.
    case noIndex(Case)
  }
}

@Jessy can you elaborate? I'm afraid I'm not following...

Terms of Service

Privacy Policy

Cookie Policy