-
Notifications
You must be signed in to change notification settings - Fork 10.5k
SIL verification failure with certain conformances to Collection
.
#66503
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
Comments
Non-differentiability diagnostics is missed somewhere. We do not support differentiating |
So, likely similar to #54404 and around |
This issue is not related to differentiation, and the reproducer does not use it at all. When the module U.swift defines a coroutine read accessor (subscript), and another module (A.swift) imports it, the accessor decl is deserialized without a body and it does not pass the SIL Verifier:
It is not clear to me how A.swift is supposed to define it. U.swift does it in getSynthesizedAccessor, but this function early-exists for A.swift, because the accessor already exists (but doesn't have a body)
I've tried the following patch, but it crashes later in IRGen, and I'm not sure if this is a correct way to fix this issue. diff --git a/lib/AST/Decl.cpp b/lib/AST/Decl.cpp
index fb73ad1454a..9ff761dc98f 100644
--- a/lib/AST/Decl.cpp
+++ b/lib/AST/Decl.cpp
@@ -2636,7 +2636,8 @@ bool AbstractStorageDecl::requiresOpaqueModifyCoroutine() const {
AccessorDecl *AbstractStorageDecl::getSynthesizedAccessor(AccessorKind kind) const {
if (auto *accessor = getAccessor(kind))
- return accessor;
+ if (accessor->getBodyKind() != AccessorDecl::BodyKind::None)
+ return accessor;
ASTContext &ctx = getASTContext();
return evaluateOrDefault(ctx.evaluator,
diff --git a/lib/AST/TypeCheckRequests.cpp b/lib/AST/TypeCheckRequests.cpp
index c4bcb953087..0ade927c8e8 100644
--- a/lib/AST/TypeCheckRequests.cpp
+++ b/lib/AST/TypeCheckRequests.cpp
@@ -759,7 +759,7 @@ SynthesizeAccessorRequest::getCachedResult() const {
auto *storage = std::get<0>(getStorage());
auto kind = std::get<1>(getStorage());
auto *accessor = storage->getAccessor(kind);
- if (accessor)
+ if (accessor && accessor->getBodyKind() != AccessorDecl::BodyKind::None)
return accessor;
return llvm::None;
}
@@ -767,7 +767,10 @@ SynthesizeAccessorRequest::getCachedResult() const {
void SynthesizeAccessorRequest::cacheResult(AccessorDecl *accessor) const {
auto *storage = std::get<0>(getStorage());
auto kind = std::get<1>(getStorage());
-
+ auto *existingAccessor = storage->getAccessor(kind);
+ if (existingAccessor) {
+ return;
+ }
storage->setSynthesizedAccessor(kind, accessor);
}
diff --git a/lib/Sema/TypeCheckStorage.cpp b/lib/Sema/TypeCheckStorage.cpp
index 89d46decbaf..afc486f5ea3 100644
--- a/lib/Sema/TypeCheckStorage.cpp
+++ b/lib/Sema/TypeCheckStorage.cpp
@@ -2359,12 +2359,15 @@ createCoroutineAccessorPrototype(AbstractStorageDecl *storage,
// Coroutine accessors always return ().
const Type retTy = TupleType::getEmpty(ctx);
- auto *accessor = AccessorDecl::create(
+ auto *accessor = storage->getAccessor(kind);
+ if (!accessor) {
+ accessor = AccessorDecl::create(
ctx, loc, /*AccessorKeywordLoc=*/SourceLoc(), kind, storage,
/*StaticLoc=*/SourceLoc(), StaticSpellingKind::None,
/*Async=*/false, /*AsyncLoc=*/SourceLoc(),
/*Throws=*/false, /*ThrowsLoc=*/SourceLoc(), params, retTy, dc);
- accessor->setSynthesized();
+ accessor->setSynthesized();
+ }
if (isMutating)
accessor->setSelfAccessKind(SelfAccessKind::Mutating); |
Can you simplify the reproducer further? |
I can get import Foundation; import Collections; import InternalPackage
public final class C<Graph: A>: LP {
public var l: OrderedDictionary<String, L<Graph.Root>>
public typealias Index = OrderedDictionary<String, L<Graph.Root>>.Index
required init(from decoder: any Decoder) throws {fatalError("")}
}
public protocol A {associatedtype Root: AnyObject; var root: Root { get }} and import Foundation; import OrderedCollections
public struct L<Root>{}
public protocol LP: Collection where Index == OrderedDictionary<Key, L<Root>>.Index, Element == OrderedDictionary<Key, L<Root>>.Element{
associatedtype Root
associatedtype Key: Hashable
var l: OrderedDictionary<Key, L<Root>> { get set }
}
public extension LP {
var startIndex: Index {self.l.elements.startIndex}
var endIndex: Index {self.l.elements.endIndex}
var indices: Range<Index> {self.l.elements.indices}
func index(after index: Index) -> Index {fatalError()}
subscript(index: Index) -> Element {self.l.elements[index]}
}
public struct BG<Root, Key: Hashable>: LP {
public typealias Index = OrderedDictionary<Key, L<Root>>.Index
public typealias Element = OrderedDictionary<Key, L<Root>>.Element
public var l = OrderedDictionary<Key, L<Root>>()
} Note that deleting all of |
Description
The following code fails to compile in Debug mode. The error message is:
SIL verification failed: public/shared function must have a body: F->isDefinition() || F->hasForeignBody()
Steps to reproduce
This reproducer requires four files: two
Package.swift
files (one is for an internal package), and two regular Swift source files.The directory tree looks like this:
Listing for
./Package.swift
:Listing for
./Sources/InternalPackage/Package.swift
:Listing for ./Sources/InternalPackage/Sources/InternalPackage/U.swift:
Listing for ./Sources/ReproducerServer/A.swift:
Note that condensing the contents of
A.swift
andU.swift
into a single file causes the build to succeed.Expected behavior
The compilation should complete successfully.
Environment
Additional context
Stack trace:
Additional SIL-related information:
If we remove the conformance of
LP
toCollection
, that is, we change line 5 ofU.swift
to:public protocol LP {
and then delete the extension of
LP
(that is, deleting lines 10 to 16 of the same file), then the compilation succeeds.The text was updated successfully, but these errors were encountered: