mirror of
https://github.com/apple/swift.git
synced 2025-12-14 20:36:38 +01:00
Merge pull request #26690 from varungandhi-apple/vg-refactor-validateExtension
Avoid setting the extendedType before and after computing the generic signature.
This commit is contained in:
@@ -52,7 +52,7 @@ const uint16_t SWIFTMODULE_VERSION_MAJOR = 0;
|
||||
/// describe what change you made. The content of this comment isn't important;
|
||||
/// it just ensures a conflict if two people change the module format.
|
||||
/// Don't worry about adhering to the 80-column limit for this line.
|
||||
const uint16_t SWIFTMODULE_VERSION_MINOR = 511; // ctor failability change
|
||||
const uint16_t SWIFTMODULE_VERSION_MINOR = 512; // extended types may be left as unbound generic types
|
||||
|
||||
using DeclIDField = BCFixed<31>;
|
||||
|
||||
|
||||
@@ -4451,7 +4451,7 @@ static Type formExtensionInterfaceType(
|
||||
|
||||
/// Check the generic parameters of an extension, recursively handling all of
|
||||
/// the parameter lists within the extension.
|
||||
static std::pair<GenericEnvironment *, Type>
|
||||
static GenericEnvironment *
|
||||
checkExtensionGenericParams(TypeChecker &tc, ExtensionDecl *ext, Type type,
|
||||
GenericParamList *genericParams) {
|
||||
assert(!ext->getGenericEnvironment());
|
||||
@@ -4489,7 +4489,7 @@ checkExtensionGenericParams(TypeChecker &tc, ExtensionDecl *ext, Type type,
|
||||
(mustInferRequirements ||
|
||||
!sameTypeReqs.empty()));
|
||||
|
||||
return { env, extInterfaceType };
|
||||
return env;
|
||||
}
|
||||
|
||||
static bool isNonGenericTypeAliasType(Type type) {
|
||||
@@ -4500,69 +4500,65 @@ static bool isNonGenericTypeAliasType(Type type) {
|
||||
return false;
|
||||
}
|
||||
|
||||
static void validateExtendedType(ExtensionDecl *ext, TypeChecker &tc) {
|
||||
// If we didn't parse a type, fill in an error type and bail out.
|
||||
if (!ext->getExtendedTypeLoc().getTypeRepr()) {
|
||||
static Type validateExtendedType(ExtensionDecl *ext) {
|
||||
auto error = [&ext]() {
|
||||
ext->setInvalid();
|
||||
ext->getExtendedTypeLoc().setInvalidType(tc.Context);
|
||||
return;
|
||||
}
|
||||
return ErrorType::get(ext->getASTContext());
|
||||
};
|
||||
|
||||
// Validate the extended type.
|
||||
// If we didn't parse a type, fill in an error type and bail out.
|
||||
if (!ext->getExtendedTypeLoc().getTypeRepr())
|
||||
return error();
|
||||
|
||||
// Compute the extended type.
|
||||
TypeResolutionOptions options(TypeResolverContext::ExtensionBinding);
|
||||
options |= TypeResolutionFlags::AllowUnboundGenerics;
|
||||
if (tc.validateType(ext->getExtendedTypeLoc(),
|
||||
TypeResolution::forInterface(ext->getDeclContext()),
|
||||
options)) {
|
||||
ext->setInvalid();
|
||||
ext->getExtendedTypeLoc().setInvalidType(tc.Context);
|
||||
return;
|
||||
}
|
||||
auto tr = TypeResolution::forStructural(ext->getDeclContext());
|
||||
auto extendedType = tr.resolveType(ext->getExtendedTypeLoc().getTypeRepr(),
|
||||
options);
|
||||
ext->getExtendedTypeLoc().setType(extendedType);
|
||||
|
||||
// Dig out the extended type.
|
||||
auto extendedType = ext->getExtendedType();
|
||||
if (extendedType->hasError())
|
||||
return error();
|
||||
|
||||
// Hack to allow extending a generic typealias.
|
||||
if (auto *unboundGeneric = extendedType->getAs<UnboundGenericType>()) {
|
||||
if (auto *aliasDecl = dyn_cast<TypeAliasDecl>(unboundGeneric->getDecl())) {
|
||||
auto extendedNominal = aliasDecl->getDeclaredInterfaceType()->getAnyNominal();
|
||||
if (extendedNominal) {
|
||||
extendedType = extendedNominal->getDeclaredType();
|
||||
if (!isPassThroughTypealias(aliasDecl))
|
||||
ext->getExtendedTypeLoc().setType(extendedType);
|
||||
}
|
||||
if (extendedNominal)
|
||||
return isPassThroughTypealias(aliasDecl)
|
||||
? extendedType
|
||||
: extendedNominal->getDeclaredType();
|
||||
}
|
||||
}
|
||||
|
||||
auto &diags = ext->getASTContext().Diags;
|
||||
|
||||
// Cannot extend a metatype.
|
||||
if (extendedType->is<AnyMetatypeType>()) {
|
||||
tc.diagnose(ext->getLoc(), diag::extension_metatype, extendedType)
|
||||
diags.diagnose(ext->getLoc(), diag::extension_metatype, extendedType)
|
||||
.highlight(ext->getExtendedTypeLoc().getSourceRange());
|
||||
ext->setInvalid();
|
||||
ext->getExtendedTypeLoc().setInvalidType(tc.Context);
|
||||
return;
|
||||
return error();
|
||||
}
|
||||
|
||||
// Cannot extend function types, tuple types, etc.
|
||||
if (!extendedType->getAnyNominal()) {
|
||||
tc.diagnose(ext->getLoc(), diag::non_nominal_extension, extendedType)
|
||||
diags.diagnose(ext->getLoc(), diag::non_nominal_extension, extendedType)
|
||||
.highlight(ext->getExtendedTypeLoc().getSourceRange());
|
||||
ext->setInvalid();
|
||||
ext->getExtendedTypeLoc().setInvalidType(tc.Context);
|
||||
return;
|
||||
return error();
|
||||
}
|
||||
|
||||
// Cannot extend a bound generic type, unless it's referenced via a
|
||||
// non-generic typealias type.
|
||||
if (extendedType->isSpecialized() &&
|
||||
!isNonGenericTypeAliasType(extendedType)) {
|
||||
tc.diagnose(ext->getLoc(), diag::extension_specialization,
|
||||
diags.diagnose(ext->getLoc(), diag::extension_specialization,
|
||||
extendedType->getAnyNominal()->getName())
|
||||
.highlight(ext->getExtendedTypeLoc().getSourceRange());
|
||||
ext->setInvalid();
|
||||
ext->getExtendedTypeLoc().setInvalidType(tc.Context);
|
||||
return;
|
||||
return error();
|
||||
}
|
||||
|
||||
return extendedType;
|
||||
}
|
||||
|
||||
void TypeChecker::validateExtension(ExtensionDecl *ext) {
|
||||
@@ -4573,7 +4569,7 @@ void TypeChecker::validateExtension(ExtensionDecl *ext) {
|
||||
|
||||
DeclValidationRAII IBV(ext);
|
||||
|
||||
validateExtendedType(ext, *this);
|
||||
auto extendedType = validateExtendedType(ext);
|
||||
|
||||
if (auto *nominal = ext->getExtendedNominal()) {
|
||||
// If this extension was not already bound, it means it is either in an
|
||||
@@ -4586,14 +4582,11 @@ void TypeChecker::validateExtension(ExtensionDecl *ext) {
|
||||
// Validate the nominal type declaration being extended.
|
||||
validateDecl(nominal);
|
||||
|
||||
if (auto *genericParams = ext->getGenericParams()) {
|
||||
GenericEnvironment *env;
|
||||
Type extendedType = ext->getExtendedType();
|
||||
std::tie(env, extendedType) = checkExtensionGenericParams(
|
||||
*this, ext, extendedType,
|
||||
genericParams);
|
||||
|
||||
ext->getExtendedTypeLoc().setType(extendedType);
|
||||
|
||||
if (auto *genericParams = ext->getGenericParams()) {
|
||||
GenericEnvironment *env =
|
||||
checkExtensionGenericParams(*this, ext, extendedType, genericParams);
|
||||
ext->setGenericEnvironment(env);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -76,7 +76,7 @@ static void checkGenericParamList(TypeChecker &tc,
|
||||
|
||||
if (auto decl = owner.dc->getAsDecl()) {
|
||||
if (auto extDecl = dyn_cast<ExtensionDecl>(decl)) {
|
||||
auto extType = extDecl->getExtendedType();
|
||||
auto extType = extDecl->getDeclaredInterfaceType();
|
||||
auto extSelfType = extDecl->getSelfInterfaceType();
|
||||
auto reqLHSType = req.getFirstType();
|
||||
auto reqRHSType = req.getSecondType();
|
||||
|
||||
@@ -536,11 +536,20 @@ Type TypeChecker::resolveTypeInContext(
|
||||
parentDC = parentDC->getParent()) {
|
||||
if (auto *ext = dyn_cast<ExtensionDecl>(parentDC)) {
|
||||
auto extendedType = ext->getExtendedType();
|
||||
if (auto *aliasType = dyn_cast<TypeAliasType>(extendedType.getPointer())) {
|
||||
if (aliasType->getDecl() == aliasDecl) {
|
||||
if (auto *unboundGeneric = dyn_cast<UnboundGenericType>(extendedType.getPointer())) {
|
||||
if (auto *ugAliasDecl = dyn_cast<TypeAliasDecl>(unboundGeneric->getAnyGeneric())) {
|
||||
if (ugAliasDecl == aliasDecl)
|
||||
return resolution.mapTypeIntoContext(
|
||||
aliasDecl->getDeclaredInterfaceType());
|
||||
|
||||
extendedType = unboundGeneric->getParent();
|
||||
continue;
|
||||
}
|
||||
}
|
||||
if (auto *aliasType = dyn_cast<TypeAliasType>(extendedType.getPointer())) {
|
||||
if (aliasType->getDecl() == aliasDecl)
|
||||
return resolution.mapTypeIntoContext(
|
||||
aliasDecl->getDeclaredInterfaceType());
|
||||
|
||||
extendedType = aliasType->getParent();
|
||||
continue;
|
||||
|
||||
@@ -3931,9 +3931,8 @@ public:
|
||||
MF.configureGenericEnvironment(extension, genericEnvID);
|
||||
|
||||
auto baseTy = MF.getType(baseID);
|
||||
auto nominal = baseTy->getAnyNominal();
|
||||
assert(!baseTy->hasUnboundGenericType());
|
||||
extension->getExtendedTypeLoc().setType(baseTy);
|
||||
auto nominal = extension->getExtendedNominal();
|
||||
|
||||
if (isImplicit)
|
||||
extension->setImplicit();
|
||||
|
||||
@@ -2871,7 +2871,6 @@ public:
|
||||
|
||||
auto contextID = S.addDeclContextRef(extension->getDeclContext());
|
||||
Type baseTy = extension->getExtendedType();
|
||||
assert(!baseTy->hasUnboundGenericType());
|
||||
assert(!baseTy->hasArchetype());
|
||||
|
||||
// FIXME: Use the canonical type here in order to minimize circularity
|
||||
|
||||
@@ -73,7 +73,7 @@ struct NonRecur: P2 {
|
||||
// Conditional conformance.
|
||||
|
||||
struct Generic<T> {}
|
||||
// CHECK-LABEL: ExtensionDecl line={{.*}} base=Generic<T>
|
||||
// CHECK-LABEL: ExtensionDecl line={{.*}} base=Generic
|
||||
// CHECK-NEXT: (normal_conformance type=Generic<T> protocol=P1
|
||||
// CHECK-NEXT: (assoc_type req=A type=T)
|
||||
// CHECK-NEXT: (value req=f() witness=main.(file).Generic extension.f()@{{.*}})
|
||||
@@ -86,7 +86,7 @@ extension Generic: P1 where T: P1 {
|
||||
|
||||
// Satisfying associated types with requirements with generic params
|
||||
class Super<T, U> {}
|
||||
// CHECK-LABEL: ExtensionDecl line={{.*}} base=Super<T, U>
|
||||
// CHECK-LABEL: ExtensionDecl line={{.*}} base=Super
|
||||
// CHECK-NEXT: (normal_conformance type=Super<T, U> protocol=P2
|
||||
// CHECK-NEXT: (assoc_type req=A type=T)
|
||||
// CHECK-NEXT: (assoc_type req=B type=T)
|
||||
|
||||
@@ -21,7 +21,7 @@ func takes_P2<X: P2>(_: X) {}
|
||||
func takes_P5<X: P5>(_: X) {}
|
||||
|
||||
struct Free<T> {}
|
||||
// CHECK-LABEL: ExtensionDecl line={{.*}} base=Free<T>
|
||||
// CHECK-LABEL: ExtensionDecl line={{.*}} base=Free
|
||||
// CHECK-NEXT: (normal_conformance type=Free<T> protocol=P2
|
||||
// CHECK-NEXT: conforms_to: T P1)
|
||||
extension Free: P2 where T: P1 {} // expected-note {{requirement from conditional conformance of 'Free<U>' to 'P2'}}
|
||||
@@ -33,7 +33,7 @@ func free_bad<U>(_: U) {
|
||||
}
|
||||
|
||||
struct Constrained<T: P1> {}
|
||||
// CHECK-LABEL: ExtensionDecl line={{.*}} base=Constrained<T>
|
||||
// CHECK-LABEL: ExtensionDecl line={{.*}} base=Constrained
|
||||
// CHECK-NEXT: (normal_conformance type=Constrained<T> protocol=P2
|
||||
// CHECK-NEXT: conforms_to: T P3)
|
||||
extension Constrained: P2 where T: P3 {} // expected-note {{requirement from conditional conformance of 'Constrained<U>' to 'P2'}}
|
||||
@@ -45,17 +45,17 @@ func constrained_bad<U: P1>(_: U) {
|
||||
}
|
||||
|
||||
struct RedundantSame<T: P1> {}
|
||||
// CHECK-LABEL: ExtensionDecl line={{.*}} base=RedundantSame<T>
|
||||
// CHECK-LABEL: ExtensionDecl line={{.*}} base=RedundantSame
|
||||
// CHECK-NEXT: (normal_conformance type=RedundantSame<T> protocol=P2)
|
||||
extension RedundantSame: P2 where T: P1 {}
|
||||
|
||||
struct RedundantSuper<T: P4> {}
|
||||
// CHECK-LABEL: ExtensionDecl line={{.*}} base=RedundantSuper<T>
|
||||
// CHECK-LABEL: ExtensionDecl line={{.*}} base=RedundantSuper
|
||||
// CHECK-NEXT: (normal_conformance type=RedundantSuper<T> protocol=P2)
|
||||
extension RedundantSuper: P2 where T: P1 {}
|
||||
|
||||
struct OverlappingSub<T: P1> {}
|
||||
// CHECK-LABEL: ExtensionDecl line={{.*}} base=OverlappingSub<T>
|
||||
// CHECK-LABEL: ExtensionDecl line={{.*}} base=OverlappingSub
|
||||
// CHECK-NEXT: (normal_conformance type=OverlappingSub<T> protocol=P2
|
||||
// CHECK-NEXT: conforms_to: T P4)
|
||||
extension OverlappingSub: P2 where T: P4 {} // expected-note {{requirement from conditional conformance of 'OverlappingSub<U>' to 'P2'}}
|
||||
@@ -68,7 +68,7 @@ func overlapping_sub_bad<U: P1>(_: U) {
|
||||
|
||||
|
||||
struct SameType<T> {}
|
||||
// CHECK-LABEL: ExtensionDecl line={{.*}} base=SameType<T>
|
||||
// CHECK-LABEL: ExtensionDecl line={{.*}} base=SameType
|
||||
// CHECK-NEXT: (normal_conformance type=SameType<T> protocol=P2
|
||||
// CHECK-NEXT: same_type: T Int)
|
||||
extension SameType: P2 where T == Int {}
|
||||
@@ -84,7 +84,7 @@ func same_type_bad<U>(_: U) {
|
||||
|
||||
|
||||
struct SameTypeGeneric<T, U> {}
|
||||
// CHECK-LABEL: ExtensionDecl line={{.*}} base=SameTypeGeneric<T, U>
|
||||
// CHECK-LABEL: ExtensionDecl line={{.*}} base=SameTypeGeneric
|
||||
// CHECK-NEXT: (normal_conformance type=SameTypeGeneric<T, U> protocol=P2
|
||||
// CHECK-NEXT: same_type: T U)
|
||||
extension SameTypeGeneric: P2 where T == U {}
|
||||
@@ -108,7 +108,7 @@ func same_type_bad<U, V>(_: U, _: V) {
|
||||
|
||||
|
||||
struct Infer<T, U> {}
|
||||
// CHECK-LABEL: ExtensionDecl line={{.*}} base=Infer<T, U>
|
||||
// CHECK-LABEL: ExtensionDecl line={{.*}} base=Infer
|
||||
// CHECK-NEXT: (normal_conformance type=Infer<T, U> protocol=P2
|
||||
// CHECK-NEXT: same_type: T Constrained<U>
|
||||
// CHECK-NEXT: conforms_to: U P1)
|
||||
@@ -126,7 +126,7 @@ func infer_bad<U: P1, V>(_: U, _: V) {
|
||||
}
|
||||
|
||||
struct InferRedundant<T, U: P1> {}
|
||||
// CHECK-LABEL: ExtensionDecl line={{.*}} base=InferRedundant<T, U>
|
||||
// CHECK-LABEL: ExtensionDecl line={{.*}} base=InferRedundant
|
||||
// CHECK-NEXT: (normal_conformance type=InferRedundant<T, U> protocol=P2
|
||||
// CHECK-NEXT: same_type: T Constrained<U>)
|
||||
extension InferRedundant: P2 where T == Constrained<U> {}
|
||||
@@ -146,7 +146,7 @@ class C2: C1 {}
|
||||
class C3: C2 {}
|
||||
|
||||
struct ClassFree<T> {}
|
||||
// CHECK-LABEL: ExtensionDecl line={{.*}} base=ClassFree<T>
|
||||
// CHECK-LABEL: ExtensionDecl line={{.*}} base=ClassFree
|
||||
// CHECK-NEXT: (normal_conformance type=ClassFree<T> protocol=P2
|
||||
// CHECK-NEXT: superclass: T C1)
|
||||
extension ClassFree: P2 where T: C1 {}
|
||||
@@ -159,7 +159,7 @@ func class_free_bad<U>(_: U) {
|
||||
}
|
||||
|
||||
struct ClassMoreSpecific<T: C1> {}
|
||||
// CHECK-LABEL: ExtensionDecl line={{.*}} base=ClassMoreSpecific<T>
|
||||
// CHECK-LABEL: ExtensionDecl line={{.*}} base=ClassMoreSpecific
|
||||
// CHECK-NEXT: (normal_conformance type=ClassMoreSpecific<T> protocol=P2
|
||||
// CHECK-NEXT: superclass: T C3)
|
||||
extension ClassMoreSpecific: P2 where T: C3 {} // expected-note {{requirement from conditional conformance of 'ClassMoreSpecific<U>' to 'P2'}}
|
||||
@@ -173,7 +173,7 @@ func class_more_specific_bad<U: C1>(_: U) {
|
||||
|
||||
|
||||
struct ClassLessSpecific<T: C3> {}
|
||||
// CHECK-LABEL: ExtensionDecl line={{.*}} base=ClassLessSpecific<T>
|
||||
// CHECK-LABEL: ExtensionDecl line={{.*}} base=ClassLessSpecific
|
||||
// CHECK-NEXT: (normal_conformance type=ClassLessSpecific<T> protocol=P2)
|
||||
extension ClassLessSpecific: P2 where T: C1 {}
|
||||
|
||||
@@ -195,11 +195,11 @@ func subclass_bad() {
|
||||
// Inheriting conformances:
|
||||
|
||||
struct InheritEqual<T> {}
|
||||
// CHECK-LABEL: ExtensionDecl line={{.*}} base=InheritEqual<T>
|
||||
// CHECK-LABEL: ExtensionDecl line={{.*}} base=InheritEqual
|
||||
// CHECK-NEXT: (normal_conformance type=InheritEqual<T> protocol=P2
|
||||
// CHECK-NEXT: conforms_to: T P1)
|
||||
extension InheritEqual: P2 where T: P1 {} // expected-note {{requirement from conditional conformance of 'InheritEqual<U>' to 'P2'}}
|
||||
// CHECK-LABEL: ExtensionDecl line={{.*}} base=InheritEqual<T>
|
||||
// CHECK-LABEL: ExtensionDecl line={{.*}} base=InheritEqual
|
||||
// CHECK-NEXT: (normal_conformance type=InheritEqual<T> protocol=P5
|
||||
// CHECK-NEXT: (normal_conformance type=InheritEqual<T> protocol=P2
|
||||
// CHECK-NEXT: conforms_to: T P1)
|
||||
@@ -223,11 +223,11 @@ extension InheritLess: P5 {} // expected-error{{type 'T' does not conform to pro
|
||||
|
||||
|
||||
struct InheritMore<T> {}
|
||||
// CHECK-LABEL: ExtensionDecl line={{.*}} base=InheritMore<T>
|
||||
// CHECK-LABEL: ExtensionDecl line={{.*}} base=InheritMore
|
||||
// CHECK-NEXT: (normal_conformance type=InheritMore<T> protocol=P2
|
||||
// CHECK-NEXT: conforms_to: T P1)
|
||||
extension InheritMore: P2 where T: P1 {} // expected-note {{requirement from conditional conformance of 'InheritMore<U>' to 'P2'}}
|
||||
// CHECK-LABEL: ExtensionDecl line={{.*}} base=InheritMore<T>
|
||||
// CHECK-LABEL: ExtensionDecl line={{.*}} base=InheritMore
|
||||
// CHECK-NEXT: (normal_conformance type=InheritMore<T> protocol=P5
|
||||
// CHECK-NEXT: (normal_conformance type=InheritMore<T> protocol=P2
|
||||
// CHECK-NEXT: conforms_to: T P1)
|
||||
@@ -310,12 +310,12 @@ extension TwoDisjointConformances: P2 where T == String {}
|
||||
// signature, meaning the stored conditional requirement is T: P1, which isn't
|
||||
// true in the original type's generic signature.
|
||||
struct RedundancyOrderDependenceGood<T: P1, U> {}
|
||||
// CHECK-LABEL: ExtensionDecl line={{.*}} base=RedundancyOrderDependenceGood<T, U>
|
||||
// CHECK-LABEL: ExtensionDecl line={{.*}} base=RedundancyOrderDependenceGood
|
||||
// CHECK-NEXT: (normal_conformance type=RedundancyOrderDependenceGood<T, U> protocol=P2
|
||||
// CHECK-NEXT: same_type: T U)
|
||||
extension RedundancyOrderDependenceGood: P2 where U: P1, T == U {}
|
||||
struct RedundancyOrderDependenceBad<T, U: P1> {}
|
||||
// CHECK-LABEL: ExtensionDecl line={{.*}} base=RedundancyOrderDependenceBad<T, U>
|
||||
// CHECK-LABEL: ExtensionDecl line={{.*}} base=RedundancyOrderDependenceBad
|
||||
// CHECK-NEXT: (normal_conformance type=RedundancyOrderDependenceBad<T, U> protocol=P2
|
||||
// CHECK-NEXT: conforms_to: T P1
|
||||
// CHECK-NEXT: same_type: T U)
|
||||
|
||||
10
test/Sema/Inputs/composition_extensions_usage.swift
Normal file
10
test/Sema/Inputs/composition_extensions_usage.swift
Normal file
@@ -0,0 +1,10 @@
|
||||
struct S {}
|
||||
|
||||
extension S : P2 {}
|
||||
|
||||
extension S : P1_1 {}
|
||||
|
||||
func f() {
|
||||
let s = S.init()
|
||||
s.p1_1()
|
||||
}
|
||||
19
test/Sema/composition_extensions.swift
Normal file
19
test/Sema/composition_extensions.swift
Normal file
@@ -0,0 +1,19 @@
|
||||
// XFAIL: *
|
||||
// RUN: %empty-directory(%t)
|
||||
// RUN: %target-swift-frontend -primary-file %s %S/Inputs/composition_extensions_usage.swift -emit-module-path %t/P-partial.swiftmodule -module-name SR11227 -enable-testing
|
||||
// RUN: %target-swift-frontend -primary-file %S/Inputs/composition_extensions_usage.swift %s -emit-module-path %t/S-partial.swiftmodule -module-name SR11227 -enable-testing
|
||||
// RUN: %target-swift-frontend -sil-merge-partial-modules %t/P-partial.swiftmodule %t/S-partial.swiftmodule -emit-module -o %t/SR11227.swiftmodule
|
||||
|
||||
protocol P0 {}
|
||||
|
||||
protocol P1 {}
|
||||
|
||||
protocol P1_1 : P1 {
|
||||
func p1_1()
|
||||
}
|
||||
|
||||
protocol P2 {}
|
||||
|
||||
extension P1 & P1_1 where Self : P2 {
|
||||
func p1_1() {}
|
||||
}
|
||||
@@ -21,13 +21,13 @@ extension Zahl {
|
||||
|
||||
public typealias List<T> = Array<T>
|
||||
|
||||
// CHECK-LABEL: extension Array {
|
||||
// CHECK-LABEL: extension List {
|
||||
extension List {
|
||||
// CHECK-NEXT: addedMember()
|
||||
public func addedMember() {}
|
||||
} // CHECK-NEXT: {{^}$}}
|
||||
|
||||
// CHECK-LABEL: extension Array where Element == Int {
|
||||
// CHECK-LABEL: extension List where Element == Int {
|
||||
extension List where Element == Int {
|
||||
// CHECK-NEXT: addedMemberInt()
|
||||
public func addedMemberInt() {}
|
||||
|
||||
@@ -22,7 +22,7 @@ extension MyNonGenericType {}
|
||||
|
||||
// CHECK-DAG: typealias MyGenericType<T> = GenericType<T>
|
||||
typealias MyGenericType<T: NSObject> = GenericType<T>
|
||||
// CHECK-DAG: extension GenericType where Element : NSObject
|
||||
// CHECK-DAG: extension MyGenericType where Element : NSObject
|
||||
extension MyGenericType {}
|
||||
// CHECK-DAG: extension GenericType where Element == NSObject
|
||||
// CHECK-DAG: extension MyGenericType where Element == NSObject
|
||||
extension MyGenericType where Element == NSObject {}
|
||||
|
||||
Reference in New Issue
Block a user