[Runtime] Handle incomplete class metadata in _checkGenericRequirements.

When constructing the metadata for a type Gen<T : Super>
where Super is a superclass constraint, the generic argument K at which
the metadata for Gen is being instantiated is verified to be a subclass
of Super via _checkGenericRequirements.

Previously, that check was done using swift_dynamicCastMetatype.  That
worked for the most part but provided an incorrect answer if the
metadata for K was not yet complete.  These classes are incomplete more
often thanks to __swift_instantiateConcreteTypeFromMangledNameAbstract.

That issue occurred concretely in the following case:

  Framework with Library Evolution enabled:

    open class Super { ... }
    public struct Gen<T : Super> {
    }

  Target in a different resilience domain from that framework:

    class Sub : Super {
      var gen: Gen<Sub>?
    }

Here, the mechanism for checking whether the generic argument K at which
the metadata for Gen is being instantiated handles the case where K's
metadata is incomplete.  At worst, every superclass name from super(K)
up to Super are demangled to instantiate metadata.  A number of faster
paths are included as well.

rdar://problem/60790020
This commit is contained in:
Nate Chandler
2020-04-03 13:28:54 -07:00
parent 5f8fece911
commit 2863f1964d
20 changed files with 588 additions and 22 deletions

View File

@@ -796,6 +796,10 @@ SWIFT_CC(swift)
SWIFT_RUNTIME_STDLIB_INTERNAL
const Metadata *_swift_class_getSuperclass(const Metadata *theClass);
SWIFT_CC(swift)
SWIFT_RUNTIME_STDLIB_INTERNAL MetadataResponse
getSuperclassMetadata(MetadataRequest request, const ClassMetadata *self);
#if !NDEBUG
/// Verify that the given metadata pointer correctly roundtrips its
/// mangled name through the demangler.

View File

@@ -2735,19 +2735,14 @@ initGenericObjCClass(ClassMetadata *self, size_t numFields,
#endif
SWIFT_CC(swift)
static std::pair<MetadataDependency, const ClassMetadata *>
getSuperclassMetadata(ClassMetadata *self, bool allowDependency) {
SWIFT_RUNTIME_STDLIB_INTERNAL MetadataResponse
getSuperclassMetadata(MetadataRequest request, const ClassMetadata *self) {
// If there is a mangled superclass name, demangle it to the superclass
// type.
const ClassMetadata *super = nullptr;
if (auto superclassNameBase = self->getDescription()->SuperclassType.get()) {
StringRef superclassName =
Demangle::makeSymbolicMangledNameStringRef(superclassNameBase);
SubstGenericParametersFromMetadata substitutions(self);
MetadataRequest request(allowDependency
? MetadataState::NonTransitiveComplete
: /*FIXME*/ MetadataState::Abstract,
/*non-blocking*/ allowDependency);
MetadataResponse response =
swift_getTypeByMangledName(request, superclassName,
substitutions.getGenericArgs(),
@@ -2765,22 +2760,42 @@ getSuperclassMetadata(ClassMetadata *self, bool allowDependency) {
superclassName.str().c_str());
}
return response;
} else {
return MetadataResponse();
}
}
SWIFT_CC(swift)
static std::pair<MetadataDependency, const ClassMetadata *>
getSuperclassMetadata(ClassMetadata *self, bool allowDependency) {
MetadataRequest request(allowDependency ? MetadataState::NonTransitiveComplete
: /*FIXME*/ MetadataState::Abstract,
/*non-blocking*/ allowDependency);
auto response = getSuperclassMetadata(request, self);
auto *superclass = response.Value;
if (!superclass)
return {MetadataDependency(), nullptr};
const ClassMetadata *second;
#if SWIFT_OBJC_INTEROP
if (auto objcWrapper = dyn_cast<ObjCClassWrapperMetadata>(superclass)) {
second = objcWrapper->Class;
} else {
second = cast<ClassMetadata>(superclass);
}
#else
second = cast<ClassMetadata>(superclass);
#endif
// If the request isn't satisfied, we have a new dependency.
if (!request.isSatisfiedBy(response.State)) {
assert(allowDependency);
return {MetadataDependency(superclass, request.getState()),
cast<ClassMetadata>(superclass)};
return {MetadataDependency(superclass, request.getState()), second};
}
#if SWIFT_OBJC_INTEROP
if (auto objcWrapper = dyn_cast<ObjCClassWrapperMetadata>(superclass))
superclass = objcWrapper->Class;
#endif
super = cast<ClassMetadata>(superclass);
}
return {MetadataDependency(), super};
return {MetadataDependency(), second};
}
// Suppress diagnostic about the availability of _objc_realizeClassFromSwift.

View File

@@ -665,6 +665,137 @@ swift::_searchConformancesByMangledTypeName(Demangle::NodePointer node) {
return nullptr;
}
static MetadataState
tryGetCompleteMetadataNonblocking(const Metadata *metadata) {
return swift_checkMetadataState(
MetadataRequest(MetadataState::Complete, /*isNonBlocking*/ true),
metadata)
.State;
}
template <typename HandleObjc>
bool isSwiftClassMetadataSubclass(const ClassMetadata *subclass,
const ClassMetadata *superclass,
HandleObjc handleObjc) {
assert(subclass);
assert(superclass);
MetadataState subclassState = tryGetCompleteMetadataNonblocking(subclass);
do {
if (subclassState == MetadataState::Complete) {
// The subclass metadata is complete. That means not just that its
// Superclass field is valid, but that the Superclass field of the
// referenced class metadata is valid, and the Superclass field of the
// class metadata referenced there, and so on transitively.
//
// Scan the superclass chains in the ClassMetadata looking for a match.
while ((subclass = subclass->Superclass)) {
if (subclass == superclass)
return true;
}
return false;
}
if (subclassState == MetadataState::NonTransitiveComplete) {
// The subclass metadata is complete, but, unlike above, not transitively.
// Its Superclass field is valid, so just read that field to get to the
// superclass to proceed to the next step.
subclass = subclass->Superclass;
if (subclass->isPureObjC()) {
return handleObjc(subclass, superclass);
}
subclassState = tryGetCompleteMetadataNonblocking(subclass);
} else {
// The subclass metadata is either LayoutComplete or Abstract, so the
// Superclass field is not valid. To get to the superclass, make the
// expensive call to getSuperclassMetadata which demangles the superclass
// name from the nominal type descriptor to get the metadata for the
// superclass.
MetadataRequest request(MetadataState::Complete,
/*non-blocking*/ true);
auto response = getSuperclassMetadata(request, subclass);
auto newMetadata = response.Value;
if (auto newSubclass = dyn_cast<ClassMetadata>(newMetadata)) {
subclass = newSubclass;
subclassState = response.State;
} else {
return handleObjc(newMetadata, superclass);
}
}
if (subclass == superclass)
return true;
} while (subclass);
return false;
}
// Whether the provided `subclass` is metadata for a subclass* of the superclass
// whose metadata is specified.
//
// The function is robust against incomplete metadata for both subclass and
// superclass. In the worst case, each intervening class between subclass and
// superclass is demangled. Besides that slow path, there are a number of fast
// paths:
// - both classes are ObjC: swift_dynamicCastMetatype
// - Complete subclass metadata: loop over Superclass fields
// - NonTransitiveComplete: read the Superclass field once
//
// * A non-strict subclass; that is, given a class X, isSubclass(X.self, X.self)
// is true.
static bool isSubclass(const Metadata *subclass, const Metadata *superclass) {
assert(subclass);
assert(superclass);
assert(subclass->isAnyClass());
assert(superclass->isAnyClass());
if (subclass == superclass)
return true;
if (!isa<ClassMetadata>(subclass)) {
if (!isa<ClassMetadata>(superclass)) {
// Only ClassMetadata can be incomplete; when the class metadata is not
// ClassMetadata, just use swift_dynamicCastMetatype.
return swift_dynamicCastMetatype(subclass, superclass);
} else {
// subclass is ObjC, but superclass is not; since it is not possible for
// any ObjC class to be a subclass of any Swift class, this subclass is
// not a subclass of this superclass.
return false;
}
}
const ClassMetadata *swiftSubclass = cast<ClassMetadata>(subclass);
if (auto *objcSuperclass = dyn_cast<ObjCClassWrapperMetadata>(superclass)) {
// Walk up swiftSubclass's ancestors until we get to an ObjC class, then
// kick over to swift_dynamicCastMetatype.
return isSwiftClassMetadataSubclass(
swiftSubclass, objcSuperclass->Class,
[](const Metadata *intermediate, const Metadata *superclass) {
// Intermediate is an ObjC class, and superclass is an ObjC class;
// as above, just use swift_dynamicCastMetatype.
return swift_dynamicCastMetatype(intermediate, superclass);
});
return false;
}
if (isa<ForeignClassMetadata>(superclass)) {
// superclass is foreign, but subclass is not (if it were, the above
// !isa<ClassMetadata> condition would have been entered). Since it is not
// possible for any Swift class to be a subclass of any foreign superclass,
// this subclass is not a subclass of this superclass.
return false;
}
auto swiftSuperclass = cast<ClassMetadata>(superclass);
return isSwiftClassMetadataSubclass(swiftSubclass, swiftSuperclass,
[](const Metadata *, const Metadata *) {
// Because (1) no ObjC classes inherit
// from Swift classes and (2)
// `superclass` is not ObjC, if some
// ancestor of `subclass` is ObjC, then
// `subclass` cannot descend from
// `superclass` (otherwise at some point
// some ObjC class would have to inherit
// from a Swift class).
return false;
});
}
bool swift::_checkGenericRequirements(
llvm::ArrayRef<GenericRequirementDescriptor> requirements,
SmallVectorImpl<const void *> &extraArguments,
@@ -738,11 +869,8 @@ bool swift::_checkGenericRequirements(
substGenericParam, substWitnessTable).getMetadata();
if (!baseType) return true;
// Check whether it's dynamically castable, which works as a superclass
// check.
// FIXME: We should be explicitly checking the superclass, so we
// don't require the subject type to be complete.
if (!swift_dynamicCastMetatype(subjectType, baseType)) return true;
if (!isSubclass(subjectType, baseType))
return true;
continue;
}

View File

@@ -0,0 +1,5 @@
#import <Foundation/Foundation.h>
@interface Subclass : NSObject
@end

View File

@@ -0,0 +1,8 @@
#import <Foundation/Foundation.h>
@interface Subclass : NSObject
@end
@implementation Subclass
@end

View File

@@ -0,0 +1,4 @@
#import <Foundation/Foundation.h>
@interface Superclass : NSObject
@end

View File

@@ -0,0 +1,7 @@
#import <Foundation/Foundation.h>
@interface Superclass : NSObject
@end
@implementation Superclass
@end

View File

@@ -0,0 +1,4 @@
import Framework
open class Subclass1 : Superclass {
}

View File

@@ -0,0 +1,3 @@
// CHECK: Subclass
print(Subclass().self)

View File

@@ -0,0 +1,6 @@
import Foundation
public struct Gen<Subclass : NSObject> {
public init() {
}
}

View File

@@ -0,0 +1,9 @@
open class Superclass {
public init() {
}
}
public struct Gen<Subclass : Superclass> {
public init() {
}
}

View File

@@ -0,0 +1,42 @@
// RUN: %empty-directory(%t)
// RUN: %target-build-swift -emit-library -enable-library-evolution -module-name Framework -module-link-name Framework %S/Inputs/public_struct_with_generic_arg_nsobject_constrained.swift -o %t/%target-library-name(Framework) -emit-module-path %t/Framework.swiftmodule
// RUN: %target-codesign %t/libFramework.dylib
// RUN: %target-build-swift %s %S/Inputs/print_subclass/main.swift -module-name main -o %t/main -I %t -L %t
// RUN: %target-codesign %t/main
// RUN: %target-run %t/main | %FileCheck %S/Inputs/print_subclass/main.swift
// REQUIRES: executable_test
// REQUIRES: OS=macosx
// Testing runtime changes that aren't in the os stdlib.
// UNSUPPORTED: use_os_stdlib
import Swift
import Foundation
import Framework
// Swift subclass of a Swift class
// subclass isSwiftClassMetadataSubclass metadata completeness : Complete
// superclass metadata path: loop
// iteration 1: subclass->Superclass == NSObject
// subclass <= NSObject
// superclass == NSObject; done
typealias Gen = Framework.Gen<Subclass>
public class Subclass : NSObject {
override init() {
self.gen = Gen()
super.init()
}
var gen: Gen?
}
@inline(never)
public func consume<T>(_ t: T) {
withExtendedLifetime(t) { t in
}
}

View File

@@ -0,0 +1,41 @@
// RUN: %empty-directory(%t)
// RUN: %target-build-swift -emit-library -enable-library-evolution -module-name Framework -module-link-name Framework %S/Inputs/public_struct_with_generic_arg_nsobject_constrained.swift -o %t/%target-library-name(Framework) -emit-module-path %t/Framework.swiftmodule -target %module-target-future
// RUN: %target-codesign %t/libFramework.dylib
// RUN: %target-build-swift %s %S/Inputs/print_subclass/main.swift -module-name main -o %t/main -I %t -L %t -target %module-target-future
// RUN: %target-codesign %t/main
// RUN: %target-run %t/main | %FileCheck %S/Inputs/print_subclass/main.swift
// REQUIRES: executable_test
// REQUIRES: OS=macosx
// Testing runtime changes that aren't in the os stdlib.
// UNSUPPORTED: use_os_stdlib
import Swift
import Foundation
import Framework
// Swift subclass of a ObjC class
// subclass isSwiftClassMetadataSubclass metadata completeness : LayoutComplete
// superclass metadata path: getSuperclassMetadata
// getSuperclassMetadata result 1: (Complete, NSObject, !ClassMetadata)
// handleObjc => swift_dynamicCastMetatype
typealias Gen = Framework.Gen<Subclass>
public class Subclass : NSObject {
override init() {
self.gen = Gen()
super.init()
}
var gen: Gen?
}
@inline(never)
public func consume<T>(_ t: T) {
withExtendedLifetime(t) { t in
}
}

View File

@@ -0,0 +1,43 @@
// RUN: %empty-directory(%t)
// RUN: %target-build-swift -emit-library -enable-library-evolution -module-name Framework -module-link-name Framework %S/Inputs/public_struct_with_generic_arg_nsobject_constrained.swift -o %t/%target-library-name(Framework) -emit-module-path %t/Framework.swiftmodule
// RUN: %target-codesign %t/libFramework.dylib
// RUN: %target-clang -fobjc-arc %S/Inputs/Superclass.m -c -o %t/Superclass.o
// RUN: %target-build-swift %s %t/Superclass.o %S/Inputs/print_subclass/main.swift -import-objc-header %S/Inputs/Superclass.h -module-name main -o %t/main -I %t -L %t
// RUN: %target-codesign %t/main
// RUN: %target-run %t/main | %FileCheck %S/Inputs/print_subclass/main.swift
// REQUIRES: executable_test
// REQUIRES: OS=macosx
// Testing runtime changes that aren't in the os stdlib.
// UNSUPPORTED: use_os_stdlib
import Swift
import Foundation
import Framework
// Swift subclass of an ObjC subclass of an ObjC class
// subclass isSwiftClassMetadataSubclass metadata completeness : Complete
// superclass metadata path: loop
// iteration 1: subclass->Superclass == NSObject
// subclass <= NSObject
// superclass == NSObject; done
typealias Gen = Framework.Gen<Subclass>
public class Subclass : Superclass {
override init() {
self.gen = Gen()
super.init()
}
var gen: Gen?
}
@inline(never)
public func consume<T>(_ t: T) {
withExtendedLifetime(t) { t in
}
}

View File

@@ -0,0 +1,42 @@
// RUN: %empty-directory(%t)
// RUN: %target-build-swift -emit-library -enable-library-evolution -module-name Framework -module-link-name Framework %S/Inputs/public_struct_with_generic_arg_nsobject_constrained.swift -o %t/%target-library-name(Framework) -emit-module-path %t/Framework.swiftmodule -target %module-target-future
// RUN: %target-codesign %t/libFramework.dylib
// RUN: %target-clang -fobjc-arc %S/Inputs/Superclass.m -c -o %t/Superclass.o
// RUN: %target-build-swift %s %t/Superclass.o %S/Inputs/print_subclass/main.swift -import-objc-header %S/Inputs/Superclass.h -module-name main -o %t/main -I %t -L %t -target %module-target-future
// RUN: %target-codesign %t/main
// RUN: %target-run %t/main | %FileCheck %S/Inputs/print_subclass/main.swift
// REQUIRES: executable_test
// REQUIRES: OS=macosx
// Testing runtime changes that aren't in the os stdlib.
// UNSUPPORTED: use_os_stdlib
import Swift
import Foundation
import Framework
// Swift subclass of an ObjC subclass of an ObjC class
// subclass isSwiftClassMetadataSubclass metadata completeness : Complete
// superclass metadata path: getSuperclassMetadata
// getSuperclassMetadata result 1: (Complete, NSObject, !ClassMetadata)
// handleObjc => swift_dynamicCastMetatype
typealias Gen = Framework.Gen<Subclass>
public class Subclass : Superclass {
override init() {
self.gen = Gen()
super.init()
}
var gen: Gen?
}
@inline(never)
public func consume<T>(_ t: T) {
withExtendedLifetime(t) { t in
}
}

View File

@@ -0,0 +1,29 @@
// RUN: %empty-directory(%t)
// RUN: %target-build-swift -emit-library -enable-library-evolution -module-name Framework -module-link-name Framework %S/Inputs/public_struct_with_generic_arg_nsobject_constrained.swift -o %t/%target-library-name(Framework) -emit-module-path %t/Framework.swiftmodule
// RUN: %target-codesign %t/libFramework.dylib
// RUN: %target-clang -fobjc-arc %S/Inputs/SubclassOfNSObject.m -c -o %t/Superclass.o
// RUN: %target-build-swift %s %t/Superclass.o %S/Inputs/print_subclass/main.swift -import-objc-header %S/Inputs/SubclassOfNSObject.h -module-name main -o %t/main -I %t -L %t
// RUN: %target-codesign %t/main
// RUN: %target-run %t/main | %FileCheck %S/Inputs/print_subclass/main.swift
// REQUIRES: executable_test
// REQUIRES: OS=macosx
// Testing runtime changes that aren't in the os stdlib.
// UNSUPPORTED: use_os_stdlib
import Swift
import Foundation
import Framework
// ObjC subclass of an ObjC subclass
// isSubclass is never called: no reference to subclass metadata from subclass
// metadata; i.e. Subclass has no member of type Gen<Subclass>?
@inline(never)
public func consume<T>(_ t: T) {
withExtendedLifetime(t) { t in
}
}

View File

@@ -0,0 +1,41 @@
// RUN: %empty-directory(%t)
// RUN: %target-build-swift -emit-library -enable-library-evolution -module-name Framework -module-link-name Framework %S/Inputs/public_struct_with_generic_arg_swift_class_constrained.swift -o %t/%target-library-name(Framework) -emit-module-path %t/Framework.swiftmodule
// RUN: %target-codesign %t/libFramework.dylib
// RUN: %target-build-swift %s %S/Inputs/print_subclass/main.swift -module-name main -o %t/main -I %t -L %t
// RUN: %target-codesign %t/main
// RUN: %target-run %t/main | %FileCheck %S/Inputs/print_subclass/main.swift
// REQUIRES: executable_test
// REQUIRES: OS=macosx
// Testing runtime changes that aren't in the os stdlib.
// UNSUPPORTED: use_os_stdlib
import Swift
import Framework
// Swift subclass of a Swift class
// subclass isSwiftClassMetadataSubclass metadata completeness : Complete
// superclass metadata path: loop
// iteration 1: subclass->Superclass == Superclass
// subclass <= Superclass
// superclass == Superclass; done
typealias Gen = Framework.Gen<Subclass>
public class Subclass : Superclass {
override init() {
self.gen = Gen()
super.init()
}
var gen: Gen?
}
@inline(never)
public func consume<T>(_ t: T) {
withExtendedLifetime(t) { t in
}
}

View File

@@ -0,0 +1,47 @@
// RUN: %empty-directory(%t)
// RUN: %target-build-swift -emit-library -enable-library-evolution -module-name Framework -module-link-name Framework %S/Inputs/public_struct_with_generic_arg_swift_class_constrained.swift -o %t/%target-library-name(Framework) -emit-module-path %t/Framework.swiftmodule
// RUN: %target-codesign %t/libFramework.dylib
// RUN: %target-build-swift -emit-library -enable-library-evolution -module-name Framework2 -module-link-name Framework2 %S/Inputs/open_subclass_of_Framework.Superclass.swift -o %t/%target-library-name(Framework2) -emit-module-path %t/Framework2.swiftmodule -I %t -L %t
// RUN: %target-codesign %t/libFramework2.dylib
// RUN: %target-build-swift %s %S/Inputs/print_subclass/main.swift -module-name main -o %t/main -I %t -L %t
// RUN: %target-codesign %t/main
// RUN: %target-run %t/main | %FileCheck %S/Inputs/print_subclass/main.swift
// REQUIRES: executable_test
// REQUIRES: OS=macosx
// Testing runtime changes that aren't in the os stdlib.
// UNSUPPORTED: use_os_stdlib
import Swift
import Framework
import Framework2
// Swift subclass of a Swift subclass of a Swift class
// subclass isSwiftClassMetadataSubclass metadata completeness : Complete
// superclass metadata path: loop
// iteration 1: subclass->Superclass == Subclass1
// subclass <= Subclass1
// iteration 2: subclass->Superclass == Superclass
// subclass <= Superclass
// superclass == Superclass; done
typealias Gen = Framework.Gen<Subclass>
public class Subclass : Subclass1 {
override init() {
self.gen = Gen()
super.init()
}
var gen: Gen?
}
@inline(never)
public func consume<T>(_ t: T) {
withExtendedLifetime(t) { t in
}
}

View File

@@ -0,0 +1,48 @@
// RUN: %empty-directory(%t)
// RUN: %target-build-swift -emit-library -enable-library-evolution -module-name Framework -module-link-name Framework %S/Inputs/public_struct_with_generic_arg_swift_class_constrained.swift -o %t/%target-library-name(Framework) -emit-module-path %t/Framework.swiftmodule -target %module-target-future
// RUN: %target-codesign %t/libFramework.dylib
// RUN: %target-build-swift -emit-library -enable-library-evolution -module-name Framework2 -module-link-name Framework2 %S/Inputs/open_subclass_of_Framework.Superclass.swift -o %t/%target-library-name(Framework2) -emit-module-path %t/Framework2.swiftmodule -target %module-target-future -I %t -L %t
// RUN: %target-codesign %t/libFramework2.dylib
// RUN: %target-build-swift %s %S/Inputs/print_subclass/main.swift -module-name main -o %t/main -I %t -L %t -target %module-target-future
// RUN: %target-codesign %t/main
// RUN: %target-run %t/main | %FileCheck %S/Inputs/print_subclass/main.swift
// REQUIRES: executable_test
// REQUIRES: OS=macosx
// Testing runtime changes that aren't in the os stdlib.
// UNSUPPORTED: use_os_stdlib
import Swift
import Framework
import Framework2
// Swift subclass of a Swift class
// subclass isSwiftClassMetadataSubclass metadata completeness : LayoutComplete
// superclass metadata path: getSuperclassMetadata
// getSuperclassMetadata result 1: (Complete, Subclass1)
// superclass metadata path: loop
// iteration 1: subclass->Superclass == Superclass
// subclass <= Superclass
// superclass == Superclass; done
typealias Gen = Framework.Gen<Subclass>
public class Subclass : Subclass1 {
override init() {
self.gen = Gen()
super.init()
}
var gen: Gen?
}
@inline(never)
public func consume<T>(_ t: T) {
withExtendedLifetime(t) { t in
}
}

View File

@@ -0,0 +1,40 @@
// RUN: %empty-directory(%t)
// RUN: %target-build-swift -emit-library -enable-library-evolution -module-name Framework -module-link-name Framework %S/Inputs/public_struct_with_generic_arg_swift_class_constrained.swift -o %t/%target-library-name(Framework) -emit-module-path %t/Framework.swiftmodule -target %module-target-future
// RUN: %target-codesign %t/libFramework.dylib
// RUN: %target-build-swift %s %S/Inputs/print_subclass/main.swift -module-name main -o %t/main -I %t -L %t -target %module-target-future
// RUN: %target-codesign %t/main
// RUN: %target-run %t/main | %FileCheck %S/Inputs/print_subclass/main.swift
// REQUIRES: executable_test
// REQUIRES: OS=macosx
// Testing runtime changes that aren't in the os stdlib.
// UNSUPPORTED: use_os_stdlib
import Swift
import Framework
// Swift subclass of a Swift class
// subclass isSwiftClassMetadataSubclass metadata completeness : LayoutComplete
// superclass metadata path: getSuperclassMetadata
// getSuperclassMetadata result 1: (Complete, Superclass)
// subclass == superclass; done
typealias Gen = Framework.Gen<Subclass>
public class Subclass : Superclass {
override init() {
self.gen = Gen()
super.init()
}
var gen: Gen?
}
@inline(never)
public func consume<T>(_ t: T) {
withExtendedLifetime(t) { t in
}
}