Skip to content

Commit 0db4ee4

Browse files
authored
Merge pull request #62653 from xymus/deser-custom-attr-cycle-alt
[Serialization] Deserialize custom attributes after the attached decl
2 parents ac10f2a + cc3d2ec commit 0db4ee4

File tree

3 files changed

+133
-35
lines changed

3 files changed

+133
-35
lines changed

lib/Serialization/Deserialization.cpp

Lines changed: 82 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -2741,6 +2741,7 @@ class DeclDeserializer {
27412741

27422742
DeclAttribute *DAttrs = nullptr;
27432743
DeclAttribute **AttrsNext = &DAttrs;
2744+
SmallVector<serialization::BitOffset> customAttrOffsets;
27442745

27452746
Identifier privateDiscriminator;
27462747
unsigned localDiscriminator = ValueDecl::InvalidDiscriminator;
@@ -2829,8 +2830,15 @@ class DeclDeserializer {
28292830

28302831
/// Deserializes records common to all decls from \c MF.DeclTypesCursor (ie.
28312832
/// the invalid flag, attributes, and discriminators)
2833+
///
2834+
/// Reads all attributes except for custom attributes that are skipped and
2835+
/// their offsets added to \c customAttrOffsets.
28322836
llvm::Error deserializeDeclCommon();
28332837

2838+
/// Deserializes the custom attributes from \c MF.DeclTypesCursor, using the
2839+
/// offsets in \c customAttrOffsets.
2840+
llvm::Error deserializeCustomAttrs();
2841+
28342842
Expected<Decl *> getDeclCheckedImpl(
28352843
llvm::function_ref<bool(DeclAttributes)> matchAttributes = nullptr);
28362844

@@ -4804,13 +4812,67 @@ DeclDeserializer::readAvailable_DECL_ATTR(SmallVectorImpl<uint64_t> &scratch,
48044812
return attr;
48054813
}
48064814

4815+
llvm::Error DeclDeserializer::deserializeCustomAttrs() {
4816+
using namespace decls_block;
4817+
4818+
SmallVector<uint64_t, 64> scratch;
4819+
StringRef blobData;
4820+
for (auto attrOffset : customAttrOffsets) {
4821+
if (auto error =
4822+
MF.diagnoseFatalIfNotSuccess(MF.DeclTypeCursor.JumpToBit(attrOffset)))
4823+
return error;
4824+
4825+
llvm::BitstreamEntry entry =
4826+
MF.fatalIfUnexpected(MF.DeclTypeCursor.advance());
4827+
if (entry.Kind != llvm::BitstreamEntry::Record) {
4828+
// We don't know how to serialize decls represented by sub-blocks.
4829+
return MF.diagnoseFatal();
4830+
}
4831+
4832+
unsigned recordID = MF.fatalIfUnexpected(
4833+
MF.DeclTypeCursor.readRecord(entry.ID, scratch, &blobData));
4834+
assert(recordID == decls_block::Custom_DECL_ATTR &&
4835+
"expecting only custom attributes in deserializeCustomAttrs");
4836+
4837+
bool isImplicit;
4838+
bool isArgUnsafe;
4839+
TypeID typeID;
4840+
serialization::decls_block::CustomDeclAttrLayout::readRecord(
4841+
scratch, isImplicit, typeID, isArgUnsafe);
4842+
4843+
Expected<Type> deserialized = MF.getTypeChecked(typeID);
4844+
if (!deserialized) {
4845+
if (deserialized.errorIsA<XRefNonLoadedModuleError>() ||
4846+
MF.allowCompilerErrors()) {
4847+
// A custom attribute defined behind an implementation-only import
4848+
// is safe to drop when it can't be deserialized.
4849+
// rdar://problem/56599179. When allowing errors we're doing a best
4850+
// effort to create a module, so ignore in that case as well.
4851+
consumeError(deserialized.takeError());
4852+
} else
4853+
return deserialized.takeError();
4854+
} else if (!deserialized.get() && MF.allowCompilerErrors()) {
4855+
// Serialized an invalid attribute, just skip it when allowing errors
4856+
} else {
4857+
auto *TE = TypeExpr::createImplicit(deserialized.get(), ctx);
4858+
auto custom = CustomAttr::create(ctx, SourceLoc(), TE, isImplicit);
4859+
custom->setArgIsUnsafe(isArgUnsafe);
4860+
AddAttribute(custom);
4861+
}
4862+
scratch.clear();
4863+
}
4864+
4865+
return llvm::Error::success();
4866+
}
4867+
48074868
llvm::Error DeclDeserializer::deserializeDeclCommon() {
48084869
using namespace decls_block;
48094870

48104871
SmallVector<uint64_t, 64> scratch;
48114872
StringRef blobData;
48124873
while (true) {
48134874
BCOffsetRAII restoreOffset(MF.DeclTypeCursor);
4875+
serialization::BitOffset attrOffset = MF.DeclTypeCursor.GetCurrentBitNo();
48144876
llvm::BitstreamEntry entry =
48154877
MF.fatalIfUnexpected(MF.DeclTypeCursor.advance());
48164878
if (entry.Kind != llvm::BitstreamEntry::Record) {
@@ -5102,33 +5164,10 @@ llvm::Error DeclDeserializer::deserializeDeclCommon() {
51025164
}
51035165

51045166
case decls_block::Custom_DECL_ATTR: {
5105-
bool isImplicit;
5106-
bool isArgUnsafe;
5107-
TypeID typeID;
5108-
serialization::decls_block::CustomDeclAttrLayout::readRecord(
5109-
scratch, isImplicit, typeID, isArgUnsafe);
5110-
5111-
Expected<Type> deserialized = MF.getTypeChecked(typeID);
5112-
if (!deserialized) {
5113-
if (deserialized.errorIsA<XRefNonLoadedModuleError>() ||
5114-
MF.allowCompilerErrors()) {
5115-
// A custom attribute defined behind an implementation-only import
5116-
// is safe to drop when it can't be deserialized.
5117-
// rdar://problem/56599179. When allowing errors we're doing a best
5118-
// effort to create a module, so ignore in that case as well.
5119-
consumeError(deserialized.takeError());
5120-
skipAttr = true;
5121-
} else
5122-
return deserialized.takeError();
5123-
} else if (!deserialized.get() && MF.allowCompilerErrors()) {
5124-
// Serialized an invalid attribute, just skip it when allowing errors
5125-
skipAttr = true;
5126-
} else {
5127-
auto *TE = TypeExpr::createImplicit(deserialized.get(), ctx);
5128-
auto custom = CustomAttr::create(ctx, SourceLoc(), TE, isImplicit);
5129-
custom->setArgIsUnsafe(isArgUnsafe);
5130-
Attr = custom;
5131-
}
5167+
// Deserialize the custom attributes after the attached decl,
5168+
// skip for now.
5169+
customAttrOffsets.push_back(attrOffset);
5170+
skipAttr = true;
51325171
break;
51335172
}
51345173

@@ -5417,16 +5456,19 @@ DeclDeserializer::getDeclCheckedImpl(
54175456
switch (recordID) {
54185457
#define CASE(RECORD_NAME) \
54195458
case decls_block::RECORD_NAME##Layout::Code: {\
5420-
auto decl = deserialize##RECORD_NAME(scratch, blobData); \
5421-
if (decl) { \
5459+
auto declOrError = deserialize##RECORD_NAME(scratch, blobData); \
5460+
if (declOrError) { \
54225461
/* \
54235462
// Set original declaration and parameter indices in `@differentiable` \
54245463
// attributes. \
54255464
*/ \
54265465
setOriginalDeclarationAndParameterIndicesInDifferentiableAttributes(\
5427-
decl.get(), DAttrs, diffAttrParamIndicesMap); \
5466+
declOrError.get(), DAttrs, diffAttrParamIndicesMap); \
54285467
} \
5429-
return decl; \
5468+
if (!declOrError) \
5469+
return declOrError; \
5470+
declOrOffset = declOrError.get(); \
5471+
break; \
54305472
}
54315473

54325474
CASE(TypeAlias)
@@ -5460,15 +5502,21 @@ DeclDeserializer::getDeclCheckedImpl(
54605502
uint32_t pathLen;
54615503
decls_block::XRefLayout::readRecord(scratch, baseModuleID, pathLen);
54625504
auto resolved = MF.resolveCrossReference(baseModuleID, pathLen);
5463-
if (resolved)
5464-
declOrOffset = resolved.get();
5465-
return resolved;
5505+
if (!resolved)
5506+
return resolved;
5507+
declOrOffset = resolved.get();
5508+
break;
54665509
}
54675510

54685511
default:
54695512
// We don't know how to deserialize this kind of decl.
54705513
MF.fatal(llvm::make_error<InvalidRecordKindError>(recordID));
54715514
}
5515+
5516+
auto attrError = deserializeCustomAttrs();
5517+
if (attrError)
5518+
return std::move(attrError);
5519+
return declOrOffset;
54725520
}
54735521

54745522
/// Translate from the Serialization function type repr enum values to the AST

test/IDE/print_ast_tc_decls.swift

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -547,7 +547,12 @@ class d0170_TestAvailability {
547547
// PASS_COMMON-LABEL: {{^}}@objc class d0180_TestIBAttrs {{{$}}
548548

549549
@IBAction func anAction(_: AnyObject) {}
550-
// PASS_COMMON-NEXT: {{^}} @objc @IBAction @MainActor func anAction(_: AnyObject){{$}}
550+
/// Tolerate different attribute orders to support both reading from source
551+
/// and deserializing from swiftmodule.
552+
// PASS_COMMON-NEXT: {{^}} @objc
553+
// PASS_COMMON-DAG: @IBAction
554+
// PASS_COMMON-DAG: @MainActor
555+
// PASS_COMMON: func anAction(_: AnyObject){{$}}
551556

552557
@IBSegueAction func aSegueAction(_ coder: AnyObject, sender: AnyObject, identifier: AnyObject?) -> Any? { fatalError() }
553558
// PASS_COMMON-NEXT: {{^}} @objc @IBSegueAction func aSegueAction(_ coder: AnyObject, sender: AnyObject, identifier: AnyObject?) -> Any?{{$}}
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
// RUN: %empty-directory(%t)
2+
// RUN: %empty-directory(%t/src)
3+
// RUN: %empty-directory(%t/sdk)
4+
// RUN: split-file %s %t/src
5+
6+
// REQUIRES: asserts
7+
8+
// RUN: %target-swift-frontend -emit-module %t/src/PublicModule.swift \
9+
// RUN: -module-name PublicModule -swift-version 5 \
10+
// RUN: -emit-module-path %t/sdk/PublicModule.swiftmodule \
11+
// RUN: -enable-experimental-feature TypeWrappers
12+
13+
// RUN: %target-swift-frontend -typecheck %t/src/Client.swift \
14+
// RUN: -enable-experimental-feature TypeWrappers \
15+
// RUN: -module-name Client -I %t/sdk
16+
17+
//--- PublicModule.swift
18+
@typeWrapper
19+
public struct Wrapper<W: Wrapped, S> {
20+
public init(for: W.Type, storage: S) {}
21+
22+
public subscript<V>(propertyKeyPath _: KeyPath<W, V>, storageKeyPath path: KeyPath<S, V>) -> V {
23+
get { fatalError() }
24+
}
25+
26+
public subscript<V>(propertyKeyPath _: KeyPath<W, V>, storageKeyPath path: WritableKeyPath<S, V>) -> V {
27+
get { fatalError() }
28+
set { }
29+
}
30+
}
31+
32+
@Wrapper
33+
public protocol Wrapped {
34+
init(storageWrapper: Wrapper<Self, $Storage>)
35+
}
36+
37+
//--- Client.swift
38+
import PublicModule
39+
40+
struct Test : Wrapped {
41+
var x: Int = 42
42+
}
43+
44+
let test = Test()
45+
_ = test.$storage

0 commit comments

Comments
 (0)