Skip to content

[CodeCompletion] Duplicate existential requirements when restated #16811

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
Merged
98 changes: 84 additions & 14 deletions lib/AST/LookupVisibleDecls.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -17,12 +17,12 @@

#include "NameLookupImpl.h"
#include "swift/AST/ASTContext.h"
#include "swift/AST/GenericSignature.h"
#include "swift/AST/GenericSignatureBuilder.h"
#include "swift/AST/Initializer.h"
#include "swift/AST/LazyResolver.h"
#include "swift/AST/NameLookup.h"
#include "swift/AST/ProtocolConformance.h"
#include "swift/AST/SubstitutionMap.h"
#include "swift/Basic/SourceManager.h"
#include "swift/Basic/STLExtras.h"
#include "swift/Sema/IDETypeChecking.h"
Expand Down Expand Up @@ -113,7 +113,7 @@ struct LookupState {
return Result;
}
};
} // unnamed namespace
} // end anonymous namespace

static bool areTypeDeclsVisibleInLookupMode(LookupState LS) {
// Nested type declarations can be accessed only with unqualified lookup or
Expand Down Expand Up @@ -473,19 +473,87 @@ lookupVisibleMemberDeclsImpl(Type BaseTy, VisibleDeclConsumer &Consumer,
GenericSignatureBuilder *GSB,
VisitedSet &Visited);

static void lookupVisibleProtocolMemberDecls(
Type BaseTy, ProtocolType *PT, VisibleDeclConsumer &Consumer,
const DeclContext *CurrDC, LookupState LS, DeclVisibilityKind Reason,
LazyResolver *TypeResolver, GenericSignatureBuilder *GSB,
VisitedSet &Visited) {
class RestateFilteringConsumer : public VisibleDeclConsumer {
VisibleDeclConsumer &parentConsumer;
LazyResolver *resolver;

llvm::DenseSet<DeclName> foundVars;
llvm::DenseSet<std::pair<DeclName, CanType>> foundFuncs;

public:
RestateFilteringConsumer(VisibleDeclConsumer &parentConsumer,
Type baseTy, const DeclContext *DC,
LazyResolver *resolver)
: parentConsumer(parentConsumer), resolver(resolver) {
assert(DC && baseTy && !baseTy->hasLValueType());
}

void foundDecl(ValueDecl *VD, DeclVisibilityKind Reason) override {
assert(VD);
// If this isn't a protocol context, hand over the decl
// to the parent consumer.
if (!isa<ProtocolDecl>(VD->getDeclContext())) {
parentConsumer.foundDecl(VD, Reason);
return;
}
if (resolver)
resolver->resolveDeclSignature(VD);

if (!VD->hasInterfaceType()) {
parentConsumer.foundDecl(VD, Reason);
return;
}
auto GFT = VD->getInterfaceType()->getAs<GenericFunctionType>();
if (!GFT) {
if (foundVars.insert(VD->getFullName()).second)
parentConsumer.foundDecl(VD, Reason);
return;
}
auto type = stripSelfRequirementsIfNeeded(VD, GFT);
if (foundFuncs.insert({VD->getFullName(), type}).second) {
parentConsumer.foundDecl(VD, Reason);
}
}
private:
CanType stripSelfRequirementsIfNeeded(ValueDecl *VD, GenericFunctionType *GFT) {
// Preserve the generic signature if this is a subscript, which are uncurried,
// or if we have generic params other than Self. Otherwise, use
// the resultType of the curried function type.
// When we keep the generic signature, we remove the requirements
// from Self to make sure they don't prevent us from recognizing restatements.
auto params = GFT->getGenericParams();
if (params.size() == 1 && !isa<SubscriptDecl>(VD)) {
return GFT->getResult()->getCanonicalType();
}
auto Self = VD->getDeclContext()->getSelfInterfaceType();
SmallVector<Requirement, 4> newReqs;
for (auto req: GFT->getRequirements()) {
if (!Self->isEqual(req.getFirstType()))
newReqs.push_back(req);
}
auto newSig = GenericSignature::get(params, newReqs, false);

return GenericFunctionType::get(newSig, GFT->getInput(),
GFT->getResult(), GFT->getExtInfo())
->getCanonicalType();
}
};

static void
lookupVisibleProtocolMemberDecls(Type BaseTy, ProtocolType *PT,
VisibleDeclConsumer &Consumer,
const DeclContext *CurrDC, LookupState LS,
DeclVisibilityKind Reason,
LazyResolver *TypeResolver,
GenericSignatureBuilder *GSB,
VisitedSet &Visited) {
if (!Visited.insert(PT->getDecl()).second)
return;

for (auto Proto : PT->getDecl()->getInheritedProtocols())
lookupVisibleProtocolMemberDecls(BaseTy, Proto->getDeclaredType(), Consumer, CurrDC,
LS, getReasonForSuper(Reason), TypeResolver,
GSB, Visited);

LS, getReasonForSuper(Reason), TypeResolver,
GSB, Visited);
lookupTypeMembers(BaseTy, PT, Consumer, CurrDC, LS, Reason, TypeResolver);
}

Expand Down Expand Up @@ -832,7 +900,7 @@ class OverrideFilteringConsumer : public VisibleDeclConsumer {
DeclsToReport.insert(FoundDeclTy(VD, Reason));
}
};
} // unnamed namespace
} // end anonymous namespace

/// \brief Enumerate all members in \c BaseTy (including members of extensions,
/// superclasses and implemented protocols), as seen from the context \c CurrDC.
Expand All @@ -844,13 +912,15 @@ static void lookupVisibleMemberDecls(
Type BaseTy, VisibleDeclConsumer &Consumer, const DeclContext *CurrDC,
LookupState LS, DeclVisibilityKind Reason, LazyResolver *TypeResolver,
GenericSignatureBuilder *GSB) {
OverrideFilteringConsumer ConsumerWrapper(BaseTy, CurrDC, TypeResolver);
OverrideFilteringConsumer overrideConsumer(BaseTy, CurrDC, TypeResolver);
RestateFilteringConsumer restateConsumer(overrideConsumer, BaseTy, CurrDC,
TypeResolver);
VisitedSet Visited;
lookupVisibleMemberDeclsImpl(BaseTy, ConsumerWrapper, CurrDC, LS, Reason,
lookupVisibleMemberDeclsImpl(BaseTy, restateConsumer, CurrDC, LS, Reason,
TypeResolver, GSB, Visited);

// Report the declarations we found to the real consumer.
for (const auto &DeclAndReason : ConsumerWrapper.DeclsToReport)
for (const auto &DeclAndReason : overrideConsumer.DeclsToReport)
Consumer.foundDecl(DeclAndReason.D, DeclAndReason.Reason);
}

Expand Down
3 changes: 2 additions & 1 deletion test/IDE/complete_associated_types.swift
Original file line number Diff line number Diff line change
Expand Up @@ -267,7 +267,8 @@ struct StructWithBrokenConformance : FooProtocolWithAssociatedTypes {
func testBrokenConformances1() {
StructWithBrokenConformance.#^BROKEN_CONFORMANCE_1^#
}
// BROKEN_CONFORMANCE_1: Begin completions, 35 items

// BROKEN_CONFORMANCE_1: Begin completions, 33 items
// BROKEN_CONFORMANCE_1-DAG: Decl[TypeAlias]/CurrNominal: DefaultedTypeCommonA[#StructWithBrokenConformance.DefaultedTypeCommonA#]; name=DefaultedTypeCommonA
// BROKEN_CONFORMANCE_1-DAG: Decl[TypeAlias]/CurrNominal: DefaultedTypeCommonB[#StructWithBrokenConformance.DefaultedTypeCommonB#]; name=DefaultedTypeCommonB
// BROKEN_CONFORMANCE_1-DAG: Decl[TypeAlias]/CurrNominal: FooBaseDefaultedTypeB[#StructWithBrokenConformance.FooBaseDefaultedTypeB#]; name=FooBaseDefaultedTypeB
Expand Down
25 changes: 11 additions & 14 deletions test/IDE/complete_override_access_control_protocol.swift
Original file line number Diff line number Diff line change
Expand Up @@ -168,18 +168,17 @@ public class TestPublicDE : ProtocolDPrivate, ProtocolEPublic {
#^TEST_PUBLIC_DE^#
}

// FIXME: Should be 2 items in the three checks below.
// TEST_PRIVATE_DE: Begin completions, 4 items
// TEST_PRIVATE_DE: Begin completions, 2 items
// TEST_PRIVATE_DE-DAG: Decl[InstanceMethod]/Super: func colliding() {|}{{; name=.+$}}
// TEST_PRIVATE_DE-DAG: Decl[InstanceMethod]/Super: func collidingGeneric<T>(x: T) {|}{{; name=.+$}}

// TEST_INTERNAL_DE: Begin completions, 4 items
// TEST_INTERNAL_DE: Begin completions, 2 items
// TEST_INTERNAL_DE-DAG: Decl[InstanceMethod]/Super: func colliding() {|}{{; name=.+$}}
// TEST_INTERNAL_DE-DAG: Decl[InstanceMethod]/Super: func collidingGeneric<T>(x: T) {|}{{; name=.+$}}

// TEST_PUBLIC_DE: Begin completions, 4 items
// TEST_PUBLIC_DE-DAG: Decl[InstanceMethod]/Super: public func colliding() {|}{{; name=.+$}}
// TEST_PUBLIC_DE-DAG: Decl[InstanceMethod]/Super: public func collidingGeneric<T>(x: T) {|}{{; name=.+$}}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why did we lose the public keyword here?

Copy link
Collaborator Author

@AnthonyLatsis AnthonyLatsis Jun 5, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It was a bit strange but I thought it isn't a big deal since we didn't lose it on the other test. Now I see. Apparently because I am filtering without taking access levels into account. This means that, given

public protocol PublicProtocol {func foo}
protocol InternalProtocol {func foo}

, completing in class Foo: PublicProtocol, InternalProtocol and class Foo: InternalProtocol, PublicProtocol will result in the removal of different foos from the look up.
Thanks for pointing it out, I'll fix this by prioritizing declarations with higher access level.

// TEST_PUBLIC_DE: Begin completions, 2 items
// TEST_PUBLIC_DE-DAG: Decl[InstanceMethod]/Super: func colliding() {|}{{; name=.+$}}
// TEST_PUBLIC_DE-DAG: Decl[InstanceMethod]/Super: func collidingGeneric<T>(x: T) {|}{{; name=.+$}}

private class TestPrivateED : ProtocolEPublic, ProtocolDPrivate {
#^TEST_PRIVATE_ED^#
Expand All @@ -195,16 +194,15 @@ public class TestPublicED : ProtocolEPublic, ProtocolDPrivate {
#^TEST_PUBLIC_ED^#
}

// FIXME: Should be 2 items in the three checks below.
// TEST_PRIVATE_ED: Begin completions, 4 items
// TEST_PRIVATE_ED: Begin completions, 2 items
// TEST_PRIVATE_ED-DAG: Decl[InstanceMethod]/Super: func colliding() {|}{{; name=.+$}}
// TEST_PRIVATE_ED-DAG: Decl[InstanceMethod]/Super: func collidingGeneric<T>(x: T) {|}{{; name=.+$}}

// TEST_INTERNAL_ED: Begin completions, 4 items
// TEST_INTERNAL_ED: Begin completions, 2 items
// TEST_INTERNAL_ED-DAG: Decl[InstanceMethod]/Super: func collidingGeneric<T>(x: T) {|}{{; name=.+$}}
// TEST_INTERNAL_ED-DAG: Decl[InstanceMethod]/Super: func colliding() {|}{{; name=.+$}}

// TEST_PUBLIC_ED: Begin completions, 4 items
// TEST_PUBLIC_ED: Begin completions, 2 items
// TEST_PUBLIC_ED-DAG: Decl[InstanceMethod]/Super: public func collidingGeneric<T>(x: T) {|}{{; name=.+$}}
// TEST_PUBLIC_ED-DAG: Decl[InstanceMethod]/Super: public func colliding() {|}{{; name=.+$}}

Expand All @@ -222,15 +220,14 @@ public class TestPublicEF : ProtocolEPublic, ProtocolFPublic {
#^TEST_PUBLIC_EF^#
}

// FIXME: Should be 2 items in the three checks below.
// TEST_PRIVATE_EF: Begin completions, 4 items
// TEST_PRIVATE_EF: Begin completions, 2 items
// TEST_PRIVATE_EF-DAG: Decl[InstanceMethod]/Super: func colliding() {|}{{; name=.+$}}
// TEST_PRIVATE_EF-DAG: Decl[InstanceMethod]/Super: func collidingGeneric<T>(x: T) {|}{{; name=.+$}}

// TEST_INTERNAL_EF: Begin completions, 4 items
// TEST_INTERNAL_EF: Begin completions, 2 items
// TEST_INTERNAL_EF-DAG: Decl[InstanceMethod]/Super: func colliding() {|}{{; name=.+$}}
// TEST_INTERNAL_EF-DAG: Decl[InstanceMethod]/Super: func collidingGeneric<T>(x: T) {|}{{; name=.+$}}

// TEST_PUBLIC_EF: Begin completions, 4 items
// TEST_PUBLIC_EF: Begin completions, 2 items
// TEST_PUBLIC_EF-DAG: Decl[InstanceMethod]/Super: public func colliding() {|}{{; name=.+$}}
// TEST_PUBLIC_EF-DAG: Decl[InstanceMethod]/Super: public func collidingGeneric<T>(x: T) {|}{{; name=.+$}}
132 changes: 132 additions & 0 deletions test/IDE/complete_value_expr.swift
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,20 @@
// RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=PROTOCOL_EXT_GENERICP1 | %FileCheck %s -check-prefix=PROTOCOL_EXT_GENERICP1
// RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=PROTOCOL_EXT_GENERICP2 | %FileCheck %s -check-prefix=PROTOCOL_EXT_GENERICP2
// RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=PROTOCOL_EXT_GENERICP3 | %FileCheck %s -check-prefix=PROTOCOL_EXT_GENERICP3
// RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=NODUP_RESTATED_REQ1 | %FileCheck %s -check-prefix=CHECK_NODUP_RESTATED_REQ
// RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=NODUP_RESTATED_REQ2 | %FileCheck %s -check-prefix=CHECK_NODUP_RESTATED_REQ
// RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=NODUP_RESTATED_REQ3 | %FileCheck %s -check-prefix=CHECK_NODUP_RESTATED_REQ
// RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=NODUP_RESTATED_REQ4 | %FileCheck %s -check-prefix=CHECK_NODUP_RESTATED_REQ
// RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=NODUP_RESTATED_REQ5 | %FileCheck %s -check-prefix=CHECK_NODUP_RESTATED_REQ
// RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=NODUP_RESTATED_REQ6 | %FileCheck %s -check-prefix=CHECK_NODUP_RESTATED_REQ
// RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=NODUP_RESTATED_REQ_TYPE1 | %FileCheck %s -check-prefix=CHECK_NODUP_RESTATED_REQ_TYPE
// RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=NODUP_RESTATED_REQ_TYPE2 | %FileCheck %s -check-prefix=CHECK_NODUP_RESTATED_REQ_TYPE
// RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=NODUP_RESTATED_REQ_TYPE3 | %FileCheck %s -check-prefix=CHECK_NODUP_RESTATED_REQ_TYPE
// RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=NODUP_RESTATED_REQ_NODOT1 | %FileCheck %s -check-prefix=CHECK_NODUP_RESTATED_REQ_NODOT
// RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=NODUP_RESTATED_REQ_NODOT2 | %FileCheck %s -check-prefix=CHECK_NODUP_RESTATED_REQ_NODOT
// RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=NODUP_RESTATED_REQ_NODOT3 | %FileCheck %s -check-prefix=CHECK_NODUP_RESTATED_REQ_NODOT
// RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=CHECK_PROT_OVERRIDES1 | %FileCheck %s -check-prefix=CHECK_PROT_OVERRIDES
// RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=CHECK_PROT_OVERRIDES2 | %FileCheck %s -check-prefix=CHECK_PROT_OVERRIDES
// RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=PROTOCOL_EXT_P4 | %FileCheck %s -check-prefix=PROTOCOL_EXT_P4
// RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=PROTOCOL_EXT_CONCRETE1 | %FileCheck %s -check-prefix=PROTOCOL_EXT_P4_P1
// RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=PROTOCOL_EXT_CONCRETE2 | %FileCheck %s -check-prefix=PROTOCOL_EXT_P4_P1
Expand Down Expand Up @@ -1504,6 +1518,124 @@ func testGenericConforming3<T: P3>(x: T) {
// PROTOCOL_EXT_GENERICP3-DAG: Decl[InstanceMethod]/Super: extP3()[#Void#]{{; name=.+$}}
// PROTOCOL_EXT_GENERICP3: End completions

protocol NoDupReq1 {
func foo()
func roo(arg1: Int)
subscript(arg: Bool) -> Bool {get}
var doo: Int {get}
associatedtype E
}
protocol NoDupReq2 {
func foo()
subscript(arg: Bool) -> Bool {get}
var doo: Int {get}
associatedtype E
}
protocol NoDupReq3 {
func foo()
func roo(arg2: Int)
subscript(arg: Bool) -> Bool {get}
var doo: Int {get}
associatedtype E
}

protocol NoDupReq4 {
func foo()
func roo(arg1: Int)
subscript(arg: Bool) -> Bool {get}
var doo: Int {get}
associatedtype E
}
protocol NoDupReq5: NoDupReq4 {
func foo()
subscript(arg: Bool) -> Bool {get}
var doo: Int {get}
associatedtype E
}
protocol NoDupReq6: NoDupReq5 {
func foo()
func roo(arg2: Int)
subscript(arg: Bool) -> Bool {get}
var doo: Int {get}
associatedtype E
}

typealias NoDupReq23 = NoDupReq2 & NoDupReq3

protocol Override {
func foo<T: NoDupReq1>(_ arg: T)
func foo<T: NoDupReq2>(_ arg: T)
}
protocol Override2 {
func foo<T: NoDupReq1>(_ arg: T)
}
protocol Override3: Override2 {
func foo<T: NoDupReq2>(_ arg: T)
}

func checkRestatementNoDup1(_ arg: NoDupReq1 & NoDupReq2 & NoDupReq3) {
arg.#^NODUP_RESTATED_REQ1^#
arg#^NODUP_RESTATED_REQ_NODOT1^#
}
func checkRestatementNoDup2(_ arg: NoDupReq6) {
arg.#^NODUP_RESTATED_REQ2^#
}
func checkRestatementNoDup3<T: NoDupReq6>(_ arg: T) {
arg.#^NODUP_RESTATED_REQ3^#
T.#^NODUP_RESTATED_REQ_TYPE1^#
arg#^NODUP_RESTATED_REQ_NODOT2^#
}
func checkRestatementNoDup4<T: NoDupReq1 & NoDupReq2 & NoDupReq3>(_ arg: T) {
arg.#^NODUP_RESTATED_REQ4^#
T.#^NODUP_RESTATED_REQ_TYPE2^#
}
func checkRestatementNoDup5<T: NoDupReq1 & NoDupReq23>(_ arg: T) {
arg.#^NODUP_RESTATED_REQ5^#
T.#^NODUP_RESTATED_REQ_TYPE3^#
}
func checkRestatementNoDup6(_ arg: NoDupReq1 & NoDupReq23) {
arg.#^NODUP_RESTATED_REQ6^#
arg#^NODUP_RESTATED_REQ_NODOT3^#
}
func checkOverrideInclusion1(_ arg: Override) {
arg.#^CHECK_PROT_OVERRIDES1^#
}
func checkOverrideInclusion2(_ arg: Override3) {
arg.#^CHECK_PROT_OVERRIDES2^#
}

// CHECK_NODUP_RESTATED_REQ: Begin completions
// CHECK_NODUP_RESTATED_REQ-DAG: Decl[InstanceMethod]/{{Super|CurrNominal}}: foo()[#Void#]; name=foo()
// CHECK_NODUP_RESTATED_REQ-DAG: Decl[InstanceMethod]/{{Super|CurrNominal}}: roo({#arg1: Int#})[#Void#]; name=roo(arg1: Int)
// CHECK_NODUP_RESTATED_REQ-DAG: Decl[InstanceVar]/{{Super|CurrNominal}}: doo[#Int#]; name=doo
// CHECK_NODUP_RESTATED_REQ-DAG: Decl[InstanceMethod]/{{Super|CurrNominal}}: roo({#arg2: Int#})[#Void#]; name=roo(arg2: Int)
// CHECK_NODUP_RESTATED_REQ-NOT: Decl[InstanceMethod]/{{Super|CurrNominal}}: foo()[#Void#]; name=foo()
// CHECK_NODUP_RESTATED_REQ-NOT: Decl[InstanceVar]/{{Super|CurrNominal}}: doo[#Int#]; name=doo
// CHECK_NODUP_RESTATED_REQ: End completions

// CHECK_NODUP_RESTATED_REQ_NODOT: Begin completions
// CHECK_NODUP_RESTATED_REQ_NODOT: Decl[InstanceMethod]/{{Super|CurrNominal}}: .foo()[#Void#]; name=foo()
// CHECK_NODUP_RESTATED_REQ_NODOT: Decl[InstanceMethod]/{{Super|CurrNominal}}: .roo({#arg1: Int#})[#Void#]; name=roo(arg1: Int)
// CHECK_NODUP_RESTATED_REQ_NODOT: Decl[Subscript]/{{Super|CurrNominal}}: [{#Bool#}][#Bool#]; name=[Bool]
// CHECK_NODUP_RESTATED_REQ_NODOT: Decl[InstanceVar]/{{Super|CurrNominal}}: .doo[#Int#]; name=doo
// CHECK_NODUP_RESTATED_REQ_NODOT: Decl[InstanceMethod]/{{Super|CurrNominal}}: .roo({#arg2: Int#})[#Void#]; name=roo(arg2: Int)
// CHECK_NODUP_RESTATED_REQ_NODOT-NOT: Decl[InstanceMethod]/{{Super|CurrNominal}}: .foo()[#Void#]; name=foo()
// CHECK_NODUP_RESTATED_REQ_NODOT-NOT: Decl[Subscript]/{{Super|CurrNominal}}: [{#Bool#}][#Bool#]; name=[Bool]
// CHECK_NODUP_RESTATED_REQ_NODOT-NOT: Decl[InstanceVar]/{{Super|CurrNominal}}: .doo[#Int#]; name=doo
// CHECK_NODUP_RESTATED_REQ_NODOT: End completions

// CHECK_NODUP_RESTATED_REQ_TYPE: Begin completions
// CHECK_NODUP_RESTATED_REQ_TYPE-DAG: Decl[InstanceMethod]/Super: foo({#self: [[ARG:.+]]#})[#() -> Void#]; name=foo([[ARG]])
// CHECK_NODUP_RESTATED_REQ_TYPE-DAG: Decl[InstanceMethod]/Super: roo({#self: [[ARG]]#})[#(arg1: Int) -> Void#]; name=roo([[ARG]])
// CHECK_NODUP_RESTATED_REQ_TYPE-DAG: Decl[AssociatedType]/Super: E; name=E
// CHECK_NODUP_RESTATED_REQ_TYPE-DAG: Decl[InstanceMethod]/Super: roo({#self: [[ARG]]#})[#(arg2: Int) -> Void#]; name=roo([[ARG]])
// CHECK_NODUP_RESTATED_REQ_TYPE-NOT: Decl[InstanceMethod]/Super: foo({#self: [[ARG:.+]]#})[#() -> Void#]; name=foo([[ARG]])
// CHECK_NODUP_RESTATED_REQ_TYPE-NOT: Decl[AssociatedType]/Super: E; name=E
// CHECK_NODUP_RESTATED_REQ_TYPE: End completions

// CHECK_PROT_OVERRIDES: Decl[InstanceMethod]/{{Super|CurrNominal}}: foo({#(arg): NoDupReq1#})[#Void#]; name=foo(arg: NoDupReq1)
// CHECK_PROT_OVERRIDES: Decl[InstanceMethod]/{{Super|CurrNominal}}: foo({#(arg): NoDupReq2#})[#Void#]; name=foo(arg: NoDupReq2)

struct OnlyMe {}
protocol P4 {
associatedtype T
Expand Down
Loading