diff --git a/include/swift/AST/ArchetypeBuilder.h b/include/swift/AST/ArchetypeBuilder.h index 998aa89336f12..f2d843e1f5b93 100644 --- a/include/swift/AST/ArchetypeBuilder.h +++ b/include/swift/AST/ArchetypeBuilder.h @@ -305,8 +305,11 @@ class ArchetypeBuilder { /// Finalize the set of requirements, performing any remaining checking /// required before generating archetypes. /// + /// \param allowConcreteGenericParams If true, allow generic parameters to + /// be made concrete. + /// /// \returns true if an error occurs, false otherwise. - bool finalize(SourceLoc loc); + bool finalize(SourceLoc loc, bool allowConcreteGenericParams=false); /// \brief Resolve the given type to the potential archetype it names. /// diff --git a/lib/AST/ArchetypeBuilder.cpp b/lib/AST/ArchetypeBuilder.cpp index 6a3fb1ec6c3f7..d109d76eddcf9 100644 --- a/lib/AST/ArchetypeBuilder.cpp +++ b/lib/AST/ArchetypeBuilder.cpp @@ -1155,15 +1155,6 @@ bool ArchetypeBuilder::addSameTypeRequirementBetweenArchetypes( compareDependentTypes(&T2, &T1) < 0)) std::swap(T1, T2); - // Don't allow two generic parameters to be equivalent, because then we - // don't actually have two parameters. - // FIXME: Should we simply allow this? - if (T1Depth == 0 && T2Depth == 0) { - Diags.diagnose(Source.getLoc(), diag::requires_generic_params_made_equal, - T1->getName(), T2->getName()); - return true; - } - // Merge any concrete constraints. Type concrete1 = T1->ArchetypeOrConcreteType.getAsConcreteType(); Type concrete2 = T2->ArchetypeOrConcreteType.getAsConcreteType(); @@ -1248,16 +1239,6 @@ bool ArchetypeBuilder::addSameTypeRequirementToConcrete( return false; } - // Don't allow a generic parameter to be equivalent to a concrete type, - // because then we don't actually have a parameter. - // FIXME: Should we simply allow this? - if (T->getNestingDepth() == 0) { - Diags.diagnose(Source.getLoc(), - diag::requires_generic_param_made_equal_to_concrete, - T->getName()); - return true; - } - // Make sure the concrete type fulfills the requirements on the archetype. DenseMap conformances; if (!Concrete->is()) { @@ -1752,8 +1733,67 @@ static Identifier typoCorrectNestedType( return bestMatches.front(); } -bool ArchetypeBuilder::finalize(SourceLoc loc) { +bool +ArchetypeBuilder::finalize(SourceLoc loc, bool allowConcreteGenericParams) { bool invalid = false; + SmallPtrSet visited; + + // Check for generic parameters which have been made concrete or equated + // with each other. + if (!allowConcreteGenericParams) { + unsigned depth = 0; + for (const auto &pair : Impl->PotentialArchetypes) { + depth = std::max(depth, pair.second->getRootParam()->getDepth()); + } + + for (const auto &pair : Impl->PotentialArchetypes) { + auto pa = pair.second; + auto rep = pa->getRepresentative(); + + if (pa->getRootParam()->getDepth() < depth) + continue; + + if (!visited.insert(rep).second) + continue; + + // Don't allow a generic parameter to be equivalent to a concrete type, + // because then we don't actually have a parameter. + if (rep->ArchetypeOrConcreteType.getAsConcreteType()) { + auto &Source = rep->SameTypeSource; + + // For auto-generated locations, we should have diagnosed the problem + // elsewhere already. + if (!Source->getLoc().isValid()) + continue; + + Diags.diagnose(Source->getLoc(), + diag::requires_generic_param_made_equal_to_concrete, + rep->getName()); + invalid = true; + continue; + } + + // Don't allow two generic parameters to be equivalent, because then we + // don't actually have two parameters. + for (auto other : rep->getEquivalenceClass()) { + if (pa != other && other->getParent() == nullptr) { + auto &Source = (other == rep ? pa->SameTypeSource + : other->SameTypeSource); + + // For auto-generated locations, we should have diagnosed the problem + // elsewhere already. + if (!Source->getLoc().isValid()) + continue; + + Diags.diagnose(Source->getLoc(), + diag::requires_generic_params_made_equal, + pa->getName(), other->getName()); + invalid = true; + break; + } + } + } + } // If any nested types remain unresolved, produce diagnostics. if (Impl->NumUnresolvedNestedTypes > 0) { diff --git a/lib/SIL/SILPrinter.cpp b/lib/SIL/SILPrinter.cpp index dc2fc53c81fbf..1ef6f7f143b8f 100644 --- a/lib/SIL/SILPrinter.cpp +++ b/lib/SIL/SILPrinter.cpp @@ -1817,7 +1817,8 @@ void SILFunction::print(SILPrintContext &PrintCtx) const { unsigned disambiguatedNameCounter = 1; for (auto *paramTy : sig->getGenericParams()) { auto *archetypeTy = mapTypeIntoContext(paramTy)->getAs(); - assert(archetypeTy); + if (!archetypeTy) + continue; Identifier name = archetypeTy->getName(); while (!UsedNames.insert(name).second) { diff --git a/lib/SIL/TypeLowering.cpp b/lib/SIL/TypeLowering.cpp index 970fef526f7bc..3de69daabb679 100644 --- a/lib/SIL/TypeLowering.cpp +++ b/lib/SIL/TypeLowering.cpp @@ -1678,11 +1678,10 @@ TypeConverter::getEffectiveGenericEnvironment(AnyFunctionRef fn, CaptureInfo captureInfo) { auto dc = fn.getAsDeclContext(); - if (dc->getParent()->isLocalContext() && - !captureInfo.hasGenericParamCaptures()) - return nullptr; + if (getEffectiveGenericSignature(fn, captureInfo)) + return dc->getGenericEnvironmentOfContext(); - return dc->getGenericEnvironmentOfContext(); + return nullptr; } CanGenericSignature @@ -1694,8 +1693,11 @@ TypeConverter::getEffectiveGenericSignature(AnyFunctionRef fn, !captureInfo.hasGenericParamCaptures()) return nullptr; - if (auto sig = dc->getGenericSignatureOfContext()) + if (auto sig = dc->getGenericSignatureOfContext()) { + if (sig->areAllParamsConcrete()) + return nullptr; return sig->getCanonicalSignature(); + } return nullptr; } @@ -1990,18 +1992,33 @@ getMaterializeForSetCallbackType(AbstractStorageDecl *storage, } } + CanType canSelfType; + CanType canSelfMetatypeType; + if (genericSig) { + canSelfType = genericSig->getCanonicalTypeInContext( + selfType, *M.getSwiftModule()); + canSelfMetatypeType = genericSig->getCanonicalTypeInContext( + selfMetatypeType, *M.getSwiftModule()); + } else { + canSelfType = selfType->getCanonicalType(); + canSelfMetatypeType = selfMetatypeType->getCanonicalType(); + } + // Create the SILFunctionType for the callback. SILParameterInfo params[] = { { ctx.TheRawPointerType, ParameterConvention::Direct_Unowned }, { ctx.TheUnsafeValueBufferType, ParameterConvention::Indirect_Inout }, - { selfType->getCanonicalType(), ParameterConvention::Indirect_Inout }, - { selfMetatypeType->getCanonicalType(), ParameterConvention::Direct_Unowned }, + { canSelfType, ParameterConvention::Indirect_Inout }, + { canSelfMetatypeType, ParameterConvention::Direct_Unowned }, }; ArrayRef results = {}; auto extInfo = SILFunctionType::ExtInfo() .withRepresentation(SILFunctionTypeRepresentation::Thin); + if (genericSig && genericSig->areAllParamsConcrete()) + genericSig = nullptr; + return SILFunctionType::get(genericSig, extInfo, /*callee*/ ParameterConvention::Direct_Unowned, params, results, None, ctx); diff --git a/lib/Sema/ConstraintSystem.cpp b/lib/Sema/ConstraintSystem.cpp index a08570dc83616..c9fef777d2d10 100644 --- a/lib/Sema/ConstraintSystem.cpp +++ b/lib/Sema/ConstraintSystem.cpp @@ -1044,20 +1044,19 @@ void ConstraintSystem::openGeneric( ConstraintLocatorBuilder locator, llvm::DenseMap &replacements) { auto locatorPtr = getConstraintLocator(locator); - auto *genericEnv = innerDC->getGenericEnvironmentOfContext(); // Create the type variables for the generic parameters. for (auto gp : params) { auto contextTy = genericEnv->mapTypeIntoContext(gp); - if (auto *archetype = contextTy->getAs()) { - auto typeVar = createTypeVariable(getConstraintLocator( - locator.withPathElement( - LocatorPathElt(archetype))), - TVO_PrefersSubtypeBinding | - TVO_MustBeMaterializable); - replacements[gp->getCanonicalType()] = typeVar; - } + if (auto *archetype = contextTy->getAs()) + locatorPtr = getConstraintLocator( + locator.withPathElement(LocatorPathElt(archetype))); + + auto typeVar = createTypeVariable(locatorPtr, + TVO_PrefersSubtypeBinding | + TVO_MustBeMaterializable); + replacements[gp->getCanonicalType()] = typeVar; } GetTypeVariable getTypeVariable{*this, locator}; diff --git a/lib/Sema/TypeCheckDecl.cpp b/lib/Sema/TypeCheckDecl.cpp index 13cf5bab82653..b8018c9257d9c 100644 --- a/lib/Sema/TypeCheckDecl.cpp +++ b/lib/Sema/TypeCheckDecl.cpp @@ -730,6 +730,7 @@ TypeChecker::handleSILGenericParams(GenericParamList *genericParams, auto genericParams = nestedList.rbegin()[i]; bool invalid = false; auto *genericSig = validateGenericSignature(genericParams, DC, parentSig, + /*allowConcreteGenericParams=*/true, nullptr, invalid); if (invalid) return std::make_pair(nullptr, nullptr); @@ -7545,11 +7546,10 @@ static Type checkExtensionGenericParams( bool invalid = false; auto *parentSig = ext->getDeclContext()->getGenericSignatureOfContext(); auto *parentEnv = ext->getDeclContext()->getGenericEnvironmentOfContext(); - GenericSignature *sig = tc.validateGenericSignature( - genericParams, - ext->getDeclContext(), - parentSig, - inferExtendedTypeReqs, invalid); + auto *sig = tc.validateGenericSignature(genericParams, + ext->getDeclContext(), parentSig, + /*allowConcreteGenericParams=*/true, + inferExtendedTypeReqs, invalid); ext->setGenericSignature(sig); if (invalid) { diff --git a/lib/Sema/TypeCheckGeneric.cpp b/lib/Sema/TypeCheckGeneric.cpp index 08333ad7ab23c..5a5760a977d3f 100644 --- a/lib/Sema/TypeCheckGeneric.cpp +++ b/lib/Sema/TypeCheckGeneric.cpp @@ -725,6 +725,7 @@ GenericSignature *TypeChecker::validateGenericSignature( GenericParamList *genericParams, DeclContext *dc, GenericSignature *parentSig, + bool allowConcreteGenericParams, std::function inferRequirements, bool &invalid) { assert(genericParams && "Missing generic parameters?"); @@ -747,7 +748,8 @@ GenericSignature *TypeChecker::validateGenericSignature( } // Finalize the generic requirements. - (void)builder.finalize(genericParams->getSourceRange().Start); + (void)builder.finalize(genericParams->getSourceRange().Start, + allowConcreteGenericParams); // The archetype builder now has all of the requirements, although there might // still be errors that have not yet been diagnosed. Revert the signature @@ -920,6 +922,7 @@ bool TypeChecker::validateGenericTypeSignature(GenericTypeDecl *typeDecl) { } auto *sig = validateGenericSignature(gp, dc, dc->getGenericSignatureOfContext(), + /*allowConcreteGenericParams=*/false, nullptr, invalid); assert(sig->getInnermostGenericParams().size() == typeDecl->getGenericParams()->size()); diff --git a/lib/Sema/TypeChecker.h b/lib/Sema/TypeChecker.h index c6b51139591e4..b19113b38b544 100644 --- a/lib/Sema/TypeChecker.h +++ b/lib/Sema/TypeChecker.h @@ -1056,6 +1056,7 @@ class TypeChecker final : public LazyResolver { GenericParamList *genericParams, DeclContext *dc, GenericSignature *outerSignature, + bool allowConcreteGenericParams, std::function inferRequirements, bool &invalid); diff --git a/test/Constraints/same_types.swift b/test/Constraints/same_types.swift index cdc6413556157..097f6a0dfa21c 100644 --- a/test/Constraints/same_types.swift +++ b/test/Constraints/same_types.swift @@ -111,7 +111,7 @@ func testAssocTypeEquivalence(_ fooable: T) -> X.Type } func fail6(_ t: T) -> Int where T == Int { // expected-error{{same-type requirement makes generic parameter 'T' non-generic}} - return t // expected-error{{cannot convert return expression of type 'T' to return type 'Int'}} + return t } func test8(_ t: T, u: U) -> (Y, Y, X, X) @@ -142,3 +142,66 @@ struct BadFooable : Fooable { func bogusInOutError(d: inout Brunch) {} // expected-error@-1{{'Brunch' requires the types '<>' and 'X' be equivalent}} +// Some interesting invalid cases that used to crash +protocol P { + associatedtype A + associatedtype B +} + +struct Q : P { + typealias A = Int + typealias B = Int +} + +struct S1 { + func foo(x: X, y: Y) where X == T.A, Y == T.B { + print(X.self) + print(Y.self) + print(x) + print(y) + } +} +S1().foo(x: 1, y: 2) + +struct S2 where T.A == T.B { + // expected-error@+1 {{same-type requirement makes generic parameters 'X' and 'Y' equivalent}} + func foo(x: X, y: Y) where X == T.A, Y == T.B { + print(X.self) + print(Y.self) + print(x) + print(y) + } +} +S2().foo(x: 1, y: 2) + +struct S3 { + // expected-error@+1 {{same-type requirement makes generic parameters 'X' and 'Y' equivalent}} + func foo(x: X, y: Y) where X == T.A, Y == T.A {} +} +S3().foo(x: 1, y: 2) + +// Secondaries can be equated OK, even if we're imposing +// new conformances onto an outer secondary + +protocol PPP {} + +protocol PP { + associatedtype A : PPP +} + +struct SSS : PPP {} +struct SS : PP { typealias A = SSS } + +struct QQ : P { + typealias A = SSS + typealias B = Int +} + +struct S4 { + func foo(x: X) where X.A == T.A { + print(x) + print(X.self) + } +} + +S4().foo(x: SS()) diff --git a/test/Generics/function_defs.swift b/test/Generics/function_defs.swift index 15bd40c9d81f0..c48f778c854b1 100644 --- a/test/Generics/function_defs.swift +++ b/test/Generics/function_defs.swift @@ -294,5 +294,5 @@ func badTypeConformance1(_: T) where Int : EqualComparable {} // expected-err func badTypeConformance2(_: T) where T.Blarg : EqualComparable { } // expected-error{{'Blarg' is not a member type of 'T'}} -func badSameType(_ : T) // expected-error{{generic parameter 'V' is not used in function signature}} +func badSameType(_ : T) where T == U.Element, U.Element == V {} // expected-error{{same-type requirement makes generic parameters 'T' and 'V' equivalent}} diff --git a/test/SILGen/constrained_extensions.swift b/test/SILGen/constrained_extensions.swift new file mode 100644 index 0000000000000..0fb0779c6954c --- /dev/null +++ b/test/SILGen/constrained_extensions.swift @@ -0,0 +1,117 @@ +// RUN: %target-swift-frontend -emit-silgen %s | %FileCheck %s +// RUN: %target-swift-frontend -emit-ir %s +// RUN: %target-swift-frontend -emit-ir -O %s + +extension Array where Element == Int { + // CHECK-LABEL: sil @_TFe22constrained_extensionsRxzSirSag16instancePropertySi : $@convention(method) (@guaranteed Array) -> Int + // CHECK-LABEL: sil @_TFe22constrained_extensionsRxzSirSas16instancePropertySi : $@convention(method) (Int, @inout Array) -> () + // CHECK-LABEL: sil [transparent] [fragile] @_TFe22constrained_extensionsRxzSirSam16instancePropertySi : $@convention(method) (Builtin.RawPointer, @inout Builtin.UnsafeValueBuffer, @inout Array) -> (Builtin.RawPointer, Optional) + // CHECK-LABEL: sil [transparent] [fragile] @_TFFe22constrained_extensionsRxzSirSam16instancePropertySiU_T_ : $@convention(thin) (Builtin.RawPointer, @inout Builtin.UnsafeValueBuffer, @inout Array, @thick Array.Type) -> () + public var instanceProperty: Element { + get { + return self[0] + } + set { + self[0] = newValue + } + } + + // CHECK-LABEL: sil @_TFe22constrained_extensionsRxzSirSa14instanceMethodfT_x : $@convention(method) (@guaranteed Array) -> Int + public func instanceMethod() -> Element { + return instanceProperty + } + + // CHECK-LABEL: sil @_TFe22constrained_extensionsRxzSirSa14instanceMethodfT1ex_x : $@convention(method) (Int, @guaranteed Array) -> Int + public func instanceMethod(e: Element) -> Element { + return e + } + + // CHECK-LABEL: sil @_TZFe22constrained_extensionsRxzSirSag14staticPropertySi : $@convention(method) (@thin Array.Type) -> Int + public static var staticProperty: Element { + return 0 + } + + // CHECK-LABEL: sil @_TZFe22constrained_extensionsRxzSirSa12staticMethodfT_x : $@convention(method) (@thin Array.Type) -> Int + public static func staticMethod() -> Element { + return staticProperty + } + + // CHECK-LABEL: sil @_TIZFe22constrained_extensionsRxzSirSa12staticMethodFT1eGSqx__xA_ : $@convention(thin) () -> Optional + // CHECK-LABEL: sil @_TZFe22constrained_extensionsRxzSirSa12staticMethodfT1eGSqx__x : $@convention(method) (Optional, @thin Array.Type) -> Int + public static func staticMethod(e: Element? = nil) -> Element { + return e! + } + + // CHECK-LABEL: sil @_TFe22constrained_extensionsRxzSirSag9subscriptFT_Si : $@convention(method) (@guaranteed Array) -> Int + public subscript(i: ()) -> Element { + return self[0] + } + + // CHECK-LABEL: sil @_TFe22constrained_extensionsRxzSirSa21inoutAccessOfPropertyfT_T_ : $@convention(method) (@inout Array) -> () + public mutating func inoutAccessOfProperty() { + func increment(x: inout Element) { + x += 1 + } + + increment(x: &instanceProperty) + } +} + +extension Dictionary where Key == Int { + // CHECK-LABEL: sil @_TFe22constrained_extensions0_RxzSirVs10Dictionaryg16instancePropertyq_ : $@convention(method) (@guaranteed Dictionary) -> @out Value + // CHECK-LABEL: sil @_TFe22constrained_extensions0_RxzSirVs10Dictionarys16instancePropertyq_ : $@convention(method) (@in Value, @inout Dictionary) -> () + // CHECK-LABEL: sil [transparent] [fragile] @_TFe22constrained_extensions0_RxzSirVs10Dictionarym16instancePropertyq_ : $@convention(method) (Builtin.RawPointer, @inout Builtin.UnsafeValueBuffer, @inout Dictionary) -> (Builtin.RawPointer, Optional) + // CHECK-LABEL: sil [transparent] [fragile] @_TFFe22constrained_extensions0_RxzSirVs10Dictionarym16instancePropertyq_U_T_ : $@convention(thin) (Builtin.RawPointer, @inout Builtin.UnsafeValueBuffer, @inout Dictionary, @thick Dictionary.Type) -> () + public var instanceProperty: Value { + get { + return self[0]! + } + set { + self[0] = newValue + } + } + + // CHECK-LABEL: sil @_TFe22constrained_extensions0_RxzSirVs10Dictionary14instanceMethodfT_q_ : $@convention(method) (@guaranteed Dictionary) -> @out Value + public func instanceMethod() -> Value { + return instanceProperty + } + + // CHECK-LABEL: sil @_TFe22constrained_extensions0_RxzSirVs10Dictionary14instanceMethodfT1vq__q_ : $@convention(method) (@in Value, @guaranteed Dictionary) -> @out Value + public func instanceMethod(v: Value) -> Value { + return v + } + + // CHECK-LABEL: sil @_TZFe22constrained_extensions0_RxzSirVs10Dictionary12staticMethodfT_x : $@convention(method) (@thin Dictionary.Type) -> Int + public static func staticMethod() -> Key { + return staticProperty + } + + // CHECK-LABEL: sil @_TZFe22constrained_extensions0_RxzSirVs10Dictionaryg14staticPropertySi : $@convention(method) (@thin Dictionary.Type) -> Int + public static var staticProperty: Key { + return 0 + } + + // CHECK-LABEL: sil @_TIZFe22constrained_extensions0_RxzSirVs10Dictionary12staticMethodFT1kGSqx_1vGSqq___q_A_ : $@convention(thin) () -> Optional + // CHECK-LABEL: sil @_TIZFe22constrained_extensions0_RxzSirVs10Dictionary12staticMethodFT1kGSqx_1vGSqq___q_A0_ : $@convention(thin) () -> @out Optional + // CHECK-LABEL: sil @_TZFe22constrained_extensions0_RxzSirVs10Dictionary12staticMethodfT1kGSqx_1vGSqq___q_ : $@convention(method) (Optional, @in Optional, @thin Dictionary.Type) -> @out Value + public static func staticMethod(k: Key? = nil, v: Value? = nil) -> Value { + return v! + } + + // CHECK-LABEL: sil @_TZFe22constrained_extensions0_RxzSirVs10Dictionary17callsStaticMethodfT_q_ : $@convention(method) (@thin Dictionary.Type) -> @out Value + public static func callsStaticMethod() -> Value { + return staticMethod() + } + + // CHECK-LABEL: sil @_TFe22constrained_extensions0_RxzSirVs10Dictionaryg9subscriptFT_q_ : $@convention(method) (@guaranteed Dictionary) -> @out Value + public subscript(i: ()) -> Value { + return self[0]! + } + + // CHECK-LABEL: sil @_TFe22constrained_extensions0_RxzSirVs10Dictionary21inoutAccessOfPropertyfT_T_ : $@convention(method) (@inout Dictionary) -> () + public mutating func inoutAccessOfProperty() { + func increment(x: inout Value) { } + + increment(x: &instanceProperty) + } +} diff --git a/test/SourceKit/CursorInfo/cursor_info.swift b/test/SourceKit/CursorInfo/cursor_info.swift index dcd32ecaf0383..ce0a56dab335d 100644 --- a/test/SourceKit/CursorInfo/cursor_info.swift +++ b/test/SourceKit/CursorInfo/cursor_info.swift @@ -421,32 +421,32 @@ func convention7(_: @convention(witness_method) ()->()) {} // CHECK33-NEXT: S2 // CHECK33-NEXT: s:V11cursor_info2S2 // CHECK33-NEXT: S2.Type -// CHECK33: struct S2<T, U> -// CHECK33-NEXT: struct S2<T, U> +// CHECK33: struct S2<T, U> where T == U +// CHECK33-NEXT: struct S2<T, U> where T == U // RUN: %sourcekitd-test -req=cursor -pos=81:8 %s -- -F %S/../Inputs/libIDE-mock-sdk -I %t.tmp %mcp_opt %s | %FileCheck %s -check-prefix=CHECK34 // CHECK34: source.lang.swift.decl.function.method.instance (81:8-81:50) // CHECK34-NEXT: foo(_:) -// CHECK34-NEXT: s:FV11cursor_info2S23foou0_rFFT_T_FT_T_ -// CHECK34-NEXT: (S2) -> (() -> ()) -> () -> () -// CHECK34: func foo<V, W>(_ closure: () -> ()) -> () -> () -// CHECK34-NEXT: func foo<V, W>(_ closure: () -> ()) -> () -> () +// CHECK34-NEXT: s:FV11cursor_info2S23foou0_Rd__zqd_0_rFFT_T_FT_T_ +// CHECK34-NEXT: (S2) -> (() -> ()) -> () -> () +// CHECK34: func foo<V, W>(_ closure: () -> ()) -> () -> () where V == W +// CHECK34-NEXT: func foo<V, W>(_ closure: () -> ()) -> () -> () where V == W // RUN: %sourcekitd-test -req=cursor -pos=83:7 %s -- -F %S/../Inputs/libIDE-mock-sdk -I %t.tmp %mcp_opt %s | %FileCheck %s -check-prefix=CHECK35 // CHECK35: source.lang.swift.decl.class (83:7-83:9) // CHECK35-NEXT: C4 // CHECK35-NEXT: s:C11cursor_info2C4 // CHECK35-NEXT: C4.Type -// CHECK35: class C4<T, U> -// CHECK35-NEXT: class C4<T, U> +// CHECK35: class C4<T, U> where T == U +// CHECK35-NEXT: class C4<T, U> where T == U // RUN: %sourcekitd-test -req=cursor -pos=84:6 %s -- -F %S/../Inputs/libIDE-mock-sdk -I %t.tmp %mcp_opt %s | %FileCheck %s -check-prefix=CHECK36 // CHECK36: source.lang.swift.decl.enum (84:6-84:8) // CHECK36-NEXT: E1 // CHECK36-NEXT: s:O11cursor_info2E1 // CHECK36-NEXT: E1.Type -// CHECK36: enum E1<T, U> -// CHECK36-NEXT: enum E1<T, U> +// CHECK36: enum E1<T, U> where T == U +// CHECK36-NEXT: enum E1<T, U> where T == U // RUN: %sourcekitd-test -req=cursor -pos=86:6 %s -- -F %S/../Inputs/libIDE-mock-sdk -I %t.tmp %mcp_opt %s | %FileCheck %s -check-prefix=CHECK37 // CHECK37: source.lang.swift.decl.function.free (86:6-86:111) diff --git a/test/decl/ext/generic.swift b/test/decl/ext/generic.swift index 6233f7af3db37..53fd94c3864cf 100644 --- a/test/decl/ext/generic.swift +++ b/test/decl/ext/generic.swift @@ -132,8 +132,7 @@ func genericClassNotEquatable(_ gc: GenericClass, x: T, y: T) { } -// FIXME: Future direction -extension Array where Element == String { } // expected-error{{same-type requirement makes generic parameter 'Element' non-generic}} +extension Array where Element == String { } extension GenericClass : P3 where T : P3 { } // expected-error{{extension of type 'GenericClass' with constraints cannot have an inheritance clause}} diff --git a/test/decl/protocol/req/recursion.swift b/test/decl/protocol/req/recursion.swift index d083dc14d9828..6183d46e35f35 100644 --- a/test/decl/protocol/req/recursion.swift +++ b/test/decl/protocol/req/recursion.swift @@ -7,8 +7,11 @@ protocol SomeProtocol { extension SomeProtocol where T == Optional { } // expected-error{{same-type constraint 'Self.T' == 'Optional' is recursive}} // rdar://problem/19840527 -class X where T == X { // expected-error{{same-type requirement makes generic parameter 'T' non-generic}} - var type: T { return type(of: self) } // expected-error{{cannot convert return expression of type 'X.Type' to return type 'T'}} +// FIXME: Crappy diagnostic + +class X where T == X { // expected-error{{non-class type '<>' cannot conform to class protocol 'AnyObject'}} +// expected-error@-1{{same-type requirement makes generic parameter 'T' non-generic}} + var type: T { return type(of: self) } // expected-error{{use of undeclared type 'T'}} } protocol Y { @@ -23,7 +26,7 @@ public protocol P { public struct S where A.T == S {} // expected-error{{type may not reference itself as a requirement}} protocol I { - init() // expected-note{{protocol requires initializer 'init()' with type '()'}} + init() // expected-note 2{{protocol requires initializer 'init()' with type '()'}} } protocol PI { @@ -33,18 +36,16 @@ protocol PI { struct SI : I where A : I, A.T == SI { // expected-error{{type may not reference itself as a requirement}} } -/* FIXME: Infinite recursion - +// Used to hit infinite recursion struct S4 : I where A : I { } struct S5 : I where A : I, A.T == S4 { -}*/ - -/* FIXME: Hits ArchetypeBuilder assertions +} +// Used to hit ArchetypeBuilder assertions struct SU where A.T == SU { } struct SIU : I where A : I, A.T == SIU { -}*/ +} diff --git a/test/decl/var/properties.swift b/test/decl/var/properties.swift index 5c866c8c77226..e0cad41c46bd7 100644 --- a/test/decl/var/properties.swift +++ b/test/decl/var/properties.swift @@ -1137,7 +1137,6 @@ extension rdar17391625derived { public protocol rdar27671033P {} struct rdar27671033S {} extension rdar27671033S : rdar27671033P where Key == String { // expected-error {{extension of type 'rdar27671033S' with constraints cannot have an inheritance clause}} - // expected-error@-1 {{same-type requirement makes generic parameter 'Key' non-generic}} let d = rdar27671033S() // expected-error {{extensions may not contain stored properties}} }