[InterfaceGen] Print property initializers in resilient, fixed-layout types (#19619)

Augment the ASTPrinter to print the name and text of initializer expressions if
a property has an initializer and the type is @_fixed_layout and resides in a resilient module, and serialize the text for partial modules.

With this change, all .swiftinterface files in the project (except for SwiftLang) compile to swiftmodules on macOS.

rdar://43774580
rdar://43812188
This commit is contained in:
Harlan
2018-10-05 18:21:46 -07:00
committed by GitHub
parent 690c6c374f
commit 2c86e3249c
10 changed files with 262 additions and 59 deletions

View File

@@ -1864,38 +1864,49 @@ public:
/// Pattern and Initialization expression. The pattern is always present, but /// Pattern and Initialization expression. The pattern is always present, but
/// the initializer can be null if there is none. /// the initializer can be null if there is none.
class PatternBindingEntry { class PatternBindingEntry {
Pattern *ThePattern;
/// The location of the equal '=' token.
SourceLoc EqualLoc;
enum class Flags { enum class Flags {
Checked = 1 << 0, Checked = 1 << 0,
Removed = 1 << 1, Removed = 1 << 1,
Lazy = 1 << 2, Lazy = 1 << 2
};
llvm::PointerIntPair<Pattern *, 3, OptionSet<Flags>> PatternAndFlags;
struct ExprAndEqualLoc {
// When the initializer is removed we don't actually clear the pointer
// because we might need to get initializer's source range. Since the
// initializer is ASTContext-allocated it is safe.
Expr *Node;
/// The location of the equal '=' token.
SourceLoc EqualLoc;
}; };
// When the initializer is removed we don't actually clear the pointer union {
// because we might need to get initializer's source range. Since the /// The initializer expression and its '=' token loc.
// initializer is ASTContext-allocated it is safe. ExprAndEqualLoc InitExpr;
llvm::PointerIntPair<Expr *, 3, OptionSet<Flags>> InitAndFlags;
/// The text of the initializer expression if deserialized from a module.
StringRef InitStringRepresentation;
};
/// The initializer context used for this pattern binding entry. /// The initializer context used for this pattern binding entry.
DeclContext *InitContext = nullptr; llvm::PointerIntPair<DeclContext *, 1, bool> InitContextAndIsText;
friend class PatternBindingInitializer; friend class PatternBindingInitializer;
public: public:
PatternBindingEntry(Pattern *P, SourceLoc EqualLoc, Expr *E, PatternBindingEntry(Pattern *P, SourceLoc EqualLoc, Expr *E,
DeclContext *InitContext) DeclContext *InitContext)
: ThePattern(P), EqualLoc(EqualLoc), InitAndFlags(E, {}), : PatternAndFlags(P, {}), InitExpr({E, EqualLoc}),
InitContext(InitContext) {} InitContextAndIsText({InitContext, false}) {
}
Pattern *getPattern() const { return ThePattern; } Pattern *getPattern() const { return PatternAndFlags.getPointer(); }
void setPattern(Pattern *P) { ThePattern = P; } void setPattern(Pattern *P) { PatternAndFlags.setPointer(P); }
Expr *getInit() const { Expr *getInit() const {
return (InitAndFlags.getInt().contains(Flags::Removed)) if (PatternAndFlags.getInt().contains(Flags::Removed) ||
? nullptr : InitAndFlags.getPointer(); InitContextAndIsText.getInt())
return nullptr;
return InitExpr.Node;
} }
Expr *getNonLazyInit() const { Expr *getNonLazyInit() const {
return isInitializerLazy() ? nullptr : getInit(); return isInitializerLazy() ? nullptr : getInit();
@@ -1903,37 +1914,64 @@ public:
SourceRange getOrigInitRange() const; SourceRange getOrigInitRange() const;
void setInit(Expr *E); void setInit(Expr *E);
/// Gets the text of the initializer expression, stripping out inactive
/// branches of any #ifs inside the expression.
StringRef getInitStringRepresentation(SmallVectorImpl<char> &scratch) const;
/// Sets the initializer string representation to the string that was
/// deserialized from a partial module.
void setInitStringRepresentation(StringRef str) {
InitStringRepresentation = str;
InitContextAndIsText.setInt(true);
}
/// Whether this pattern entry can generate a string representation of its
/// initializer expression.
bool hasInitStringRepresentation() const;
/// Retrieve the location of the equal '=' token. /// Retrieve the location of the equal '=' token.
SourceLoc getEqualLoc() const { return EqualLoc; } SourceLoc getEqualLoc() const {
return InitContextAndIsText.getInt() ? SourceLoc() : InitExpr.EqualLoc;
}
/// Set the location of the equal '=' token. /// Set the location of the equal '=' token.
void setEqualLoc(SourceLoc equalLoc) { EqualLoc = equalLoc; } void setEqualLoc(SourceLoc equalLoc) {
assert(!InitContextAndIsText.getInt() &&
"cannot set equal loc for textual initializer");
InitExpr.EqualLoc = equalLoc;
}
/// Retrieve the initializer as it was written in the source. /// Retrieve the initializer as it was written in the source.
Expr *getInitAsWritten() const { return InitAndFlags.getPointer(); } Expr *getInitAsWritten() const {
return InitContextAndIsText.getInt() ? nullptr : InitExpr.Node;
}
bool isInitializerChecked() const { bool isInitializerChecked() const {
return InitAndFlags.getInt().contains(Flags::Checked); return PatternAndFlags.getInt().contains(Flags::Checked);
} }
void setInitializerChecked() { void setInitializerChecked() {
InitAndFlags.setInt(InitAndFlags.getInt() | Flags::Checked); PatternAndFlags.setInt(PatternAndFlags.getInt() | Flags::Checked);
} }
bool isInitializerLazy() const { bool isInitializerLazy() const {
return InitAndFlags.getInt().contains(Flags::Lazy); return PatternAndFlags.getInt().contains(Flags::Lazy);
} }
void setInitializerLazy() { void setInitializerLazy() {
InitAndFlags.setInt(InitAndFlags.getInt() | Flags::Lazy); PatternAndFlags.setInt(PatternAndFlags.getInt() | Flags::Lazy);
} }
// Return the first variable initialized by this pattern. // Return the first variable initialized by this pattern.
VarDecl *getAnchoringVarDecl() const; VarDecl *getAnchoringVarDecl() const;
// Retrieve the declaration context for the initializer. // Retrieve the declaration context for the initializer.
DeclContext *getInitContext() const { return InitContext; } DeclContext *getInitContext() const {
return InitContextAndIsText.getPointer();
}
/// Override the initializer context. /// Override the initializer context.
void setInitContext(DeclContext *dc) { InitContext = dc; } void setInitContext(DeclContext *dc) {
InitContextAndIsText.setPointer(dc);
}
/// Retrieve the source range covered by this pattern binding. /// Retrieve the source range covered by this pattern binding.
/// ///
@@ -2007,6 +2045,10 @@ public:
return const_cast<PatternBindingDecl*>(this)->getMutablePatternList(); return const_cast<PatternBindingDecl*>(this)->getMutablePatternList();
} }
void setInitStringRepresentation(unsigned i, StringRef str) {
getMutablePatternList()[i].setInitStringRepresentation(str);
}
Expr *getInit(unsigned i) const { Expr *getInit(unsigned i) const {
return getPatternList()[i].getInit(); return getPatternList()[i].getInit();
} }
@@ -2039,7 +2081,8 @@ public:
/// Return the PatternEntry (a pattern + initializer pair) for the specified /// Return the PatternEntry (a pattern + initializer pair) for the specified
/// VarDecl. /// VarDecl.
PatternBindingEntry getPatternEntryForVarDecl(const VarDecl *VD) const { const PatternBindingEntry &getPatternEntryForVarDecl(
const VarDecl *VD) const {
return getPatternList()[getPatternEntryIndexForVarDecl(VD)]; return getPatternList()[getPatternEntryIndexForVarDecl(VD)];
} }
@@ -2097,7 +2140,7 @@ public:
static bool classof(const Decl *D) { static bool classof(const Decl *D) {
return D->getKind() == DeclKind::PatternBinding; return D->getKind() == DeclKind::PatternBinding;
} }
private: private:
MutableArrayRef<PatternBindingEntry> getMutablePatternList() { MutableArrayRef<PatternBindingEntry> getMutablePatternList() {
// Pattern entries are tail allocated. // Pattern entries are tail allocated.
@@ -4606,6 +4649,14 @@ public:
return nullptr; return nullptr;
} }
// Return whether this VarDecl has an initial value, either by checking
// if it has an initializer in its parent pattern binding or if it has
// the @_hasInitialValue attribute.
bool hasInitialValue() const {
return getAttrs().hasAttribute<HasInitialValueAttr>() ||
getParentInitializer();
}
VarDecl *getOverriddenDecl() const { VarDecl *getOverriddenDecl() const {
return cast_or_null<VarDecl>(AbstractStorageDecl::getOverriddenDecl()); return cast_or_null<VarDecl>(AbstractStorageDecl::getOverriddenDecl());
} }
@@ -4687,6 +4738,13 @@ public:
void setHasNonPatternBindingInit(bool V = true) { void setHasNonPatternBindingInit(bool V = true) {
Bits.VarDecl.HasNonPatternBindingInit = V; Bits.VarDecl.HasNonPatternBindingInit = V;
} }
/// Determines if this var has an initializer expression that should be
/// exposed to clients.
/// There's a very narrow case when we would: if the decl is an instance
/// member with an initializer expression and the parent type is
/// @_fixed_layout and resides in a resilient module.
bool isInitExposedToClients() const;
/// Is this a special debugger variable? /// Is this a special debugger variable?
bool isDebuggerVar() const { return Bits.VarDecl.IsDebuggerVar; } bool isDebuggerVar() const { return Bits.VarDecl.IsDebuggerVar; }

View File

@@ -887,6 +887,9 @@ public:
/// Reads inlinable body text from \c DeclTypeCursor, if present. /// Reads inlinable body text from \c DeclTypeCursor, if present.
Optional<StringRef> maybeReadInlinableBodyText(); Optional<StringRef> maybeReadInlinableBodyText();
/// Reads pattern initializer text from \c DeclTypeCursor, if present.
Optional<StringRef> maybeReadPatternInitializerText();
}; };
template <typename T, typename RawData> template <typename T, typename RawData>

View File

@@ -55,7 +55,7 @@ const uint16_t VERSION_MAJOR = 0;
/// describe what change you made. The content of this comment isn't important; /// describe what change you made. The content of this comment isn't important;
/// it just ensures a conflict if two people change the module format. /// it just ensures a conflict if two people change the module format.
/// Don't worry about adhering to the 80-column limit for this line. /// Don't worry about adhering to the 80-column limit for this line.
const uint16_t VERSION_MINOR = 450; // Last change: don't serialize requirement environment const uint16_t VERSION_MINOR = 451; // Last change: pattern initializer text
using DeclIDField = BCFixed<31>; using DeclIDField = BCFixed<31>;
@@ -1478,7 +1478,8 @@ namespace decls_block {
using PatternBindingInitializerLayout = BCRecordLayout< using PatternBindingInitializerLayout = BCRecordLayout<
PATTERN_BINDING_INITIALIZER_CONTEXT, PATTERN_BINDING_INITIALIZER_CONTEXT,
DeclIDField, // parent pattern binding decl DeclIDField, // parent pattern binding decl
BCVBR<3> // binding index in the pattern binding decl BCVBR<3>, // binding index in the pattern binding decl
BCBlob // initializer text, if present
>; >;
using DefaultArgumentInitializerLayout = BCRecordLayout< using DefaultArgumentInitializerLayout = BCRecordLayout<

View File

@@ -842,26 +842,35 @@ void PrintAST::printAttributes(const Decl *D) {
if (Options.SkipAttributes) if (Options.SkipAttributes)
return; return;
// Don't print a redundant 'final' if we are printing a 'static' decl. // Save the current number of exclude attrs to restore once we're done.
unsigned originalExcludeAttrCount = Options.ExcludeAttrList.size(); unsigned originalExcludeAttrCount = Options.ExcludeAttrList.size();
if (Options.PrintImplicitAttrs &&
D->getDeclContext()->getSelfClassDecl() &&
getCorrectStaticSpelling(D) == StaticSpellingKind::KeywordStatic) {
Options.ExcludeAttrList.push_back(DAK_Final);
}
// Don't print any contextual decl modifiers. if (Options.PrintImplicitAttrs) {
// We will handle 'mutating' and 'nonmutating' separately.
if (Options.PrintImplicitAttrs && isa<AccessorDecl>(D)) { // Don't print a redundant 'final' if we are printing a 'static' decl.
if (D->getDeclContext()->getSelfClassDecl() &&
getCorrectStaticSpelling(D) == StaticSpellingKind::KeywordStatic) {
Options.ExcludeAttrList.push_back(DAK_Final);
}
// Don't print @_hasInitialValue if we're printing an initializer
// expression.
if (auto vd = dyn_cast<VarDecl>(D)) {
if (vd->isInitExposedToClients())
Options.ExcludeAttrList.push_back(DAK_HasInitialValue);
}
// Don't print any contextual decl modifiers.
// We will handle 'mutating' and 'nonmutating' separately.
if (isa<AccessorDecl>(D)) {
#define EXCLUDE_ATTR(Class) Options.ExcludeAttrList.push_back(DAK_##Class); #define EXCLUDE_ATTR(Class) Options.ExcludeAttrList.push_back(DAK_##Class);
#define CONTEXTUAL_DECL_ATTR(X, Class, Y, Z) EXCLUDE_ATTR(Class) #define CONTEXTUAL_DECL_ATTR(X, Class, Y, Z) EXCLUDE_ATTR(Class)
#define CONTEXTUAL_SIMPLE_DECL_ATTR(X, Class, Y, Z) EXCLUDE_ATTR(Class) #define CONTEXTUAL_SIMPLE_DECL_ATTR(X, Class, Y, Z) EXCLUDE_ATTR(Class)
#define CONTEXTUAL_DECL_ATTR_ALIAS(X, Class) EXCLUDE_ATTR(Class) #define CONTEXTUAL_DECL_ATTR_ALIAS(X, Class) EXCLUDE_ATTR(Class)
#include "swift/AST/Attr.def" #include "swift/AST/Attr.def"
} }
// If the declaration is implicitly @objc, print the attribute now. // If the declaration is implicitly @objc, print the attribute now.
if (Options.PrintImplicitAttrs) {
if (auto VD = dyn_cast<ValueDecl>(D)) { if (auto VD = dyn_cast<ValueDecl>(D)) {
if (VD->isObjC() && !VD->getAttrs().hasAttribute<ObjCAttr>()) { if (VD->isObjC() && !VD->getAttrs().hasAttribute<ObjCAttr>()) {
Printer.printAttrName("@objc"); Printer.printAttrName("@objc");
@@ -899,7 +908,10 @@ void PrintAST::printPattern(const Pattern *pattern) {
recordDeclLoc(decl, [&]{ recordDeclLoc(decl, [&]{
if (Options.OmitNameOfInaccessibleProperties && if (Options.OmitNameOfInaccessibleProperties &&
contributesToParentTypeStorage(decl) && contributesToParentTypeStorage(decl) &&
!isPublicOrUsableFromInline(decl)) !isPublicOrUsableFromInline(decl) &&
// FIXME: We need to figure out a way to generate an entry point
// for the initializer expression without revealing the name.
!decl->hasInitialValue())
Printer << "_"; Printer << "_";
else else
Printer.printName(named->getBoundName()); Printer.printName(named->getBoundName());
@@ -2045,7 +2057,7 @@ void PrintAST::visitPatternBindingDecl(PatternBindingDecl *decl) {
} }
bool isFirst = true; bool isFirst = true;
for (auto entry : decl->getPatternList()) { for (auto &entry : decl->getPatternList()) {
if (!shouldPrintPattern(entry.getPattern())) if (!shouldPrintPattern(entry.getPattern()))
continue; continue;
if (isFirst) if (isFirst)
@@ -2065,6 +2077,13 @@ void PrintAST::visitPatternBindingDecl(PatternBindingDecl *decl) {
if (Options.VarInitializers) { if (Options.VarInitializers) {
// FIXME: Implement once we can pretty-print expressions. // FIXME: Implement once we can pretty-print expressions.
} }
auto vd = entry.getAnchoringVarDecl();
if (entry.hasInitStringRepresentation() &&
vd->isInitExposedToClients()) {
SmallString<128> scratch;
Printer << " = " << entry.getInitStringRepresentation(scratch);
}
} }
} }

View File

@@ -1181,18 +1181,19 @@ unsigned PatternBindingDecl::getPatternEntryIndexForVarDecl(const VarDecl *VD) c
} }
SourceRange PatternBindingEntry::getOrigInitRange() const { SourceRange PatternBindingEntry::getOrigInitRange() const {
auto Init = InitAndFlags.getPointer(); auto Init = getInitAsWritten();
return Init ? Init->getSourceRange() : SourceRange(); return Init ? Init->getSourceRange() : SourceRange();
} }
void PatternBindingEntry::setInit(Expr *E) { void PatternBindingEntry::setInit(Expr *E) {
auto F = InitAndFlags.getInt(); auto F = PatternAndFlags.getInt();
if (E) { if (E) {
InitAndFlags.setInt(F - Flags::Removed); PatternAndFlags.setInt(F - Flags::Removed);
InitAndFlags.setPointer(E);
} else { } else {
InitAndFlags.setInt(F | Flags::Removed); PatternAndFlags.setInt(F | Flags::Removed);
} }
InitExpr.Node = E;
InitContextAndIsText.setInt(false);
} }
VarDecl *PatternBindingEntry::getAnchoringVarDecl() const { VarDecl *PatternBindingEntry::getAnchoringVarDecl() const {
@@ -1225,6 +1226,25 @@ SourceRange PatternBindingEntry::getSourceRange(bool omitAccessors) const {
return SourceRange(startLoc, endLoc); return SourceRange(startLoc, endLoc);
} }
bool PatternBindingEntry::hasInitStringRepresentation() const {
if (InitContextAndIsText.getInt())
return !InitStringRepresentation.empty();
return getInit() && getInit()->getSourceRange().isValid();
}
StringRef PatternBindingEntry::getInitStringRepresentation(
SmallVectorImpl<char> &scratch) const {
assert(hasInitStringRepresentation() &&
"must check if pattern has string representation");
if (InitContextAndIsText.getInt() && !InitStringRepresentation.empty())
return InitStringRepresentation;
auto &sourceMgr = getAnchoringVarDecl()->getASTContext().SourceMgr;
auto init = getInit();
return extractInlinableText(sourceMgr, init, scratch);
}
SourceRange PatternBindingDecl::getSourceRange() const { SourceRange PatternBindingDecl::getSourceRange() const {
SourceLoc startLoc = getStartLoc(); SourceLoc startLoc = getStartLoc();
SourceLoc endLoc = getPatternList().back().getSourceRange().End; SourceLoc endLoc = getPatternList().back().getSourceRange().End;
@@ -1279,6 +1299,19 @@ VarDecl *PatternBindingDecl::getSingleVar() const {
return nullptr; return nullptr;
} }
bool VarDecl::isInitExposedToClients() const {
auto parent = dyn_cast<NominalTypeDecl>(getDeclContext());
if (!parent) return false;
if (!hasInitialValue())
return false;
if (isStatic())
return false;
if (!parent->getAttrs().hasAttribute<FixedLayoutAttr>())
return false;
auto *module = parent->getModuleContext();
return module->getResilienceStrategy() == ResilienceStrategy::Resilient;
}
/// Check whether the given type representation will be /// Check whether the given type representation will be
/// default-initializable. /// default-initializable.
static bool isDefaultInitializable(const TypeRepr *typeRepr) { static bool isDefaultInitializable(const TypeRepr *typeRepr) {

View File

@@ -2483,7 +2483,7 @@ bool TypeChecker::typeCheckPatternBinding(PatternBindingDecl *PBD,
// Add the attribute that preserves the "has an initializer" value across // Add the attribute that preserves the "has an initializer" value across
// module generation, as required for TBDGen. // module generation, as required for TBDGen.
PBD->getPattern(patternNumber)->forEachVariable([&](VarDecl *VD) { PBD->getPattern(patternNumber)->forEachVariable([&](VarDecl *VD) {
if (VD->hasStorage()) if (VD->hasStorage() && !VD->getAttrs().hasAttribute<HasInitialValueAttr>())
VD->getAttrs().add(new (ctx) HasInitialValueAttr(/*IsImplicit=*/true)); VD->getAttrs().add(new (ctx) HasInitialValueAttr(/*IsImplicit=*/true));
}); });

View File

@@ -1837,6 +1837,9 @@ DeclContext *ModuleFile::getLocalDeclContext(DeclContextID DCID) {
if (!declContextOrOffset.isComplete()) if (!declContextOrOffset.isComplete())
declContextOrOffset = new (ctx) declContextOrOffset = new (ctx)
SerializedPatternBindingInitializer(binding, bindingIndex); SerializedPatternBindingInitializer(binding, bindingIndex);
if (!blobData.empty())
binding->setInitStringRepresentation(bindingIndex, blobData);
break; break;
} }

View File

@@ -2438,9 +2438,19 @@ void Serializer::writePatternBindingInitializer(PatternBindingDecl *binding,
unsigned bindingIndex) { unsigned bindingIndex) {
using namespace decls_block; using namespace decls_block;
auto abbrCode = DeclTypeAbbrCodes[PatternBindingInitializerLayout::Code]; auto abbrCode = DeclTypeAbbrCodes[PatternBindingInitializerLayout::Code];
StringRef initStr;
SmallString<128> scratch;
auto &entry = binding->getPatternList()[bindingIndex];
auto varDecl = entry.getAnchoringVarDecl();
if (entry.hasInitStringRepresentation() &&
varDecl->isInitExposedToClients()) {
initStr = entry.getInitStringRepresentation(scratch);
}
PatternBindingInitializerLayout::emitRecord(Out, ScratchRecord, PatternBindingInitializerLayout::emitRecord(Out, ScratchRecord,
abbrCode, addDeclRef(binding), abbrCode, addDeclRef(binding),
bindingIndex); bindingIndex, initStr);
} }
void void

View File

@@ -0,0 +1,76 @@
// RUN: %empty-directory(%t)
// RUN: %target-swift-frontend -typecheck -emit-parseable-module-interface-path %t.swiftinterface %s
// RUN: %FileCheck %s < %t.swiftinterface --check-prefix CHECK --check-prefix COMMON
// RUN: %target-swift-frontend -typecheck -emit-parseable-module-interface-path %t-resilient.swiftinterface -enable-resilience %s
// RUN: %FileCheck %s --check-prefix RESILIENT --check-prefix COMMON < %t-resilient.swiftinterface
// FIXME(rdar44993525): %target-swift-frontend -emit-module -o %t/Test.swiftmodule %t.swiftinterface -disable-objc-attr-requires-foundation-module
// FIXME(rdar44993525): %target-swift-frontend -emit-module -o /dev/null -merge-modules %t/Test.swiftmodule -module-name Test -emit-parseable-module-interface-path - | %FileCheck %s --check-prefix CHECK --check-prefix COMMON
// RUN: %target-swift-frontend -emit-module -o %t/TestResilient.swiftmodule -enable-resilience %t-resilient.swiftinterface -disable-objc-attr-requires-foundation-module
// RUN: %target-swift-frontend -emit-module -o /dev/null -merge-modules %t/TestResilient.swiftmodule -module-name TestResilient -enable-resilience -emit-parseable-module-interface-path - | %FileCheck %s --check-prefix RESILIENT --check-prefix COMMON
// COMMON: @_fixed_layout public struct MyStruct {
@_fixed_layout
public struct MyStruct {
// CHECK: @_hasInitialValue public var publicVar: [[BOOL:(Swift\.)?Bool]]{{$}}
// RESILIENT: public var publicVar: [[BOOL:(Swift\.)?Bool]] = false
public var publicVar: Bool = false
// CHECK: @_hasInitialValue internal var internalVar: ([[BOOL]], [[BOOL]]){{$}}
// RESILIENT: internal var internalVar: ([[BOOL]], [[BOOL]]) = (false, true)
internal var internalVar: (Bool, Bool) = (false, true)
// CHECK: @_hasInitialValue private var privateVar: [[BOOL]]{{$}}
// RESILIENT: private var privateVar: [[BOOL]] = Bool(4 < 10)
private var privateVar: Bool = Bool(4 < 10)
// CHECK: @usableFromInline
// CHECK-NEXT: internal var ufiVar: [[BOOL]]{{$}}
// RESILIENT: @usableFromInline
// RESILIENT-NEXT: internal var ufiVar: [[BOOL]] = true
@usableFromInline internal var ufiVar: Bool = true
// CHECK: @_hasInitialValue public var multiVar1: [[BOOL]], (multiVar2, multiVar3): ([[BOOL]], [[BOOL]])
// RESILIENT: public var multiVar1: [[BOOL]] = Bool(false), (multiVar2, multiVar3): ([[BOOL]], [[BOOL]]) = (true, 3 == 0)
public var multiVar1: Bool = Bool(false), (multiVar2, multiVar3): (Bool, Bool) = (true, 3 == 0)
// COMMON: @_hasInitialValue public static var staticVar: [[BOOL]]
public static var staticVar: Bool = Bool(true && false)
// COMMON: @inlinable internal init() {}
@inlinable init() {}
}
// COMMON: @_fixed_layout public class MyClass {
@_fixed_layout
public class MyClass {
// CHECK: @_hasInitialValue public var publicVar: [[BOOL]]{{$}}
// RESILIENT: public var publicVar: [[BOOL]] = false
public var publicVar: Bool = false
// CHECK: @_hasInitialValue internal var internalVar: [[BOOL]]{{$}}
// RESILIENT: internal var internalVar: [[BOOL]] = false
internal var internalVar: Bool = false
// CHECK: @_hasInitialValue private var privateVar: {{(Swift\.)?}}UInt8{{$}}
// RESILIENT: private var privateVar: {{(Swift\.)?}}UInt8 = UInt8(2)
private var privateVar: UInt8 = UInt8(2)
// CHECK: @usableFromInline
// CHECK-NEXT: internal var ufiVar: [[BOOL]]{{$}}
// RESILIENT: @usableFromInline
// RESILIENT: internal var ufiVar: [[BOOL]] = true
@usableFromInline internal var ufiVar: Bool = true
// COMMON: @_hasInitialValue public static var staticVar: [[BOOL]]
public static var staticVar: Bool = Bool(true && false)
// COMMON: @inlinable internal init() {}
@inlinable init() {}
}
// COMMON: @_hasInitialValue public var topLevelVar: [[BOOL]]
public var topLevelVar: Bool = Bool(false && !true)

View File

@@ -69,12 +69,12 @@ public class MyClass {
// COMMON-NEXT: let publicLet: [[BOOL]]{{$}} // COMMON-NEXT: let publicLet: [[BOOL]]{{$}}
public let publicLet: Bool = true public let publicLet: Bool = true
// CHECK-NEXT: internal var _: [[INT64]]{{$}} // CHECK-NEXT: internal var internalVar: [[INT64]]{{$}}
// RESILIENT-NOT: internal var _: [[INT64]]{{$}} // RESILIENT-NOT: internal var internalVar: [[INT64]]{{$}}
var internalVar: Int64 = 0 var internalVar: Int64 = 0
// CHECK-NEXT: internal let _: [[BOOL]]{{$}} // CHECK-NEXT: internal let internalLet: [[BOOL]]{{$}}
// RESILIENT-NOT: internal let _: [[BOOL]]{{$}} // RESILIENT-NOT: internal let internalLet: [[BOOL]]{{$}}
let internalLet: Bool = true let internalLet: Bool = true
// COMMON-NEXT: @usableFromInline // COMMON-NEXT: @usableFromInline
@@ -85,12 +85,12 @@ public class MyClass {
// COMMON-NEXT: internal let ufiLet: [[BOOL]]{{$}} // COMMON-NEXT: internal let ufiLet: [[BOOL]]{{$}}
@usableFromInline let ufiLet: Bool = true @usableFromInline let ufiLet: Bool = true
// CHECK-NEXT: private var _: [[INT64]]{{$}} // CHECK-NEXT: private var privateVar: [[INT64]]{{$}}
// RESILIENT-NOT: private var _: [[INT64]]{{$}} // RESILIENT-NOT: private var privateVar: [[INT64]]{{$}}
private var privateVar: Int64 = 0 private var privateVar: Int64 = 0
// CHECK-NEXT: private let _: [[BOOL]]{{$}} // CHECK-NEXT: private let privateLet: [[BOOL]]{{$}}
// RESILIENT-NOT: private let _: [[BOOL]]{{$}} // RESILIENT-NOT: private let privateLet: [[BOOL]]{{$}}
private let privateLet: Bool = true private let privateLet: Bool = true
// CHECK-NOT: private var // CHECK-NOT: private var