mirror of
https://github.com/apple/swift.git
synced 2025-12-21 12:14:44 +01:00
Respect resilience when specializing opaque type archetypes
This commit is contained in:
@@ -111,8 +111,9 @@ public:
|
|||||||
|
|
||||||
/// Replace opaque types in the conforming type with their underlying types,
|
/// Replace opaque types in the conforming type with their underlying types,
|
||||||
/// and resolve opaque conformances to their underlying conformances.
|
/// and resolve opaque conformances to their underlying conformances.
|
||||||
ProtocolConformanceRef substOpaqueTypesWithUnderlyingTypes(Type origType) const;
|
ProtocolConformanceRef substOpaqueTypesWithUnderlyingTypes(
|
||||||
|
Type origType, ModuleDecl *modulePerformingSubstitution) const;
|
||||||
|
|
||||||
/// Given a dependent type (expressed in terms of this conformance's
|
/// Given a dependent type (expressed in terms of this conformance's
|
||||||
/// protocol), follow it from the conforming type.
|
/// protocol), follow it from the conforming type.
|
||||||
Type getAssociatedType(Type origType, Type dependentType,
|
Type getAssociatedType(Type origType, Type dependentType,
|
||||||
|
|||||||
@@ -177,7 +177,8 @@ public:
|
|||||||
|
|
||||||
/// Replace opaque types in the replacement types in the map with their
|
/// Replace opaque types in the replacement types in the map with their
|
||||||
/// underlying types. Does not change keys.
|
/// underlying types. Does not change keys.
|
||||||
SubstitutionMap substOpaqueTypesWithUnderlyingTypes() const;
|
SubstitutionMap substOpaqueTypesWithUnderlyingTypes(
|
||||||
|
ModuleDecl *modulePerformingSubstitution) const;
|
||||||
|
|
||||||
/// Create a substitution map for a protocol conformance.
|
/// Create a substitution map for a protocol conformance.
|
||||||
static SubstitutionMap
|
static SubstitutionMap
|
||||||
|
|||||||
@@ -318,7 +318,8 @@ public:
|
|||||||
|
|
||||||
/// Replace opaque types with their underlying types when visible at the given
|
/// Replace opaque types with their underlying types when visible at the given
|
||||||
/// resilience expansion.
|
/// resilience expansion.
|
||||||
Type substOpaqueTypesWithUnderlyingTypes() const;
|
Type substOpaqueTypesWithUnderlyingTypes(
|
||||||
|
ModuleDecl *modulePerformingSubstitution) const;
|
||||||
|
|
||||||
bool isPrivateStdlibType(bool treatNonBuiltinProtocolsAsPublic = true) const;
|
bool isPrivateStdlibType(bool treatNonBuiltinProtocolsAsPublic = true) const;
|
||||||
|
|
||||||
|
|||||||
@@ -4827,8 +4827,11 @@ END_CAN_TYPE_WRAPPER(OpaqueTypeArchetypeType, ArchetypeType)
|
|||||||
/// to their underlying types.
|
/// to their underlying types.
|
||||||
class ReplaceOpaqueTypesWithUnderlyingTypes {
|
class ReplaceOpaqueTypesWithUnderlyingTypes {
|
||||||
public:
|
public:
|
||||||
ReplaceOpaqueTypesWithUnderlyingTypes() {}
|
ModuleDecl *modulePerformingSubstitution;
|
||||||
|
ReplaceOpaqueTypesWithUnderlyingTypes(
|
||||||
|
ModuleDecl *modulePerformingSubstitution)
|
||||||
|
: modulePerformingSubstitution(modulePerformingSubstitution) {}
|
||||||
|
|
||||||
/// TypeSubstitutionFn
|
/// TypeSubstitutionFn
|
||||||
Type operator()(SubstitutableType *maybeOpaqueType) const;
|
Type operator()(SubstitutableType *maybeOpaqueType) const;
|
||||||
|
|
||||||
|
|||||||
@@ -142,8 +142,9 @@ ProtocolConformanceRef::subst(Type origType,
|
|||||||
}
|
}
|
||||||
|
|
||||||
ProtocolConformanceRef
|
ProtocolConformanceRef
|
||||||
ProtocolConformanceRef::substOpaqueTypesWithUnderlyingTypes(Type origType) const {
|
ProtocolConformanceRef::substOpaqueTypesWithUnderlyingTypes(
|
||||||
ReplaceOpaqueTypesWithUnderlyingTypes replacer;
|
Type origType, ModuleDecl *modulePerformingSubstitution) const {
|
||||||
|
ReplaceOpaqueTypesWithUnderlyingTypes replacer(modulePerformingSubstitution);
|
||||||
return subst(origType, replacer, replacer,
|
return subst(origType, replacer, replacer,
|
||||||
SubstFlags::SubstituteOpaqueArchetypes);
|
SubstFlags::SubstituteOpaqueArchetypes);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -492,10 +492,9 @@ SubstitutionMap SubstitutionMap::subst(TypeSubstitutionFn subs,
|
|||||||
return SubstitutionMap(genericSig, newSubs, newConformances);
|
return SubstitutionMap(genericSig, newSubs, newConformances);
|
||||||
}
|
}
|
||||||
|
|
||||||
SubstitutionMap
|
SubstitutionMap SubstitutionMap::substOpaqueTypesWithUnderlyingTypes(
|
||||||
SubstitutionMap::substOpaqueTypesWithUnderlyingTypes()
|
ModuleDecl *modulePerformingSubstitution) const {
|
||||||
const {
|
ReplaceOpaqueTypesWithUnderlyingTypes replacer(modulePerformingSubstitution);
|
||||||
ReplaceOpaqueTypesWithUnderlyingTypes replacer;
|
|
||||||
return subst(replacer, replacer, SubstFlags::SubstituteOpaqueArchetypes);
|
return subst(replacer, replacer, SubstFlags::SubstituteOpaqueArchetypes);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -2477,9 +2477,17 @@ Type ReplaceOpaqueTypesWithUnderlyingTypes::operator()(
|
|||||||
auto archetypeAndRoot = getArchetypeAndRootOpaqueArchetype(maybeOpaqueType);
|
auto archetypeAndRoot = getArchetypeAndRootOpaqueArchetype(maybeOpaqueType);
|
||||||
if (!archetypeAndRoot)
|
if (!archetypeAndRoot)
|
||||||
return maybeOpaqueType;
|
return maybeOpaqueType;
|
||||||
|
|
||||||
auto archetype = archetypeAndRoot->first;
|
auto archetype = archetypeAndRoot->first;
|
||||||
auto opaqueRoot = archetypeAndRoot->second;
|
auto opaqueRoot = archetypeAndRoot->second;
|
||||||
|
|
||||||
|
// Don't replace opaque types from resilient modules.
|
||||||
|
auto namingDecl = opaqueRoot->getDecl()->getNamingDecl();
|
||||||
|
auto module = namingDecl->getModuleContext();
|
||||||
|
if (module->isResilient() && module != modulePerformingSubstitution) {
|
||||||
|
return maybeOpaqueType;
|
||||||
|
}
|
||||||
|
|
||||||
auto subs = opaqueRoot->getDecl()->getUnderlyingTypeSubstitutions();
|
auto subs = opaqueRoot->getDecl()->getUnderlyingTypeSubstitutions();
|
||||||
// TODO: Check the resilience expansion, and handle opaque types with
|
// TODO: Check the resilience expansion, and handle opaque types with
|
||||||
// unknown underlying types. For now, all opaque types are always
|
// unknown underlying types. For now, all opaque types are always
|
||||||
@@ -2496,7 +2504,8 @@ Type ReplaceOpaqueTypesWithUnderlyingTypes::operator()(
|
|||||||
|
|
||||||
// If the type still contains opaque types, recur.
|
// If the type still contains opaque types, recur.
|
||||||
if (substTy->hasOpaqueArchetype()) {
|
if (substTy->hasOpaqueArchetype()) {
|
||||||
return substTy.substOpaqueTypesWithUnderlyingTypes();
|
return substTy.substOpaqueTypesWithUnderlyingTypes(
|
||||||
|
modulePerformingSubstitution);
|
||||||
}
|
}
|
||||||
return substTy;
|
return substTy;
|
||||||
}
|
}
|
||||||
@@ -2516,6 +2525,14 @@ ReplaceOpaqueTypesWithUnderlyingTypes::operator()(CanType maybeOpaqueType,
|
|||||||
|
|
||||||
auto archetype = archetypeAndRoot->first;
|
auto archetype = archetypeAndRoot->first;
|
||||||
auto opaqueRoot = archetypeAndRoot->second;
|
auto opaqueRoot = archetypeAndRoot->second;
|
||||||
|
|
||||||
|
// Don't replace opaque types from resilient modules.
|
||||||
|
auto namingDecl = opaqueRoot->getDecl()->getNamingDecl();
|
||||||
|
auto module = namingDecl->getModuleContext();
|
||||||
|
if (module->isResilient() && module != modulePerformingSubstitution) {
|
||||||
|
return abstractRef;
|
||||||
|
}
|
||||||
|
|
||||||
auto subs = opaqueRoot->getDecl()->getUnderlyingTypeSubstitutions();
|
auto subs = opaqueRoot->getDecl()->getUnderlyingTypeSubstitutions();
|
||||||
assert(subs.hasValue());
|
assert(subs.hasValue());
|
||||||
|
|
||||||
@@ -2534,13 +2551,15 @@ ReplaceOpaqueTypesWithUnderlyingTypes::operator()(CanType maybeOpaqueType,
|
|||||||
|
|
||||||
// If the type still contains opaque types, recur.
|
// If the type still contains opaque types, recur.
|
||||||
if (substTy->hasOpaqueArchetype()) {
|
if (substTy->hasOpaqueArchetype()) {
|
||||||
return substRef.substOpaqueTypesWithUnderlyingTypes(substTy);
|
return substRef.substOpaqueTypesWithUnderlyingTypes(
|
||||||
|
substTy, modulePerformingSubstitution);
|
||||||
}
|
}
|
||||||
return substRef;
|
return substRef;
|
||||||
}
|
}
|
||||||
|
|
||||||
Type Type::substOpaqueTypesWithUnderlyingTypes() const {
|
Type Type::substOpaqueTypesWithUnderlyingTypes(
|
||||||
ReplaceOpaqueTypesWithUnderlyingTypes replacer;
|
ModuleDecl *modulePerformingSubstitution) const {
|
||||||
|
ReplaceOpaqueTypesWithUnderlyingTypes replacer(modulePerformingSubstitution);
|
||||||
return subst(replacer, replacer,
|
return subst(replacer, replacer,
|
||||||
SubstFlags::SubstituteOpaqueArchetypes
|
SubstFlags::SubstituteOpaqueArchetypes
|
||||||
// TODO(opaque): Currently lowered types always get opaque types
|
// TODO(opaque): Currently lowered types always get opaque types
|
||||||
|
|||||||
@@ -20,6 +20,7 @@ class OpaqueSpecializerCloner
|
|||||||
|
|
||||||
SILBasicBlock *entryBlock;
|
SILBasicBlock *entryBlock;
|
||||||
SILBasicBlock *cloneFromBlock;
|
SILBasicBlock *cloneFromBlock;
|
||||||
|
ModuleDecl *currentModule;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
friend class SILCloner<OpaqueSpecializerCloner>;
|
friend class SILCloner<OpaqueSpecializerCloner>;
|
||||||
@@ -30,6 +31,7 @@ public:
|
|||||||
true /*ReplacingOpaqueArchetypes*/) {
|
true /*ReplacingOpaqueArchetypes*/) {
|
||||||
entryBlock = fun.getEntryBlock();
|
entryBlock = fun.getEntryBlock();
|
||||||
cloneFromBlock = entryBlock->split(entryBlock->begin());
|
cloneFromBlock = entryBlock->split(entryBlock->begin());
|
||||||
|
currentModule = fun.getModule().getSwiftModule();
|
||||||
}
|
}
|
||||||
|
|
||||||
void clone();
|
void clone();
|
||||||
@@ -208,21 +210,23 @@ protected:
|
|||||||
}
|
}
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
|
||||||
SILType remapType(SILType Ty) {
|
SILType remapType(SILType Ty) {
|
||||||
SILType &Sty = TypeCache[Ty];
|
SILType &Sty = TypeCache[Ty];
|
||||||
if (!Sty) {
|
if (Sty)
|
||||||
// Apply the opaque types substitution.
|
return Sty;
|
||||||
ReplaceOpaqueTypesWithUnderlyingTypes replacer;
|
|
||||||
Sty = Ty.subst(Original.getModule(), SubsMap)
|
// Apply the opaque types substitution.
|
||||||
.subst(Original.getModule(), replacer, replacer,
|
ReplaceOpaqueTypesWithUnderlyingTypes replacer(currentModule);
|
||||||
CanGenericSignature(), true);
|
Sty = Ty.subst(Original.getModule(), SubsMap)
|
||||||
}
|
.subst(Original.getModule(), replacer, replacer,
|
||||||
|
CanGenericSignature(), true);
|
||||||
return Sty;
|
return Sty;
|
||||||
}
|
}
|
||||||
|
|
||||||
CanType remapASTType(CanType ty) {
|
CanType remapASTType(CanType ty) {
|
||||||
// Apply the opaque types substitution.
|
// Apply the opaque types substitution.
|
||||||
ReplaceOpaqueTypesWithUnderlyingTypes replacer;
|
ReplaceOpaqueTypesWithUnderlyingTypes replacer(currentModule);
|
||||||
return SuperTy::remapASTType(ty)
|
return SuperTy::remapASTType(ty)
|
||||||
.subst(replacer, replacer,
|
.subst(replacer, replacer,
|
||||||
SubstFlags::SubstituteOpaqueArchetypes |
|
SubstFlags::SubstituteOpaqueArchetypes |
|
||||||
@@ -233,7 +237,7 @@ protected:
|
|||||||
ProtocolConformanceRef remapConformance(Type type,
|
ProtocolConformanceRef remapConformance(Type type,
|
||||||
ProtocolConformanceRef conf) {
|
ProtocolConformanceRef conf) {
|
||||||
// Apply the opaque types substitution.
|
// Apply the opaque types substitution.
|
||||||
ReplaceOpaqueTypesWithUnderlyingTypes replacer;
|
ReplaceOpaqueTypesWithUnderlyingTypes replacer(currentModule);
|
||||||
return SuperTy::remapConformance(type, conf)
|
return SuperTy::remapConformance(type, conf)
|
||||||
.subst(type, replacer, replacer,
|
.subst(type, replacer, replacer,
|
||||||
SubstFlags::SubstituteOpaqueArchetypes |
|
SubstFlags::SubstituteOpaqueArchetypes |
|
||||||
@@ -242,7 +246,7 @@ protected:
|
|||||||
|
|
||||||
SubstitutionMap remapSubstitutionMap(SubstitutionMap Subs) {
|
SubstitutionMap remapSubstitutionMap(SubstitutionMap Subs) {
|
||||||
// Apply the opaque types substitution.
|
// Apply the opaque types substitution.
|
||||||
ReplaceOpaqueTypesWithUnderlyingTypes replacer;
|
ReplaceOpaqueTypesWithUnderlyingTypes replacer(currentModule);
|
||||||
return SuperTy::remapSubstitutionMap(Subs).subst(
|
return SuperTy::remapSubstitutionMap(Subs).subst(
|
||||||
replacer, replacer,
|
replacer, replacer,
|
||||||
SubstFlags::SubstituteOpaqueArchetypes | SubstFlags::AllowLoweredTypes);
|
SubstFlags::SubstituteOpaqueArchetypes | SubstFlags::AllowLoweredTypes);
|
||||||
@@ -295,13 +299,24 @@ void OpaqueSpecializerCloner::insertOpaqueToConcreteAddressCasts(
|
|||||||
namespace {
|
namespace {
|
||||||
class OpaqueArchetypeSpecializer : public SILFunctionTransform {
|
class OpaqueArchetypeSpecializer : public SILFunctionTransform {
|
||||||
void run() override {
|
void run() override {
|
||||||
|
auto *currentModule = getFunction()->getModule().getSwiftModule();
|
||||||
|
|
||||||
|
auto opaqueArchetypeWouldChange = [=](CanType ty) -> bool {
|
||||||
|
if (!ty->hasOpaqueArchetype())
|
||||||
|
return false;
|
||||||
|
ReplaceOpaqueTypesWithUnderlyingTypes replacer(currentModule);
|
||||||
|
return ty.subst(replacer, replacer,
|
||||||
|
SubstFlags::SubstituteOpaqueArchetypes |
|
||||||
|
SubstFlags::AllowLoweredTypes)
|
||||||
|
->getCanonicalType() != ty;
|
||||||
|
};
|
||||||
|
|
||||||
// Look for opaque type archetypes.
|
// Look for opaque type archetypes.
|
||||||
bool foundOpaqueArchetype = false;
|
bool foundOpaqueArchetype = false;
|
||||||
for (auto &BB : *getFunction()) {
|
for (auto &BB : *getFunction()) {
|
||||||
for (auto &inst : BB) {
|
for (auto &inst : BB) {
|
||||||
for (auto &opd : inst.getAllOperands()) {
|
for (auto &opd : inst.getAllOperands()) {
|
||||||
if (!opd.get()->getType().getASTType()->hasOpaqueArchetype())
|
if (!opaqueArchetypeWouldChange(opd.get()->getType().getASTType()))
|
||||||
continue;
|
continue;
|
||||||
foundOpaqueArchetype = true;
|
foundOpaqueArchetype = true;
|
||||||
break;
|
break;
|
||||||
@@ -309,8 +324,8 @@ class OpaqueArchetypeSpecializer : public SILFunctionTransform {
|
|||||||
if (foundOpaqueArchetype)
|
if (foundOpaqueArchetype)
|
||||||
break;
|
break;
|
||||||
auto *allocStack = dyn_cast<AllocStackInst>(&inst);
|
auto *allocStack = dyn_cast<AllocStackInst>(&inst);
|
||||||
if (!allocStack ||
|
if (!allocStack || !opaqueArchetypeWouldChange(
|
||||||
!allocStack->getElementType().getASTType()->hasOpaqueArchetype())
|
allocStack->getElementType().getASTType()))
|
||||||
continue;
|
continue;
|
||||||
foundOpaqueArchetype = true;
|
foundOpaqueArchetype = true;
|
||||||
break;
|
break;
|
||||||
@@ -322,10 +337,8 @@ class OpaqueArchetypeSpecializer : public SILFunctionTransform {
|
|||||||
OpaqueSpecializerCloner s(subsMap, *getFunction());
|
OpaqueSpecializerCloner s(subsMap, *getFunction());
|
||||||
s.clone();
|
s.clone();
|
||||||
removeUnreachableBlocks(*getFunction());
|
removeUnreachableBlocks(*getFunction());
|
||||||
}
|
|
||||||
|
|
||||||
if (foundOpaqueArchetype)
|
|
||||||
invalidateAnalysis(SILAnalysis::InvalidationKind::FunctionBody);
|
invalidateAnalysis(SILAnalysis::InvalidationKind::FunctionBody);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
} // end anonymous namespace
|
} // end anonymous namespace
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
// RUN: %target-swift-frontend %S/Inputs/specialize_opaque_type_archetypes_2.swift -module-name External -emit-module -emit-module-path %t/External.swiftmodule
|
// RUN: %target-swift-frontend %S/Inputs/specialize_opaque_type_archetypes_2.swift -module-name External -emit-module -emit-module-path %t/External.swiftmodule
|
||||||
// RUN: %target-swift-frontend %S/Inputs/specialize_opaque_type_archetypes_3.swift -enable-library-evolution -module-name External2 -emit-module -emit-module-path %t/External2.swiftmodule
|
// RUN: %target-swift-frontend %S/Inputs/specialize_opaque_type_archetypes_3.swift -enable-library-evolution -module-name External2 -emit-module -emit-module-path %t/External2.swiftmodule
|
||||||
// RUN: %target-swift-frontend -I %t -module-name A -enforce-exclusivity=checked -Osize -emit-sil -sil-verify-all %s | %FileCheck %s
|
// RUN: %target-swift-frontend -I %t -module-name A -enforce-exclusivity=checked -Osize -emit-sil -sil-verify-all %s | %FileCheck %s
|
||||||
|
// RUN: %target-swift-frontend -I %t -module-name A -enforce-exclusivity=checked -enable-library-evolution -Osize -emit-sil -sil-verify-all %s | %FileCheck %s
|
||||||
import External
|
import External
|
||||||
import External2
|
import External2
|
||||||
|
|
||||||
@@ -112,12 +113,14 @@ public func useExternal() {
|
|||||||
useP(e.myValue2())
|
useP(e.myValue2())
|
||||||
}
|
}
|
||||||
|
|
||||||
// This should change once opaque types support resilience.
|
// Call to a resilient function should not be specialized.
|
||||||
|
|
||||||
// CHECK-LABEL: sil @$s1A20useExternalResilientyyF
|
// CHECK-LABEL: sil @$s1A20useExternalResilientyyF
|
||||||
// CHECK: // function_ref Int64.myValue3()
|
// CHECK: [[RES:%.*]] = alloc_stack $@_opaqueReturnTypeOf("$s9External217externalResilientQryF", 0)
|
||||||
// CHECK: [[FUN:%.*]] = function_ref @$ss5Int64V9External2E8myValue3AByF
|
// CHECK: [[FUN:%.*]] = function_ref @$s9External217externalResilientQryF : $@convention(thin) () -> @out @_opaqueReturnTypeOf("$s9External217externalResilientQryF", 0)
|
||||||
// CHECK: apply [[FUN]]
|
// CHECK: apply [[FUN]]([[RES]])
|
||||||
|
// CHECK: witness_method
|
||||||
|
// CHECK: return
|
||||||
public func useExternalResilient() {
|
public func useExternalResilient() {
|
||||||
let e = externalResilient()
|
let e = externalResilient()
|
||||||
useP(e.myValue3())
|
useP(e.myValue3())
|
||||||
@@ -207,6 +210,35 @@ public func usePair() {
|
|||||||
useP(x.second.myValue())
|
useP(x.second.myValue())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
struct MyInt64 : ExternalP2 {
|
||||||
|
var x = Int64(0)
|
||||||
|
public func myValue3() -> Int64 {
|
||||||
|
return x + 3
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func nonResilient() -> some ExternalP2 {
|
||||||
|
return MyInt64()
|
||||||
|
}
|
||||||
|
|
||||||
|
// CHECK-LABEL: sil @$s1A019usePairResilientNonC0yyF : $@convention(thin) () -> ()
|
||||||
|
// CHECK: alloc_stack $Pair<MyInt64, @_opaqueReturnTypeOf("$s9External217externalResilientQryF", 0)
|
||||||
|
// CHECK: cond_fail
|
||||||
|
// CHECK: [[FIRST_MYVALUE3:%.*]] = struct $Int64
|
||||||
|
// CHECK: [[USEP:%.*]] = function_ref @$s1A4usePyyxAA1PRzlFs5Int64V_Tg5
|
||||||
|
// CHECK: apply [[USEP]]([[FIRST_MYVALUE3]])
|
||||||
|
// CHECK: [[MYVALUE_WITNESS:%.*]] = witness_method $@_opaqueReturnTypeOf("$s9External217externalResilientQryF"
|
||||||
|
// CHECK: [[SECOND_MYVALUE3:%.*]] = apply [[MYVALUE_WITNESS]]
|
||||||
|
// CHECK: apply [[USEP]]([[SECOND_MYVALUE3]])
|
||||||
|
// CHECK: return
|
||||||
|
|
||||||
|
public func usePairResilientNonResilient() {
|
||||||
|
var x = Pair(first: nonResilient(), second: externalResilient())
|
||||||
|
useP(x.first.myValue3())
|
||||||
|
useP(x.second.myValue3())
|
||||||
|
}
|
||||||
|
|
||||||
public protocol P3 {
|
public protocol P3 {
|
||||||
associatedtype AT
|
associatedtype AT
|
||||||
func foo() -> AT
|
func foo() -> AT
|
||||||
|
|||||||
@@ -0,0 +1,59 @@
|
|||||||
|
public protocol P {
|
||||||
|
func getValue() -> Int
|
||||||
|
}
|
||||||
|
|
||||||
|
extension Int : P {
|
||||||
|
public func getValue() -> Int {
|
||||||
|
return self + 1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#if !BEFORE
|
||||||
|
public struct Pair : P {
|
||||||
|
var x = 0
|
||||||
|
var y = 1
|
||||||
|
|
||||||
|
public func getValue() -> Int {
|
||||||
|
return y
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
public func resilientFunction() -> some P {
|
||||||
|
#if BEFORE
|
||||||
|
return Int(5)
|
||||||
|
#else
|
||||||
|
return Pair()
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
public func expectedResult() -> Int {
|
||||||
|
return resilientFunction().getValue()
|
||||||
|
}
|
||||||
|
|
||||||
|
public func expectedSize() -> Int {
|
||||||
|
return MemoryLayout.size(ofValue: resilientFunction())
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public struct Container {
|
||||||
|
public init() {}
|
||||||
|
|
||||||
|
public var property : some P {
|
||||||
|
get {
|
||||||
|
#if BEFORE
|
||||||
|
return Int(5)
|
||||||
|
#else
|
||||||
|
return Pair()
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public func expectedResult() -> Int {
|
||||||
|
return property.getValue()
|
||||||
|
}
|
||||||
|
|
||||||
|
public func expectedSize() -> Int {
|
||||||
|
return MemoryLayout.size(ofValue: property)
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,22 @@
|
|||||||
|
// RUN: %target-resilience-test
|
||||||
|
// REQUIRES: executable_test
|
||||||
|
|
||||||
|
// Use swift-version 4.
|
||||||
|
// UNSUPPORTED: swift_test_mode_optimize_none_with_implicit_dynamic
|
||||||
|
|
||||||
|
import opaque_archetypes_change_underlying_type
|
||||||
|
import StdlibUnittest
|
||||||
|
|
||||||
|
var OpaqueArchetypes = TestSuite("OpaqueArchetypes")
|
||||||
|
|
||||||
|
OpaqueArchetypes.test("test1") {
|
||||||
|
let o = resilientFunction()
|
||||||
|
expectEqual(o.getValue(), expectedResult())
|
||||||
|
expectEqual(MemoryLayout.size(ofValue: o), expectedSize())
|
||||||
|
|
||||||
|
let c = Container()
|
||||||
|
expectEqual(c.property.getValue(), c.expectedResult())
|
||||||
|
expectEqual(MemoryLayout.size(ofValue: c.property), c.expectedSize())
|
||||||
|
}
|
||||||
|
|
||||||
|
runAllTests()
|
||||||
Reference in New Issue
Block a user