mirror of
https://github.com/apple/swift.git
synced 2025-12-21 12:14:44 +01:00
[SourceKit] Workaround a bug that parameterized protocols without 'any' cannot be mangled
`typealias` is currently allowed to refer to a protocol without the `any` keyword. This breaks mangling the typealias type into a USR will crash because parameterized protocols are expected to be `any` types. Implement a SourceKit-specific minimal workaround for that problem by not computing USRs for parameterized protocols. rdar://98623438
This commit is contained in:
@@ -195,6 +195,16 @@ const USRBasedType *USRBasedType::fromType(Type Ty, USRBasedTypeArena &Arena) {
|
||||
return USRBasedType::null(Arena);
|
||||
}
|
||||
|
||||
// ParameterizedProtocolType should always be wrapped in ExistentialType and
|
||||
// cannot be mangled on its own.
|
||||
// But ParameterizedProtocolType can currently occur in 'typealias'
|
||||
// declarations. rdar://99176683
|
||||
// To avoid crashing in USR generation, simply return a null type until the
|
||||
// underlying issue has been fixed.
|
||||
if (Ty->is<ParameterizedProtocolType>()) {
|
||||
return USRBasedType::null(Arena);
|
||||
}
|
||||
|
||||
SmallString<32> USR;
|
||||
llvm::raw_svector_ostream OS(USR);
|
||||
printTypeUSR(Ty, OS);
|
||||
|
||||
@@ -0,0 +1,30 @@
|
||||
// RUN: %empty-directory(%t/split)
|
||||
// RUN: %empty-directory(%t/build)
|
||||
// RUN: %{python} %utils/split_file.py -o %t/split %s
|
||||
|
||||
// RUN: %target-swift-frontend -emit-module -o %t/build %t/split/pck.swift
|
||||
|
||||
// RUN: %target-swift-ide-test -code-completion -source-filename %t/split/test.swift -I %t/build -code-completion-token=COMPLETE | %FileCheck %s
|
||||
|
||||
// BEGIN pck.swift
|
||||
|
||||
public protocol Foo<Bar> {
|
||||
associatedtype Bar
|
||||
}
|
||||
|
||||
public typealias Problem = Foo<String>
|
||||
|
||||
public protocol EmptyProto {}
|
||||
public typealias ConstrainedBar<T: EmptyProto> = Foo<T>
|
||||
|
||||
// BEGIN test.swift
|
||||
|
||||
import pck
|
||||
|
||||
#^COMPLETE^#
|
||||
|
||||
// CHECK: Begin completions
|
||||
// CHECK-DAG: Decl[Protocol]/OtherModule[pck]/Flair[RareType]: Foo[#Foo#];
|
||||
// CHECK-DAG: Decl[TypeAlias]/OtherModule[pck]: Problem[#Foo<String>#];
|
||||
// CHECK-DAG: Decl[TypeAlias]/OtherModule[pck]: ConstrainedBar[#Foo<T>#];
|
||||
// CHECK: End completions
|
||||
@@ -0,0 +1,13 @@
|
||||
// Testing that these requests don't crash
|
||||
|
||||
public protocol Foo<Bar> {
|
||||
associatedtype Bar
|
||||
}
|
||||
// RUN: %sourcekitd-test -req=cursor -pos=%(line+1):11 %s -- %s
|
||||
typealias Problem = Foo<String>
|
||||
|
||||
protocol EmptyProto {}
|
||||
// RUN: %sourcekitd-test -req=cursor -pos=%(line+1):11 %s -- %s
|
||||
typealias ConstrainedBar<T: EmptyProto> = Foo<T>
|
||||
// RUN: %sourcekitd-test -req=cursor -pos=%(line+1):11 %s -- %s
|
||||
typealias ConstrainedBarMetatype<T: P> = Foo<T>.Type
|
||||
@@ -948,6 +948,22 @@ fillSymbolInfo(CursorSymbolInfo &Symbol, const DeclInfo &DInfo,
|
||||
}
|
||||
Symbol.TypeName = copyAndClearString(Allocator, Buffer);
|
||||
|
||||
// ParameterizedProtocolType should always be wrapped in ExistentialType and
|
||||
// cannot be mangled on its own.
|
||||
// But ParameterizedProtocolType can currently occur in 'typealias'
|
||||
// declarations. rdar://99176683
|
||||
// To avoid crashing in USR generation, return an error for now.
|
||||
if (auto Ty = DInfo.VD->getInterfaceType()) {
|
||||
while (auto MetaTy = Ty->getAs<MetatypeType>()) {
|
||||
Ty = MetaTy->getInstanceType();
|
||||
}
|
||||
if (Ty && Ty->getCanonicalType()->is<ParameterizedProtocolType>()) {
|
||||
return llvm::createStringError(
|
||||
llvm::inconvertibleErrorCode(),
|
||||
"Cannot mangle USR for ParameterizedProtocolType without 'any'.");
|
||||
}
|
||||
}
|
||||
|
||||
SwiftLangSupport::printDeclTypeUSR(DInfo.VD, OS);
|
||||
Symbol.TypeUSR = copyAndClearString(Allocator, Buffer);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user