Skip to content

Commit e388c4a

Browse files
committed
[CodeCompletion] Get associatedtype constraints from ProtocolDecl::getRequirementSignature()
instead of AssociatedTypeDecl::getInherited() when checking if the return type should be suggested as "opaque result type" in override completion. AssociatedTypeDecl::getInherited() is not serialized. So if the protocol is declared in a module, it was never suggested as 'some' result. rdar://problem/57245073
1 parent 98a5c04 commit e388c4a

File tree

4 files changed

+88
-21
lines changed

4 files changed

+88
-21
lines changed

lib/AST/ASTPrinter.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3039,10 +3039,10 @@ void PrintAST::visitSubscriptDecl(SubscriptDecl *decl) {
30393039
Printer << " -> ";
30403040

30413041
TypeLoc elementTy = decl->getElementTypeLoc();
3042-
Printer.printDeclResultTypePre(decl, elementTy);
3043-
Printer.callPrintStructurePre(PrintStructureKind::FunctionReturnType);
30443042
if (!elementTy.getTypeRepr())
30453043
elementTy = TypeLoc::withoutLoc(decl->getElementInterfaceType());
3044+
Printer.printDeclResultTypePre(decl, elementTy);
3045+
Printer.callPrintStructurePre(PrintStructureKind::FunctionReturnType);
30463046

30473047
// HACK: When printing result types for subscripts with opaque result types,
30483048
// always print them using the `some` keyword instead of printing

lib/IDE/CodeCompletion.cpp

Lines changed: 41 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -4159,8 +4159,8 @@ class CompletionOverrideLookup : public swift::VisibleDeclConsumer {
41594159

41604160
/// Return type if the result type if \p VD should be represented as opaque
41614161
/// result type.
4162-
TypeLoc getOpaqueResultTypeLoc(const ValueDecl *VD, DeclVisibilityKind Reason,
4163-
DynamicLookupInfo dynamicLookupInfo) {
4162+
Type getOpaqueResultType(const ValueDecl *VD, DeclVisibilityKind Reason,
4163+
DynamicLookupInfo dynamicLookupInfo) {
41644164
if (Reason !=
41654165
DeclVisibilityKind::MemberOfProtocolImplementedByCurrentNominal)
41664166
return nullptr;
@@ -4179,41 +4179,65 @@ class CompletionOverrideLookup : public swift::VisibleDeclConsumer {
41794179
else
41804180
return nullptr;
41814181

4182-
if (!ResultT->is<DependentMemberType>())
4183-
// The result is not associatedtype.
4184-
return nullptr;
4185-
4186-
// If associatedtype doesn't have conformance/superclass constraint, we
4187-
// can't use opaque type.
4188-
auto assocTyD = ResultT->castTo<DependentMemberType>()->getAssocType();
4189-
if (!assocTyD->getInherited().size())
4182+
if (!ResultT->is<DependentMemberType>() ||
4183+
!ResultT->castTo<DependentMemberType>()->getAssocType())
4184+
// The result is not a valid associatedtype.
41904185
return nullptr;
41914186

41924187
// Try substitution to see if the associated type is resolved to concrete
41934188
// type.
41944189
auto substMap = currTy->getMemberSubstitutionMap(
41954190
CurrDeclContext->getParentModule(), VD);
4196-
ResultT = ResultT.subst(substMap);
4197-
if (!ResultT || !ResultT->is<DependentMemberType>())
4191+
if (!ResultT.subst(substMap)->is<DependentMemberType>())
41984192
// If resolved print it.
41994193
return nullptr;
42004194

4201-
return assocTyD->getInherited()[0];
4195+
// Collect requirements on the associatedtype.
4196+
ProtocolDecl *protoD =
4197+
ResultT->castTo<DependentMemberType>()->getAssocType()->getProtocol();
4198+
4199+
SmallVector<Type, 2> opaqueTypes;
4200+
bool hasExplicitAnyObject = false;
4201+
for (auto req : protoD->getRequirementSignature()) {
4202+
if (!req.getFirstType()->isEqual(ResultT))
4203+
continue;
4204+
4205+
switch (req.getKind()) {
4206+
case RequirementKind::Conformance:
4207+
case RequirementKind::Superclass:
4208+
opaqueTypes.push_back(req.getSecondType());
4209+
break;
4210+
case RequirementKind::Layout:
4211+
hasExplicitAnyObject |= req.getLayoutConstraint()->isClass();
4212+
break;
4213+
case RequirementKind::SameType:
4214+
return nullptr;
4215+
}
4216+
}
4217+
4218+
if (!hasExplicitAnyObject) {
4219+
if (opaqueTypes.empty())
4220+
return nullptr;
4221+
if (opaqueTypes.size() == 1)
4222+
return opaqueTypes.front();
4223+
}
4224+
return ProtocolCompositionType::get(
4225+
VD->getASTContext(), opaqueTypes, hasExplicitAnyObject);
42024226
}
42034227

42044228
void addValueOverride(const ValueDecl *VD, DeclVisibilityKind Reason,
42054229
DynamicLookupInfo dynamicLookupInfo,
42064230
CodeCompletionResultBuilder &Builder,
42074231
bool hasDeclIntroducer) {
42084232
class DeclPrinter : public StreamPrinter {
4209-
TypeLoc OpaqueBaseTy;
4233+
Type OpaqueBaseTy;
42104234

42114235
public:
42124236
using StreamPrinter::StreamPrinter;
42134237

42144238
Optional<unsigned> NameOffset;
42154239

4216-
DeclPrinter(raw_ostream &OS, TypeLoc OpaqueBaseTy)
4240+
DeclPrinter(raw_ostream &OS, Type OpaqueBaseTy)
42174241
: StreamPrinter(OS), OpaqueBaseTy(OpaqueBaseTy) {}
42184242

42194243
void printDeclLoc(const Decl *D) override {
@@ -4225,7 +4249,7 @@ class CompletionOverrideLookup : public swift::VisibleDeclConsumer {
42254249
void printDeclResultTypePre(ValueDecl *VD, TypeLoc &TL) override {
42264250
if (!OpaqueBaseTy.isNull()) {
42274251
OS << "some ";
4228-
TL = OpaqueBaseTy;
4252+
TL = TypeLoc::withoutLoc(OpaqueBaseTy);
42294253
}
42304254
}
42314255
};
@@ -4235,7 +4259,7 @@ class CompletionOverrideLookup : public swift::VisibleDeclConsumer {
42354259
{
42364260
llvm::raw_svector_ostream OS(DeclStr);
42374261
DeclPrinter Printer(
4238-
OS, getOpaqueResultTypeLoc(VD, Reason, dynamicLookupInfo));
4262+
OS, getOpaqueResultType(VD, Reason, dynamicLookupInfo));
42394263
PrintOptions Options;
42404264
if (auto transformType = CurrDeclContext->getDeclaredTypeInContext())
42414265
Options.setBaseType(transformType);

test/IDE/complete_crossmodule.swift

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
// RUN: %empty-directory(%t)
2+
// RUN: %{python} %utils/split_file.py -o %t %s
3+
4+
// RUN: %target-swift-frontend -emit-module -o %t/MyModule.swiftmodule %t/MyModule.swift
5+
// RUN: %target-swift-ide-test -code-completion -source-filename %t/Test.swift -I %t -code-completion-token=OPAQUE_RESULT | %FileCheck --check-prefix=OPAQUE_RESULT %s
6+
7+
// BEGIN MyModule.swift
8+
9+
public protocol HasAssocWithConstraint {
10+
associatedtype AssocWithContraint: HasAssocWithConstraint
11+
var value: AssocWithContraint { get }
12+
}
13+
14+
// BEGIN Test.swift
15+
import MyModule
16+
17+
struct MyValue: HasAssocWithConstraint {
18+
var #^OPAQUE_RESULT^#
19+
// OPAQUE_RESULT: Begin completions
20+
// OPAQUE_RESULT-DAG: Decl[InstanceVar]/Super: value: some HasAssocWithConstraint;
21+
// OPAQUE_RESULT: End completions
22+
}

test/IDE/complete_opaque_result.swift

Lines changed: 23 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -102,14 +102,29 @@ protocol HasAssocWithConstraintAndDefault {
102102
associatedtype AssocWithConstraintAndDefault: MyProtocol = ConcreteMyProtocol
103103
func returnAssocWithConstraintAndDefault() -> AssocWithConstraintAndDefault
104104
}
105+
protocol HasAssocWithAnyObjectConstraint {
106+
associatedtype AssocWithAnyObjectConstraint: AnyObject & MyProtocol
107+
func returnAssocWithAnyObjectConstraint() -> AssocWithAnyObjectConstraint
108+
}
109+
protocol HasAssocWithConstraintOnProto where Self.AssocWithConstraintOnProto : MyProtocol {
110+
associatedtype AssocWithConstraintOnProto
111+
func returnAssocWithConstraintOnProto() -> AssocWithConstraintOnProto
112+
}
113+
protocol HasAssocWithSameTypeConstraint where Self.AssocWithSameTypeConstraint == MyClass {
114+
associatedtype AssocWithSameTypeConstraint
115+
func returnAssocWithSameTypeConstraint() -> AssocWithSameTypeConstraint
116+
}
105117

106118
class TestClass :
107119
HasAssocPlain,
108120
HasAssocWithConformanceConstraint,
109121
HasAssocWithSuperClassConstraint,
110122
HasAssocWithCompositionConstraint,
111123
HasAssocWithDefault,
112-
HasAssocWithConstraintAndDefault {
124+
HasAssocWithConstraintAndDefault,
125+
HasAssocWithAnyObjectConstraint,
126+
HasAssocWithConstraintOnProto,
127+
HasAssocWithSameTypeConstraint {
113128
#^OVERRIDE_TestClass^#
114129
// OVERRIDE: Begin completions
115130
// OVERRIDE-DAG: Decl[InstanceMethod]/Super: func returnAssocPlain() -> AssocPlain {|};
@@ -118,6 +133,9 @@ class TestClass :
118133
// OVERRIDE-DAG: Decl[Subscript]/Super: subscript<T>(idx: T) -> some MyClass & MyProtocol where T : Comparable {|};
119134
// OVERRIDE-DAG: Decl[InstanceMethod]/Super: func returnAssocWithDefault() -> MyEnum {|};
120135
// OVERRIDE-DAG: Decl[InstanceMethod]/Super: func returnAssocWithConstraintAndDefault() -> ConcreteMyProtocol {|};
136+
// OVERRIDE-DAG: Decl[InstanceMethod]/Super: func returnAssocWithAnyObjectConstraint() -> some MyProtocol & AnyObject {|}
137+
// OVERRIDE-DAG: Decl[InstanceMethod]/Super: func returnAssocWithConstraintOnProto() -> some MyProtocol {|}
138+
// OVERRIDE-DAG: Decl[InstanceMethod]/Super: func returnAssocWithSameTypeConstraint() -> AssocWithSameTypeConstraint {|}
121139
// OVERRIDE: End completions
122140
}
123141

@@ -127,7 +145,10 @@ struct TestStruct :
127145
HasAssocWithSuperClassConstraint,
128146
HasAssocWithCompositionConstraint,
129147
HasAssocWithDefault,
130-
HasAssocWithConstraintAndDefault {
148+
HasAssocWithConstraintAndDefault,
149+
HasAssocWithAnyObjectConstraint,
150+
HasAssocWithConstraintOnProto,
151+
HasAssocWithSameTypeConstraint {
131152
#^OVERRIDE_TestStruct^#
132153
}
133154

0 commit comments

Comments
 (0)