mirror of
https://github.com/apple/swift.git
synced 2025-12-14 20:36:38 +01:00
[Demangler] Handle invertible reqs for extensions in findDeclContext
If we didn't find an extension result, try again disregarding invertible requirements since `demangleGenericSignature` won't include them. This is just meant to be a quick low risk fix that we can cherry-pick, the proper fix here is to delete all this logic and just return the nominal along with the ABI module name to filter lookup results. rdar://165639044
This commit is contained in:
@@ -1550,6 +1550,17 @@ ASTBuilder::findDeclContext(NodePointer node) {
|
||||
}
|
||||
}
|
||||
|
||||
// FIXME: We shouldn't be attempting to find an exact extension match,
|
||||
// clients only need the nominal for qualified lookup. Additionally, the
|
||||
// module in which the extension resides is currently used to filter the
|
||||
// lookup results. This means when we have multiple matches, the particular
|
||||
// extension we choose matters.
|
||||
//
|
||||
// We ought to refactor things such that we return a module ABI name +
|
||||
// nominal decl which downstream logic can use to lookup and limit results
|
||||
// to only those that appear in the ABI module. Then we can delete all this
|
||||
// logic.
|
||||
SmallVector<ExtensionDecl *, 4> genericExts;
|
||||
for (auto *ext : nominalDecl->getExtensions()) {
|
||||
bool found = false;
|
||||
for (ModuleDecl *module : moduleDecls) {
|
||||
@@ -1588,6 +1599,39 @@ ASTBuilder::findDeclContext(NodePointer node) {
|
||||
if (requirements.empty())
|
||||
return ext;
|
||||
}
|
||||
genericExts.push_back(ext);
|
||||
}
|
||||
if (!genericSig)
|
||||
return nullptr;
|
||||
|
||||
SmallVector<Requirement, 2> requirements;
|
||||
SmallVector<InverseRequirement, 2> inverses;
|
||||
genericSig->getRequirementsWithInverses(requirements, inverses);
|
||||
|
||||
// If we didn't find a result yet, try again without invertible requirements
|
||||
// since `demangleGenericSignature` won't include them, e.g won't include
|
||||
// Copyable for:
|
||||
//
|
||||
// struct S<T: ~Copyable> {}
|
||||
// protocol P: ~Copyable {}
|
||||
// extension S where T: P/*, T: Copyable*/ {}
|
||||
//
|
||||
// We do this as a separate loop to avoid disturbing existing lookup
|
||||
// behavior for cases where there's an extension with matching inverses,
|
||||
// since the choice of extension matters (see above FIXME).
|
||||
//
|
||||
// FIXME: This is a complete hack, we ought to delete all this logic and
|
||||
// just return the nominal + module ABI name.
|
||||
for (auto *ext : genericExts) {
|
||||
auto extSig = ext->getGenericSignature().getCanonicalSignature();
|
||||
if (extSig.getGenericParams() != genericSig.getGenericParams())
|
||||
continue;
|
||||
|
||||
SmallVector<Requirement, 2> extReqs;
|
||||
SmallVector<InverseRequirement, 2> extInvs;
|
||||
extSig->getRequirementsWithInverses(extReqs, extInvs);
|
||||
if (extReqs == requirements)
|
||||
return ext;
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
|
||||
15
test/IDE/rdar165639044.swift
Normal file
15
test/IDE/rdar165639044.swift
Normal file
@@ -0,0 +1,15 @@
|
||||
// RUN: %batch-code-completion
|
||||
|
||||
struct S<T: ~Copyable> {}
|
||||
protocol P: ~Copyable {}
|
||||
|
||||
extension S where T: P {
|
||||
var bar: Int { 0 }
|
||||
}
|
||||
struct R: P {}
|
||||
|
||||
// Make sure USR round-tripping works here.
|
||||
func foo(_ x: S<R>) {
|
||||
x.#^COMPLETE^#
|
||||
// COMPLETE: Decl[InstanceVar]/CurrNominal: bar[#Int#]; name=bar
|
||||
}
|
||||
@@ -58,3 +58,19 @@ extension Generic where T: AnyObject {
|
||||
// DEMANGLE-DECL: $s10extensions7GenericVAARlzClE18NestedViaAnyObjectV
|
||||
// CHECK-DECL: extensions.(file).Generic extension.NestedViaAnyObject
|
||||
|
||||
// Invertible Constraints
|
||||
|
||||
struct GenericNonCopyable<T: ~Copyable> {}
|
||||
protocol ProtoNonCopyable: ~Copyable {}
|
||||
|
||||
extension GenericNonCopyable where T: ProtoNonCopyable/*, T: Copyable*/ {
|
||||
struct Nested {}
|
||||
}
|
||||
|
||||
struct NonCopyableType: ProtoNonCopyable {}
|
||||
|
||||
// DEMANGLE-DECL: $s10extensions18GenericNonCopyableVA2A05ProtocD0RzlE6NestedV
|
||||
// CHECK-DECL: extensions.(file).GenericNonCopyable extension.Nested
|
||||
|
||||
// DEMANGLE-TYPE: $s10extensions18GenericNonCopyableVA2A05ProtocD0RzlE6NestedVyAA0cD4TypeV_GD
|
||||
// CHECK-TYPE: GenericNonCopyable<NonCopyableType>.Nested
|
||||
|
||||
Reference in New Issue
Block a user