Skip to content

Commit dce5ddc

Browse files
authored
Merge pull request #29104 from rintaro/5.2-ide-completion-opaqueresult-rdar57245073
[5.2][CodeCompletion] Use GenericSignature methods to get 'associatedtype' requirements
2 parents 7e4c402 + ef628f2 commit dce5ddc

File tree

4 files changed

+103
-27
lines changed

4 files changed

+103
-27
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: 47 additions & 21 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;
@@ -4207,50 +4207,76 @@ class CompletionOverrideLookup : public swift::VisibleDeclConsumer {
42074207
return nullptr;
42084208

42094209
Type ResultT;
4210-
if (auto *FD = dyn_cast<FuncDecl>(VD))
4210+
if (auto *FD = dyn_cast<FuncDecl>(VD)) {
4211+
if (FD->getGenericParams()) {
4212+
// Generic function cannot have opaque result type.
4213+
return nullptr;
4214+
}
42114215
ResultT = FD->getResultInterfaceType();
4212-
else if (auto *SD = dyn_cast<SubscriptDecl>(VD))
4216+
} else if (auto *SD = dyn_cast<SubscriptDecl>(VD)) {
4217+
if (SD->getGenericParams()) {
4218+
// Generic subscript cannot have opaque result type.
4219+
return nullptr;
4220+
}
42134221
ResultT = SD->getElementInterfaceType();
4214-
else if (auto *VarD = dyn_cast<VarDecl>(VD))
4222+
} else if (auto *VarD = dyn_cast<VarDecl>(VD)) {
42154223
ResultT = VarD->getInterfaceType();
4216-
else
4217-
return nullptr;
4218-
4219-
if (!ResultT->is<DependentMemberType>())
4220-
// The result is not associatedtype.
4224+
} else {
42214225
return nullptr;
4226+
}
42224227

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())
4228+
if (!ResultT->is<DependentMemberType>() ||
4229+
!ResultT->castTo<DependentMemberType>()->getAssocType())
4230+
// The result is not a valid associatedtype.
42274231
return nullptr;
42284232

42294233
// Try substitution to see if the associated type is resolved to concrete
42304234
// type.
42314235
auto substMap = currTy->getMemberSubstitutionMap(
42324236
CurrDeclContext->getParentModule(), VD);
4233-
ResultT = ResultT.subst(substMap);
4234-
if (!ResultT || !ResultT->is<DependentMemberType>())
4237+
if (!ResultT.subst(substMap)->is<DependentMemberType>())
42354238
// If resolved print it.
42364239
return nullptr;
42374240

4238-
return assocTyD->getInherited()[0];
4241+
auto genericSig = VD->getDeclContext()->getGenericSignatureOfContext();
4242+
4243+
if (genericSig->isConcreteType(ResultT))
4244+
// If it has same type requrement, we will emit the concrete type.
4245+
return nullptr;
4246+
4247+
// Collect requirements on the associatedtype.
4248+
SmallVector<Type, 2> opaqueTypes;
4249+
bool hasExplicitAnyObject = false;
4250+
if (auto superTy = genericSig->getSuperclassBound(ResultT))
4251+
opaqueTypes.push_back(superTy);
4252+
for (auto proto : genericSig->getConformsTo(ResultT))
4253+
opaqueTypes.push_back(proto->getDeclaredInterfaceType());
4254+
if (auto layout = genericSig->getLayoutConstraint(ResultT))
4255+
hasExplicitAnyObject = layout->isClass();
4256+
4257+
if (!hasExplicitAnyObject) {
4258+
if (opaqueTypes.empty())
4259+
return nullptr;
4260+
if (opaqueTypes.size() == 1)
4261+
return opaqueTypes.front();
4262+
}
4263+
return ProtocolCompositionType::get(
4264+
VD->getASTContext(), opaqueTypes, hasExplicitAnyObject);
42394265
}
42404266

42414267
void addValueOverride(const ValueDecl *VD, DeclVisibilityKind Reason,
42424268
DynamicLookupInfo dynamicLookupInfo,
42434269
CodeCompletionResultBuilder &Builder,
42444270
bool hasDeclIntroducer) {
42454271
class DeclPrinter : public StreamPrinter {
4246-
TypeLoc OpaqueBaseTy;
4272+
Type OpaqueBaseTy;
42474273

42484274
public:
42494275
using StreamPrinter::StreamPrinter;
42504276

42514277
Optional<unsigned> NameOffset;
42524278

4253-
DeclPrinter(raw_ostream &OS, TypeLoc OpaqueBaseTy)
4279+
DeclPrinter(raw_ostream &OS, Type OpaqueBaseTy)
42544280
: StreamPrinter(OS), OpaqueBaseTy(OpaqueBaseTy) {}
42554281

42564282
void printDeclLoc(const Decl *D) override {
@@ -4262,7 +4288,7 @@ class CompletionOverrideLookup : public swift::VisibleDeclConsumer {
42624288
void printDeclResultTypePre(ValueDecl *VD, TypeLoc &TL) override {
42634289
if (!OpaqueBaseTy.isNull()) {
42644290
OS << "some ";
4265-
TL = OpaqueBaseTy;
4291+
TL = TypeLoc::withoutLoc(OpaqueBaseTy);
42664292
}
42674293
}
42684294
};
@@ -4272,7 +4298,7 @@ class CompletionOverrideLookup : public swift::VisibleDeclConsumer {
42724298
{
42734299
llvm::raw_svector_ostream OS(DeclStr);
42744300
DeclPrinter Printer(
4275-
OS, getOpaqueResultTypeLoc(VD, Reason, dynamicLookupInfo));
4301+
OS, getOpaqueResultType(VD, Reason, dynamicLookupInfo));
42764302
PrintOptions Options;
42774303
if (auto transformType = CurrDeclContext->getDeclaredTypeInContext())
42784304
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: 32 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -92,7 +92,7 @@ protocol HasAssocWithSuperClassConstraint {
9292
}
9393
protocol HasAssocWithCompositionConstraint {
9494
associatedtype AssocWithCompositionConstraint: MyClass & MyProtocol
95-
subscript<T>(idx: T) -> AssocWithCompositionConstraint where T: Comparable { get }
95+
subscript(idx: Int) -> AssocWithCompositionConstraint { get }
9696
}
9797
protocol HasAssocWithDefault {
9898
associatedtype AssocWithDefault = MyEnum
@@ -102,22 +102,46 @@ 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 == ConcreteMyProtocol {
114+
associatedtype AssocWithSameTypeConstraint : MyProtocol
115+
func returnAssocWithSameTypeConstraint() -> AssocWithSameTypeConstraint
116+
}
117+
protocol HasAssocWithConformanceConstraintGeneric {
118+
associatedtype AssocWithConformanceConstraintGeneric: MyProtocol
119+
func returnAssocWithConformanceConstraintGeneric<T>(arg: T) -> AssocWithConformanceConstraintGeneric
120+
}
105121

106122
class TestClass :
107123
HasAssocPlain,
108124
HasAssocWithConformanceConstraint,
109125
HasAssocWithSuperClassConstraint,
110126
HasAssocWithCompositionConstraint,
111127
HasAssocWithDefault,
112-
HasAssocWithConstraintAndDefault {
128+
HasAssocWithConstraintAndDefault,
129+
HasAssocWithAnyObjectConstraint,
130+
HasAssocWithConstraintOnProto,
131+
HasAssocWithSameTypeConstraint,
132+
HasAssocWithConformanceConstraintGeneric {
113133
#^OVERRIDE_TestClass^#
114134
// OVERRIDE: Begin completions
115135
// OVERRIDE-DAG: Decl[InstanceMethod]/Super: func returnAssocPlain() -> AssocPlain {|};
116136
// OVERRIDE-DAG: Decl[InstanceMethod]/Super: func returnAssocWithConformanceConstraint(fn: (Int) -> Int) -> some MyProtocol {|};
117137
// OVERRIDE-DAG: Decl[InstanceVar]/Super: var valAssocWithSuperClassConstraint: some MyClass;
118-
// OVERRIDE-DAG: Decl[Subscript]/Super: subscript<T>(idx: T) -> some MyClass & MyProtocol where T : Comparable {|};
138+
// OVERRIDE-DAG: Decl[Subscript]/Super: subscript(idx: Int) -> some MyClass & MyProtocol {|};
119139
// OVERRIDE-DAG: Decl[InstanceMethod]/Super: func returnAssocWithDefault() -> MyEnum {|};
120140
// OVERRIDE-DAG: Decl[InstanceMethod]/Super: func returnAssocWithConstraintAndDefault() -> ConcreteMyProtocol {|};
141+
// OVERRIDE-DAG: Decl[InstanceMethod]/Super: func returnAssocWithAnyObjectConstraint() -> some MyProtocol & AnyObject {|}
142+
// OVERRIDE-DAG: Decl[InstanceMethod]/Super: func returnAssocWithConstraintOnProto() -> some MyProtocol {|}
143+
// OVERRIDE-DAG: Decl[InstanceMethod]/Super: func returnAssocWithSameTypeConstraint() -> AssocWithSameTypeConstraint {|}
144+
// OVERRIDE-DAG: Decl[InstanceMethod]/Super: func returnAssocWithConformanceConstraintGeneric<T>(arg: T) -> AssocWithConformanceConstraintGeneric {|}
121145
// OVERRIDE: End completions
122146
}
123147

@@ -127,7 +151,11 @@ struct TestStruct :
127151
HasAssocWithSuperClassConstraint,
128152
HasAssocWithCompositionConstraint,
129153
HasAssocWithDefault,
130-
HasAssocWithConstraintAndDefault {
154+
HasAssocWithConstraintAndDefault,
155+
HasAssocWithAnyObjectConstraint,
156+
HasAssocWithConstraintOnProto,
157+
HasAssocWithSameTypeConstraint,
158+
HasAssocWithConformanceConstraintGeneric {
131159
#^OVERRIDE_TestStruct^#
132160
}
133161

0 commit comments

Comments
 (0)