Skip to content

Commit dd40c70

Browse files
authored
Merge pull request #23627 from akyrtzi/fix-bad-deserial-49336277
[Serialization] Fix bad tagging of deserialized decls that can result in failed member lookups
2 parents 9b4bfd8 + 1b2cb9c commit dd40c70

File tree

5 files changed

+54
-20
lines changed

5 files changed

+54
-20
lines changed

lib/Serialization/Deserialization.cpp

Lines changed: 20 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -3753,35 +3753,35 @@ class swift::DeclDeserializer {
37533753

37543754
Expected<Decl *>
37553755
ModuleFile::getDeclChecked(DeclID DID) {
3756-
// Tag every deserialized ValueDecl coming out of getDeclChecked with its ID.
37573756
if (DID == 0)
37583757
return nullptr;
37593758

37603759
assert(DID <= Decls.size() && "invalid decl ID");
37613760
auto &declOrOffset = Decls[DID-1];
37623761

3763-
if (declOrOffset.isComplete())
3764-
return declOrOffset;
3762+
if (!declOrOffset.isComplete()) {
3763+
++NumDeclsLoaded;
3764+
BCOffsetRAII restoreOffset(DeclTypeCursor);
3765+
DeclTypeCursor.JumpToBit(declOrOffset);
37653766

3766-
++NumDeclsLoaded;
3767-
BCOffsetRAII restoreOffset(DeclTypeCursor);
3768-
DeclTypeCursor.JumpToBit(declOrOffset);
3767+
ModuleFile::DeserializingEntityRAII deserializingEntity(*this);
3768+
Expected<Decl *> deserialized =
3769+
DeclDeserializer(*this, declOrOffset).getDeclCheckedImpl();
3770+
if (!deserialized)
3771+
return deserialized;
3772+
}
37693773

3770-
SWIFT_DEFER {
3771-
if (!declOrOffset.isComplete())
3772-
return;
3773-
if (auto *IDC = dyn_cast_or_null<IterableDeclContext>(declOrOffset.get())) {
3774-
// Only set the DeclID on the returned Decl if it's one that was loaded
3775-
// and _wasn't_ one that had its DeclID set elsewhere (a followed XREF).
3776-
if (IDC->wasDeserialized() &&
3777-
static_cast<uint32_t>(IDC->getDeclID()) == 0) {
3778-
IDC->setDeclID(DID);
3779-
}
3774+
// Tag every deserialized ValueDecl coming out of getDeclChecked with its ID.
3775+
assert(declOrOffset.isComplete());
3776+
if (auto *IDC = dyn_cast_or_null<IterableDeclContext>(declOrOffset.get())) {
3777+
// Only set the DeclID on the returned Decl if it's one that was loaded
3778+
// and _wasn't_ one that had its DeclID set elsewhere (a followed XREF).
3779+
if (IDC->wasDeserialized() &&
3780+
static_cast<uint32_t>(IDC->getDeclID()) == 0) {
3781+
IDC->setDeclID(DID);
37803782
}
3781-
};
3782-
3783-
ModuleFile::DeserializingEntityRAII deserializingEntity(*this);
3784-
return DeclDeserializer(*this, declOrOffset).getDeclCheckedImpl();
3783+
}
3784+
return declOrOffset;
37853785
}
37863786

37873787
llvm::Error DeclDeserializer::deserializeDeclAttributes() {
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
import itermod
2+
3+
public protocol MySequence {
4+
associatedtype Element
5+
associatedtype Iterator: MyIter where Iterator.Element == Element
6+
}
7+
8+
public struct MyBar: MySequence, MyIter {
9+
public func callme() {}
10+
11+
public typealias Element = UInt8
12+
public typealias Iterator = MyBar
13+
}
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
import itermod
2+
import basemod
3+
4+
extension MyIter where Element == MyBar {}
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
public protocol MyIter {
2+
associatedtype Element
3+
}
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
// RUN: %empty-directory(%t)
2+
// RUN: %target-swift-frontend %S/Inputs/itermod.swift -module-name itermod -emit-module -o %t/itermod.swiftmodule
3+
// RUN: %target-swift-frontend %S/Inputs/basemod.swift -module-name basemod -emit-module -o %t/basemod.swiftmodule -I %t
4+
// RUN: %target-swift-frontend %S/Inputs/dependmod.swift -module-name dependmod -emit-module -o %t/dependmod.swiftmodule -I %t
5+
// RUN: %target-swift-frontend -typecheck %s -I %t -verify
6+
7+
import basemod
8+
import dependmod
9+
10+
func test(b: MyBar) {
11+
b.callme()
12+
// Check that there was typechecking.
13+
b.non_existent() // expected-error {{no member 'non_existent'}}
14+
}

0 commit comments

Comments
 (0)