Skip to content

Serialize fewer archetypes and tidy up casts #7139

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

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 6 additions & 3 deletions include/swift/AST/Decl.h
Original file line number Diff line number Diff line change
Expand Up @@ -325,8 +325,11 @@ class alignas(1 << DeclAlignInBits) Decl {
/// \brief Whether or not this element directly or indirectly references
/// the enum type.
unsigned Recursiveness : 2;

/// \brief Whther or not this element has an associated value.
unsigned HasArgumentType : 1;
};
enum { NumEnumElementDeclBits = NumValueDeclBits + 2 };
enum { NumEnumElementDeclBits = NumValueDeclBits + 3 };
static_assert(NumEnumElementDeclBits <= 32, "fits in an unsigned");

class AbstractFunctionDeclBitfields {
Expand Down Expand Up @@ -5323,6 +5326,7 @@ class EnumElementDecl : public ValueDecl {
public:
EnumElementDecl(SourceLoc IdentifierLoc, Identifier Name,
TypeLoc ArgumentType,
bool HasArgumentType,
SourceLoc EqualsLoc,
LiteralExpr *RawValueExpr,
DeclContext *DC)
Expand All @@ -5333,14 +5337,13 @@ class EnumElementDecl : public ValueDecl {
{
EnumElementDeclBits.Recursiveness =
static_cast<unsigned>(ElementRecursiveness::NotRecursive);
EnumElementDeclBits.HasArgumentType = HasArgumentType;
}

/// \returns false if there was an error during the computation rendering the
/// EnumElementDecl invalid, true otherwise.
bool computeType();

bool hasArgumentType() const { return !ArgumentType.getType().isNull(); }
Type getArgumentType() const { return ArgumentType.getType(); }
Type getArgumentInterfaceType() const;

TypeLoc &getArgumentTypeLoc() { return ArgumentType; }
Expand Down
4 changes: 2 additions & 2 deletions include/swift/Serialization/ModuleFormat.h
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ const uint16_t VERSION_MAJOR = 0;
/// in source control, you should also update the comment to briefly
/// 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.
const uint16_t VERSION_MINOR = 308; // Last change: nested type table
const uint16_t VERSION_MINOR = 309; // Last change: remove enum argument type

using DeclID = PointerEmbeddedInt<unsigned, 31>;
using DeclIDField = BCFixed<31>;
Expand Down Expand Up @@ -975,8 +975,8 @@ namespace decls_block {
ENUM_ELEMENT_DECL,
IdentifierIDField, // name
DeclContextIDField,// context decl
TypeIDField, // argument type
TypeIDField, // interface type
BCFixed<1>, // has argument type?
BCFixed<1>, // implicit?
EnumElementRawValueKindField, // raw value kind
BCFixed<1>, // negative raw value?
Expand Down
15 changes: 7 additions & 8 deletions lib/AST/ASTPrinter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -325,7 +325,7 @@ struct SynthesizedExtensionAnalyzer::Implementation {

std::unique_ptr<ExtensionInfoMap>
collectSynthesizedExtensionInfo(MergeGroupVector &AllGroups) {
if (Target->getKind() == DeclKind::Protocol) {
if (isa<ProtocolDecl>(Target)) {
return collectSynthesizedExtensionInfoForProtocol(AllGroups);
}
std::unique_ptr<ExtensionInfoMap> InfoMap(new ExtensionInfoMap());
Expand Down Expand Up @@ -553,7 +553,7 @@ void ASTPrinter::callPrintDeclPre(const Decl *D,
Optional<BracketOptions> Bracket) {
forceNewlines();

if (SynthesizeTarget && D->getKind() == DeclKind::Extension)
if (SynthesizeTarget && isa<ExtensionDecl>(D))
printSynthesizedExtensionPre(cast<ExtensionDecl>(D), SynthesizeTarget, Bracket);
else
printDeclPre(D, Bracket);
Expand Down Expand Up @@ -1006,7 +1006,7 @@ class PrintAST : public ASTVisitor<PrintAST> {
bool Synthesize =
Options.TransformContext &&
Options.TransformContext->isPrintingSynthesizedExtension() &&
D->getKind() == DeclKind::Extension;
isa<ExtensionDecl>(D);
if (Synthesize)
Printer.setSynthesizedTarget(Options.TransformContext->getNominal());

Expand Down Expand Up @@ -2016,7 +2016,7 @@ static void printExtendedTypeName(Type ExtendedType, ASTPrinter &Printer,
}

// Respect alias type.
if (ExtendedType->getKind() == TypeKind::NameAlias) {
if (isa<NameAliasType>(ExtendedType.getPointer())) {
ExtendedType.print(Printer, Options);
return;
}
Expand Down Expand Up @@ -2720,10 +2720,9 @@ void PrintAST::printEnumElement(EnumElementDecl *elt) {
Printer.printName(elt->getName());
});

if (elt->hasArgumentType()) {
Type Ty = elt->getArgumentType();
if (!Options.SkipPrivateStdlibDecls || !Ty.isPrivateStdlibType())
Ty.print(Printer, Options);
if (auto argTy = elt->getArgumentInterfaceType()) {
if (!Options.SkipPrivateStdlibDecls || !argTy.isPrivateStdlibType())
argTy.print(Printer, Options);
}

auto *raw = elt->getRawValueExpr();
Expand Down
8 changes: 3 additions & 5 deletions lib/AST/ASTWalker.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -321,11 +321,9 @@ class Traversal : public ASTVisitor<Traversal, Expr*, Stmt*,
}

bool visitEnumElementDecl(EnumElementDecl *ED) {
if (ED->hasArgumentType()) {
if (auto TR = ED->getArgumentTypeLoc().getTypeRepr()) {
if (doIt(TR)) {
return true;
}
if (auto TR = ED->getArgumentTypeLoc().getTypeRepr()) {
if (doIt(TR)) {
return true;
}
}

Expand Down
4 changes: 2 additions & 2 deletions lib/AST/Decl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4702,7 +4702,7 @@ bool EnumElementDecl::computeType() {
Type selfTy = MetatypeType::get(resultTy);

// The type of the enum element is either (T) -> T or (T) -> ArgType -> T.
if (auto inputTy = getArgumentType()) {
if (auto inputTy = getArgumentTypeLoc().getType()) {
resultTy = FunctionType::get(ED->mapTypeOutOfContext(inputTy), resultTy);
}

Expand All @@ -4719,7 +4719,7 @@ bool EnumElementDecl::computeType() {
}

Type EnumElementDecl::getArgumentInterfaceType() const {
if (!hasArgumentType())
if (!EnumElementDeclBits.HasArgumentType)
return nullptr;

auto interfaceType = getInterfaceType();
Expand Down
4 changes: 2 additions & 2 deletions lib/ClangImporter/ImportDecl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4837,8 +4837,8 @@ Decl *SwiftDeclConverter::importEnumCase(const clang::EnumConstantDecl *decl,
rawValueExpr->setNegative(SourceLoc());

auto element = Impl.createDeclWithClangNode<EnumElementDecl>(
decl, Accessibility::Public, SourceLoc(), name, TypeLoc(), SourceLoc(),
rawValueExpr, theEnum);
decl, Accessibility::Public, SourceLoc(), name, TypeLoc(), false,
SourceLoc(), rawValueExpr, theEnum);

// Give the enum element the appropriate type.
element->computeType();
Expand Down
20 changes: 10 additions & 10 deletions lib/IDE/CodeCompletion.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -913,8 +913,8 @@ static CodeCompletionResult::ExpectedTypeRelation calculateTypeRelation(
Type ExpectedTy,
DeclContext *DC) {
if (Ty.isNull() || ExpectedTy.isNull() ||
Ty->getKind() == TypeKind::Error ||
ExpectedTy->getKind() == TypeKind::Error)
Ty->is<ErrorType>() ||
ExpectedTy->is<ErrorType>())
return CodeCompletionResult::ExpectedTypeRelation::Unrelated;
if (Ty->isEqual(ExpectedTy))
return CodeCompletionResult::ExpectedTypeRelation::Identical;
Expand Down Expand Up @@ -2694,8 +2694,8 @@ class CompletionLookup final : public swift::VisibleDeclConsumer {
setClangDeclKeywords(EED, Pairs, Builder);
addLeadingDot(Builder);
Builder.addTextChunk(EED->getName().str());
if (EED->hasArgumentType())
addPatternFromType(Builder, EED->getArgumentType());
if (auto argTy = EED->getArgumentInterfaceType())
addPatternFromType(Builder, argTy);

// Enum element is of function type such as EnumName.type -> Int ->
// EnumName; however we should show Int -> EnumName as the type
Expand Down Expand Up @@ -2833,7 +2833,7 @@ class CompletionLookup final : public swift::VisibleDeclConsumer {
Optional<Type> Result = None;
if (auto AT = MT->getInstanceType()) {
if (!CD->getInterfaceType()->is<ErrorType>() &&
AT->getKind() == TypeKind::NameAlias &&
isa<NameAliasType>(AT.getPointer()) &&
AT->getDesugaredType() ==
CD->getResultInterfaceType().getPointer())
Result = AT;
Expand Down Expand Up @@ -3658,9 +3658,9 @@ class CompletionLookup final : public swift::VisibleDeclConsumer {
}

void unboxType(Type T) {
if (T->getKind() == TypeKind::Paren) {
if (isa<ParenType>(T.getPointer())) {
unboxType(T->getDesugaredType());
} else if (T->getKind() == TypeKind::Tuple) {
} else if (T->is<TupleType>()) {
for (auto Ele : T->getAs<TupleType>()->getElements()) {
unboxType(Ele.getType());
}
Expand Down Expand Up @@ -3838,7 +3838,7 @@ class CompletionLookup final : public swift::VisibleDeclConsumer {
DeclContext *DC) {
for (auto It = PossibleArgTypes.begin(); It != PossibleArgTypes.end(); ) {
llvm::SmallVector<Type, 3> ExpectedTypes;
if ((*It)->getKind() == TypeKind::Tuple) {
if (isa<TupleType>((*It).getPointer())) {
auto Elements = (*It)->getAs<TupleType>()->getElements();
for (auto Ele : Elements)
ExpectedTypes.push_back(Ele.getType());
Expand Down Expand Up @@ -3874,7 +3874,7 @@ class CompletionLookup final : public swift::VisibleDeclConsumer {
removeUnlikelyOverloads(PossibleTypes, TupleEleTypesBeforeTarget, &DC);
return !PossibleTypes.empty();
}
} else if (CallE->getArg()->getKind() == ExprKind::Paren) {
} else if (isa<ParenExpr>(CallE->getArg())) {
Position = 0;
HasName = false;
if (PossibleTypes.empty() &&
Expand Down Expand Up @@ -4230,7 +4230,7 @@ class CompletionOverrideLookup : public swift::VisibleDeclConsumer {
// Implement swift::VisibleDeclConsumer.
void foundDecl(ValueDecl *D, DeclVisibilityKind Reason) override {
if (Reason == DeclVisibilityKind::MemberOfCurrentNominal) {
if (D->getKind() == DeclKind::TypeAlias) {
if (isa<TypeAliasDecl>(D)) {
ValueDecl *VD = dyn_cast<ValueDecl>(D);
SatisfiedAssociatedTypes.insert(VD->getName().str());
}
Expand Down
2 changes: 1 addition & 1 deletion lib/IDE/Formatting.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -420,7 +420,7 @@ class FormatContext {
} else if (auto *Seq = dyn_cast_or_null<SequenceExpr>(Cursor->getAsExpr())) {
ArrayRef<Expr*> Elements = Seq->getElements();
if (Elements.size() == 3 &&
Elements[1]->getKind() == ExprKind::Assign &&
isa<AssignExpr>(Elements[1]) &&
SM.getLineAndColumn(Elements[2]->getEndLoc()).first == Line) {
return false;
}
Expand Down
2 changes: 1 addition & 1 deletion lib/IDE/TypeReconstruction.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -514,7 +514,7 @@ static bool FindFirstNamedDeclWithKind(
// If we didn't find any exact matches, accept any type aliases
if (check_type_aliases) {
for (auto decl : decls) {
if (decl->getKind() == DeclKind::TypeAlias) {
if (isa<TypeAliasDecl>(decl)) {
result._decls.assign(1, decl);
if (decl->hasInterfaceType()) {
result._types.assign(1, decl->getInterfaceType());
Expand Down
34 changes: 19 additions & 15 deletions lib/IRGen/DebugTypeInfo.h
Original file line number Diff line number Diff line change
Expand Up @@ -78,25 +78,29 @@ class DebugTypeInfo {

void unwrapLValueOrInOutType() {
Type = Type->getLValueOrInOutObjectType().getPointer();
}
}

// Determine whether this type is an Archetype itself.
bool isArchetype() const {
return Type->getLValueOrInOutObjectType()->is<ArchetypeType>();
}
// Determine whether this type is an Archetype itself.
bool isArchetype() const {
return Type->getLValueOrInOutObjectType()->is<ArchetypeType>();
}

/// LValues, inout args, and Archetypes are implicitly indirect by
/// virtue of their DWARF type.
bool isImplicitlyIndirect() const {
return Type->isLValueType() || isArchetype() ||
(Type->getKind() == TypeKind::InOut);
}
/// LValues, inout args, and Archetypes are implicitly indirect by
/// virtue of their DWARF type.
//
// FIXME: Should this check if the lowered SILType is address only
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@adrian-prantl What do you think? Should we be checking the SIL type lowering instead?

Also class-bound archetypes are not passed indirectly, so it's wrong in that case too.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, please go ahead.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How can I construct a test case to verify my hypothesis? I don't want to start blindly changing this stuff without understanding what's going on :)

// instead? Otherwise optionals of archetypes etc will still have
// 'isImplicitlyIndirect()' return false.
bool isImplicitlyIndirect() const {
return Type->isLValueType() || isArchetype() ||
Type->is<InOutType>();
}

bool isNull() const { return Type == nullptr; }
bool operator==(DebugTypeInfo T) const;
bool operator!=(DebugTypeInfo T) const;
bool isNull() const { return Type == nullptr; }
bool operator==(DebugTypeInfo T) const;
bool operator!=(DebugTypeInfo T) const;

void dump() const;
void dump() const;
};
}
}
Expand Down
12 changes: 9 additions & 3 deletions lib/IRGen/GenEnum.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -187,7 +187,9 @@ const {

// Empty payload addresses can be left undefined.
if (payloadI == ElementsWithPayload.end()) {
return IGF.getTypeInfoForUnlowered(elt->getArgumentType())
auto argTy = elt->getParentEnum()->mapTypeIntoContext(
elt->getArgumentInterfaceType());
return IGF.getTypeInfoForUnlowered(argTy)
.getUndefAddress();
}

Expand All @@ -208,7 +210,9 @@ const {

// Empty payload addresses can be left undefined.
if (payloadI == ElementsWithPayload.end()) {
return IGF.getTypeInfoForUnlowered(Case->getArgumentType())
auto argTy = Case->getParentEnum()->mapTypeIntoContext(
Case->getArgumentInterfaceType());
return IGF.getTypeInfoForUnlowered(argTy)
.getUndefAddress();
}

Expand Down Expand Up @@ -4980,7 +4984,7 @@ EnumImplStrategy::get(TypeConverter &TC, SILType type, EnumDecl *theEnum) {
// strategy. If the abstract layout of the enum is dependent on generic
// parameters, then we additionally need to constrain any layout
// optimizations we perform to things that are reproducible by the runtime.
Type origArgType = elt->getArgumentType();
Type origArgType = elt->getArgumentInterfaceType();
if (origArgType.isNull()) {
elementsWithNoPayload.push_back({elt, nullptr, nullptr});
continue;
Expand All @@ -4994,6 +4998,8 @@ EnumImplStrategy::get(TypeConverter &TC, SILType type, EnumDecl *theEnum) {
continue;
}

origArgType = theEnum->mapTypeIntoContext(origArgType);

auto origArgLoweredTy = TC.IGM.getLoweredType(origArgType);
const TypeInfo *origArgTI
= TC.tryGetCompleteTypeInfo(origArgLoweredTy.getSwiftRValueType());
Expand Down
12 changes: 7 additions & 5 deletions lib/IRGen/GenMeta.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2458,16 +2458,18 @@ namespace {
// using the lowered cases, i.e. the cases for Optional<>.
if (type->classifyAsOptionalType() == OTK_ImplicitlyUnwrappedOptional) {
assert(enumElements.size() == 1);
auto caseType =
IGM.Context.getImplicitlyUnwrappedOptionalSomeDecl()
->getArgumentType()->getCanonicalType();
auto decl = IGM.Context.getImplicitlyUnwrappedOptionalSomeDecl();
auto caseType = decl->getParentEnum()->mapTypeIntoContext(
decl->getArgumentInterfaceType())
->getCanonicalType();
types.push_back(FieldTypeInfo(caseType, false, false));
return getFieldTypeAccessorFn(IGM, type, types);
}

for (auto &elt : enumElements) {
assert(elt.decl->hasArgumentType() && "enum case doesn't have arg?!");
auto caseType = elt.decl->getArgumentType()->getCanonicalType();
auto caseType = elt.decl->getParentEnum()->mapTypeIntoContext(
elt.decl->getArgumentInterfaceType())
->getCanonicalType();
bool isIndirect = elt.decl->isIndirect()
|| elt.decl->getParentEnum()->isIndirect();
types.push_back(FieldTypeInfo(caseType, isIndirect, /*weak*/ false));
Expand Down
4 changes: 2 additions & 2 deletions lib/IRGen/GenType.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1499,7 +1499,7 @@ namespace {
return false;

for (auto elt : decl->getAllElements()) {
if (elt->hasArgumentType() &&
if (elt->getArgumentInterfaceType() &&
!elt->isIndirect() &&
visit(elt->getArgumentInterfaceType()->getCanonicalType()))
return true;
Expand Down Expand Up @@ -1902,7 +1902,7 @@ SILType irgen::getSingletonAggregateFieldType(IRGenModule &IGM, SILType t,

auto theCase = allCases.begin();
if (!allCases.empty() && std::next(theCase) == allCases.end()
&& (*theCase)->hasArgumentType())
&& (*theCase)->getArgumentInterfaceType())
return t.getEnumElementType(*theCase, IGM.getSILModule());

return SILType();
Expand Down
7 changes: 4 additions & 3 deletions lib/IRGen/IRGenDebugInfo.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1147,12 +1147,13 @@ llvm::DINodeArray IRGenDebugInfo::getEnumElements(DebugTypeInfo DbgTy,
// the storage size from the enum.
ElemDbgTy = DebugTypeInfo(ED, ED->getRawType(), DbgTy.StorageType,
DbgTy.size, DbgTy.align);
else if (ElemDecl->hasArgumentType()) {
else if (auto ArgTy = ElemDecl->getArgumentInterfaceType()) {
// A discriminated union. This should really be described as a
// DW_TAG_variant_type. For now only describing the data.
auto &TI = IGM.getTypeInfoForUnlowered(ElemDecl->getArgumentType());
ArgTy = ElemDecl->getParentEnum()->mapTypeIntoContext(ArgTy);
auto &TI = IGM.getTypeInfoForUnlowered(ArgTy);
ElemDbgTy =
DebugTypeInfo::getFromTypeInfo(ED, ElemDecl->getArgumentType(), TI);
DebugTypeInfo::getFromTypeInfo(ED, ArgTy, TI);
} else {
// Discriminated union case without argument. Fallback to Int
// as the element type; there is no storage here.
Expand Down
6 changes: 5 additions & 1 deletion lib/IRGen/IRGenSIL.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3278,9 +3278,13 @@ void IRGenSILFunction::visitDebugValueAddrInst(DebugValueAddrInst *i) {
auto RealType = SILTy.getSwiftType();
// Unwrap implicitly indirect types and types that are passed by
// reference only at the SIL level and below.
//
// FIXME: Should this check if the lowered SILType is address only
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

// instead? Otherwise optionals of archetypes etc will still have
// 'Unwrap' set to false.
bool Unwrap =
i->getVarInfo().Constant ||
RealType->getLValueOrInOutObjectType()->getKind() == TypeKind::Archetype;
RealType->getLValueOrInOutObjectType()->is<ArchetypeType>();
auto DbgTy = DebugTypeInfo::getLocalVariable(
CurSILFn->getDeclContext(), Decl, RealType,
getTypeInfo(SILVal->getType()), Unwrap);
Expand Down
Loading