Skip to content

Commit 3ba745c

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 (cherry picked from commit e388c4a)
1 parent 880e9e6 commit 3ba745c

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
@@ -3008,10 +3008,10 @@ void PrintAST::visitSubscriptDecl(SubscriptDecl *decl) {
30083008
Printer << " -> ";
30093009

30103010
TypeLoc elementTy = decl->getElementTypeLoc();
3011-
Printer.printDeclResultTypePre(decl, elementTy);
3012-
Printer.callPrintStructurePre(PrintStructureKind::FunctionReturnType);
30133011
if (!elementTy.getTypeRepr())
30143012
elementTy = TypeLoc::withoutLoc(decl->getElementInterfaceType());
3013+
Printer.printDeclResultTypePre(decl, elementTy);
3014+
Printer.callPrintStructurePre(PrintStructureKind::FunctionReturnType);
30153015

30163016
// HACK: When printing result types for subscripts with opaque result types,
30173017
// 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
@@ -4196,8 +4196,8 @@ class CompletionOverrideLookup : public swift::VisibleDeclConsumer {
41964196

41974197
/// Return type if the result type if \p VD should be represented as opaque
41984198
/// result type.
4199-
TypeLoc getOpaqueResultTypeLoc(const ValueDecl *VD, DeclVisibilityKind Reason,
4200-
DynamicLookupInfo dynamicLookupInfo) {
4199+
Type getOpaqueResultType(const ValueDecl *VD, DeclVisibilityKind Reason,
4200+
DynamicLookupInfo dynamicLookupInfo) {
42014201
if (Reason !=
42024202
DeclVisibilityKind::MemberOfProtocolImplementedByCurrentNominal)
42034203
return nullptr;
@@ -4216,41 +4216,65 @@ class CompletionOverrideLookup : public swift::VisibleDeclConsumer {
42164216
else
42174217
return nullptr;
42184218

4219-
if (!ResultT->is<DependentMemberType>())
4220-
// The result is not associatedtype.
4221-
return nullptr;
4222-
4223-
// If associatedtype doesn't have conformance/superclass constraint, we
4224-
// can't use opaque type.
4225-
auto assocTyD = ResultT->castTo<DependentMemberType>()->getAssocType();
4226-
if (!assocTyD->getInherited().size())
4219+
if (!ResultT->is<DependentMemberType>() ||
4220+
!ResultT->castTo<DependentMemberType>()->getAssocType())
4221+
// The result is not a valid associatedtype.
42274222
return nullptr;
42284223

42294224
// Try substitution to see if the associated type is resolved to concrete
42304225
// type.
42314226
auto substMap = currTy->getMemberSubstitutionMap(
42324227
CurrDeclContext->getParentModule(), VD);
4233-
ResultT = ResultT.subst(substMap);
4234-
if (!ResultT || !ResultT->is<DependentMemberType>())
4228+
if (!ResultT.subst(substMap)->is<DependentMemberType>())
42354229
// If resolved print it.
42364230
return nullptr;
42374231

4238-
return assocTyD->getInherited()[0];
4232+
// Collect requirements on the associatedtype.
4233+
ProtocolDecl *protoD =
4234+
ResultT->castTo<DependentMemberType>()->getAssocType()->getProtocol();
4235+
4236+
SmallVector<Type, 2> opaqueTypes;
4237+
bool hasExplicitAnyObject = false;
4238+
for (auto req : protoD->getRequirementSignature()) {
4239+
if (!req.getFirstType()->isEqual(ResultT))
4240+
continue;
4241+
4242+
switch (req.getKind()) {
4243+
case RequirementKind::Conformance:
4244+
case RequirementKind::Superclass:
4245+
opaqueTypes.push_back(req.getSecondType());
4246+
break;
4247+
case RequirementKind::Layout:
4248+
hasExplicitAnyObject |= req.getLayoutConstraint()->isClass();
4249+
break;
4250+
case RequirementKind::SameType:
4251+
return nullptr;
4252+
}
4253+
}
4254+
4255+
if (!hasExplicitAnyObject) {
4256+
if (opaqueTypes.empty())
4257+
return nullptr;
4258+
if (opaqueTypes.size() == 1)
4259+
return opaqueTypes.front();
4260+
}
4261+
return ProtocolCompositionType::get(
4262+
VD->getASTContext(), opaqueTypes, hasExplicitAnyObject);
42394263
}
42404264

42414265
void addValueOverride(const ValueDecl *VD, DeclVisibilityKind Reason,
42424266
DynamicLookupInfo dynamicLookupInfo,
42434267
CodeCompletionResultBuilder &Builder,
42444268
bool hasDeclIntroducer) {
42454269
class DeclPrinter : public StreamPrinter {
4246-
TypeLoc OpaqueBaseTy;
4270+
Type OpaqueBaseTy;
42474271

42484272
public:
42494273
using StreamPrinter::StreamPrinter;
42504274

42514275
Optional<unsigned> NameOffset;
42524276

4253-
DeclPrinter(raw_ostream &OS, TypeLoc OpaqueBaseTy)
4277+
DeclPrinter(raw_ostream &OS, Type OpaqueBaseTy)
42544278
: StreamPrinter(OS), OpaqueBaseTy(OpaqueBaseTy) {}
42554279

42564280
void printDeclLoc(const Decl *D) override {
@@ -4262,7 +4286,7 @@ class CompletionOverrideLookup : public swift::VisibleDeclConsumer {
42624286
void printDeclResultTypePre(ValueDecl *VD, TypeLoc &TL) override {
42634287
if (!OpaqueBaseTy.isNull()) {
42644288
OS << "some ";
4265-
TL = OpaqueBaseTy;
4289+
TL = TypeLoc::withoutLoc(OpaqueBaseTy);
42664290
}
42674291
}
42684292
};
@@ -4272,7 +4296,7 @@ class CompletionOverrideLookup : public swift::VisibleDeclConsumer {
42724296
{
42734297
llvm::raw_svector_ostream OS(DeclStr);
42744298
DeclPrinter Printer(
4275-
OS, getOpaqueResultTypeLoc(VD, Reason, dynamicLookupInfo));
4299+
OS, getOpaqueResultType(VD, Reason, dynamicLookupInfo));
42764300
PrintOptions Options;
42774301
if (auto transformType = CurrDeclContext->getDeclaredTypeInContext())
42784302
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)