Skip to content

Demangle inverse requirements when building AST types #72336

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
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
18 changes: 13 additions & 5 deletions include/swift/AST/ASTDemangler.h
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,7 @@ class ASTBuilder {
using BuiltProtocolDecl = swift::ProtocolDecl *;
using BuiltGenericSignature = swift::GenericSignature;
using BuiltRequirement = swift::Requirement;
using BuiltInverseRequirement = swift::InverseRequirement;
using BuiltSubstitutionMap = swift::SubstitutionMap;

static constexpr bool needsToPrecomputeParentGenericContextShapes = false;
Expand Down Expand Up @@ -161,8 +162,10 @@ class ASTBuilder {

Type createProtocolTypeFromDecl(ProtocolDecl *protocol);

Type createConstrainedExistentialType(Type base,
ArrayRef<BuiltRequirement> constraints);
Type createConstrainedExistentialType(
Type base,
ArrayRef<BuiltRequirement> constraints,
ArrayRef<BuiltInverseRequirement> inverseRequirements);

Type createSymbolicExtendedExistentialType(NodePointer shapeNode,
ArrayRef<Type> genArgs);
Expand Down Expand Up @@ -193,9 +196,11 @@ class ASTBuilder {
using BuiltSILBoxField = llvm::PointerIntPair<Type, 1>;
using BuiltSubstitution = std::pair<Type, Type>;
using BuiltLayoutConstraint = swift::LayoutConstraint;
Type createSILBoxTypeWithLayout(ArrayRef<BuiltSILBoxField> Fields,
ArrayRef<BuiltSubstitution> Substitutions,
ArrayRef<BuiltRequirement> Requirements);
Type createSILBoxTypeWithLayout(
ArrayRef<BuiltSILBoxField> Fields,
ArrayRef<BuiltSubstitution> Substitutions,
ArrayRef<BuiltRequirement> Requirements,
ArrayRef<BuiltInverseRequirement> inverseRequirements);

bool isExistential(Type type) {
return type->isExistentialType();
Expand Down Expand Up @@ -238,6 +243,9 @@ class ASTBuilder {
unsigned size,
unsigned alignment);

InverseRequirement createInverseRequirement(
Type subject, InvertibleProtocolKind kind);

private:
bool validateParentType(TypeDecl *decl, Type parent);
CanGenericSignature demangleGenericSignature(
Expand Down
12 changes: 12 additions & 0 deletions include/swift/AST/ASTMangler.h
Original file line number Diff line number Diff line change
Expand Up @@ -461,12 +461,24 @@ class ASTMangler : public Mangler {
bool innermostTypeDecl;
bool extension;
std::optional<unsigned> mangledDepth; // for inverses
std::optional<unsigned> suppressedInnermostDepth;
public:
bool reachedInnermostTypeDecl() {
bool answer = innermostTypeDecl;
innermostTypeDecl = false;
return answer;
}

/// Whether inverses of the innermost declaration's generic parameters
/// should be suppressed.
///
/// This makes sense only for entities that can only ever be defined
/// within the primary type, such as enum cases and the stored properties
/// of struct and class types.
std::optional<unsigned> getSuppressedInnermostInversesDepth() const {
return suppressedInnermostDepth;
}

bool reachedExtension() const { return extension; }
void setReachedExtension() { assert(!extension); extension = true; }
GenericSignature getSignature() const { return sig; }
Expand Down
33 changes: 33 additions & 0 deletions include/swift/AST/InvertibleProtocolKind.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
//===--- InvertibleProtocolKind.h - -----------------------------*- C++ -*-===//
//
// This source file is part of the Swift.org open source project
//
// Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
// See https://swift.org/LICENSE.txt for license information
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
//
//===----------------------------------------------------------------------===//
//
// This header declares the InvertibleProtocolKind enum and some
// related operations.
//
//===----------------------------------------------------------------------===//

#ifndef SWIFT_AST_INVERTIBLEPROTOCOLKIND_H
#define SWIFT_AST_INVERTIBLEPROTOCOLKIND_H

#include <stdint.h>

namespace swift {

enum class InvertibleProtocolKind : uint8_t {
#define INVERTIBLE_PROTOCOL_WITH_NAME(Id, Name) Id,
#include "swift/AST/KnownProtocols.def"
};


} // end namespace swift

#endif // SWIFT_AST_INVERTIBLEPROTOCOLKIND_H
6 changes: 1 addition & 5 deletions include/swift/AST/KnownProtocols.h
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@

#include "swift/Basic/InlineBitfield.h"
#include "swift/Basic/FixedBitSet.h"
#include "swift/AST/InvertibleProtocolKind.h"
#include "swift/Config.h"

namespace llvm {
Expand Down Expand Up @@ -57,11 +58,6 @@ enum : uint8_t {
#include "swift/AST/KnownProtocols.def"
};

enum class InvertibleProtocolKind : uint8_t {
#define INVERTIBLE_PROTOCOL_WITH_NAME(Id, Name) Id,
#include "swift/AST/KnownProtocols.def"
};

using InvertibleProtocolSet = FixedBitSet<NumInvertibleProtocols,
InvertibleProtocolKind>;

Expand Down
69 changes: 55 additions & 14 deletions include/swift/Demangling/TypeDecoder.h
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
#include "swift/Basic/LLVM.h"

#include "swift/ABI/MetadataValues.h"
#include "swift/AST/InvertibleProtocolKind.h"
#include "swift/AST/LayoutConstraintKind.h"
#include "swift/AST/RequirementKind.h"
#include "swift/Basic/OptionSet.h"
Expand Down Expand Up @@ -422,10 +423,13 @@ getObjCClassOrProtocolName(NodePointer node) {
#endif

template <typename BuiltType, typename BuiltRequirement,
typename BuiltInverseRequirement,
typename BuiltLayoutConstraint, typename BuilderType>
void decodeRequirement(NodePointer node,
llvm::SmallVectorImpl<BuiltRequirement> &requirements,
BuilderType &Builder) {
void decodeRequirement(
NodePointer node,
llvm::SmallVectorImpl<BuiltRequirement> &requirements,
llvm::SmallVectorImpl<BuiltInverseRequirement> &inverseRequirements,
BuilderType &Builder) {
for (auto &child : *node) {
if (child->getKind() == Demangle::Node::Kind::DependentGenericParamCount ||
child->getKind() == Demangle::Node::Kind::DependentGenericParamPackMarker)
Expand All @@ -451,9 +455,40 @@ void decodeRequirement(NodePointer node,
return;
} else if (child->getKind() ==
Demangle::Node::Kind::DependentGenericInverseConformanceRequirement) {
// FIXME(kavon): this is unimplemented! We should build a PCT here with
// the inverse in it.
return;
// Type child
auto constraintNode = child->getChild(1);
if (constraintNode->getKind() != Demangle::Node::Kind::Type ||
constraintNode->getNumChildren() != 1)
return;

// Protocol child
auto protocolNode = constraintNode->getChild(0);
if (protocolNode->getKind() != Demangle::Node::Kind::Protocol ||
protocolNode->getNumChildren() != 2)
return;

auto moduleNode = protocolNode->getChild(0);
if (moduleNode->getKind() != Demangle::Node::Kind::Module ||
moduleNode->getText() != "Swift")
return;

auto protocolNameNode = protocolNode->getChild(1);
if (protocolNameNode->getKind() != Demangle::Node::Kind::Identifier)
return;

auto protocolName = protocolNameNode->getText();
using OptInvertibleKind = std::optional<InvertibleProtocolKind>;
auto protocolKind = llvm::StringSwitch<OptInvertibleKind>(protocolName)
#define INVERTIBLE_PROTOCOL_WITH_NAME(Id, Name) \
.Case(Name, InvertibleProtocolKind::Id)
#include "swift/AST/KnownProtocols.def"
.Default(std::nullopt);
if (!protocolKind)
return;

inverseRequirements.push_back(
Builder.createInverseRequirement(subjectType, *protocolKind));
continue;
}


Expand Down Expand Up @@ -538,6 +573,7 @@ class TypeDecoder {
using Field = typename BuilderType::BuiltSILBoxField;
using BuiltSubstitution = typename BuilderType::BuiltSubstitution;
using BuiltRequirement = typename BuilderType::BuiltRequirement;
using BuiltInverseRequirement = typename BuilderType::BuiltInverseRequirement;
using BuiltLayoutConstraint = typename BuilderType::BuiltLayoutConstraint;
using BuiltGenericSignature = typename BuilderType::BuiltGenericSignature;
using BuiltSubstitutionMap = typename BuilderType::BuiltSubstitutionMap;
Expand Down Expand Up @@ -800,16 +836,19 @@ class TypeDecoder {
return protocolType;

llvm::SmallVector<BuiltRequirement, 8> requirements;
llvm::SmallVector<BuiltInverseRequirement, 8> inverseRequirements;

auto *reqts = Node->getChild(1);
if (reqts->getKind() != NodeKind::ConstrainedExistentialRequirementList)
return MAKE_NODE_TYPE_ERROR0(reqts, "is not requirement list");

decodeRequirement<BuiltType, BuiltRequirement, BuiltLayoutConstraint,
BuilderType>(reqts, requirements, Builder);
decodeRequirement<BuiltType, BuiltRequirement, BuiltInverseRequirement,
BuiltLayoutConstraint, BuilderType>(
reqts, requirements, inverseRequirements, Builder);

return Builder.createConstrainedExistentialType(protocolType.getType(),
requirements);
requirements,
inverseRequirements);
}
case NodeKind::ConstrainedExistentialSelf:
return Builder.createGenericTypeParameterType(/*depth*/ 0, /*index*/ 0);
Expand Down Expand Up @@ -1280,6 +1319,7 @@ class TypeDecoder {
llvm::SmallVector<Field, 4> fields;
llvm::SmallVector<BuiltSubstitution, 4> substitutions;
llvm::SmallVector<BuiltRequirement, 4> requirements;
llvm::SmallVector<BuiltInverseRequirement, 8> inverseRequirements;
llvm::SmallVector<BuiltType, 4> genericParams;

if (Node->getNumChildren() < 1)
Expand Down Expand Up @@ -1332,10 +1372,10 @@ class TypeDecoder {
}

// Decode requirements.
decodeRequirement<BuiltType, BuiltRequirement, BuiltLayoutConstraint,
BuilderType>(dependentGenericSignatureNode,
requirements,
Builder);
decodeRequirement<BuiltType, BuiltRequirement, BuiltInverseRequirement,
BuiltLayoutConstraint, BuilderType>(
dependentGenericSignatureNode, requirements, inverseRequirements,
Builder);

// Decode substitutions.
for (unsigned i = 0, e = substNode->getNumChildren(); i < e; ++i) {
Expand Down Expand Up @@ -1373,7 +1413,8 @@ class TypeDecoder {
}

return Builder.createSILBoxTypeWithLayout(fields, substitutions,
requirements);
requirements,
inverseRequirements);
}
case NodeKind::SugaredOptional: {
if (Node->getNumChildren() < 1)
Expand Down
19 changes: 19 additions & 0 deletions include/swift/RemoteInspection/TypeRef.h
Original file line number Diff line number Diff line change
Expand Up @@ -192,6 +192,25 @@ class TypeRefRequirement {
}
};

class TypeRefInverseRequirement {
llvm::PointerIntPair<const TypeRef *, 3, InvertibleProtocolKind> Storage;

public:
TypeRefInverseRequirement(const TypeRef *first, InvertibleProtocolKind proto)
: Storage(first, proto) {
assert(first);
}

/// Retrieve the first type.
const TypeRef *getFirstType() const {
return Storage.getPointer();
}

/// Determine the kind of requirement.
InvertibleProtocolKind getKind() const { return Storage.getInt(); }
};


// On 32-bit systems this needs more than just pointer alignment to fit the
// extra bits needed by TypeRefRequirement.
class alignas(8) TypeRef {
Expand Down
14 changes: 12 additions & 2 deletions include/swift/RemoteInspection/TypeRefBuilder.h
Original file line number Diff line number Diff line change
Expand Up @@ -389,6 +389,7 @@ class TypeRefBuilder {
std::optional<std::pair<std::string, bool /*isObjC*/>>;
using BuiltSubstitution = std::pair<const TypeRef *, const TypeRef *>;
using BuiltRequirement = TypeRefRequirement;
using BuiltInverseRequirement = TypeRefInverseRequirement;
using BuiltLayoutConstraint = TypeRefLayoutConstraint;
using BuiltGenericTypeParam = const GenericTypeParameterTypeRef *;
using BuiltGenericSignature = const GenericSignatureRef *;
Expand Down Expand Up @@ -1221,7 +1222,9 @@ class TypeRefBuilder {
}

const ConstrainedExistentialTypeRef *createConstrainedExistentialType(
const TypeRef *base, llvm::ArrayRef<BuiltRequirement> constraints) {
const TypeRef *base, llvm::ArrayRef<BuiltRequirement> constraints,
llvm::ArrayRef<BuiltInverseRequirement> InverseRequirements) {
// FIXME: Handle inverse requirements.
auto *baseProto = llvm::dyn_cast<ProtocolCompositionTypeRef>(base);
if (!baseProto)
return nullptr;
Expand Down Expand Up @@ -1295,10 +1298,17 @@ class TypeRefBuilder {
return {};
}

BuiltInverseRequirement createInverseRequirement(
const TypeRef *subject, InvertibleProtocolKind proto) {
return TypeRefInverseRequirement(subject, proto);
}

const SILBoxTypeWithLayoutTypeRef *createSILBoxTypeWithLayout(
const llvm::SmallVectorImpl<BuiltSILBoxField> &Fields,
const llvm::SmallVectorImpl<BuiltSubstitution> &Substitutions,
const llvm::SmallVectorImpl<BuiltRequirement> &Requirements) {
const llvm::SmallVectorImpl<BuiltRequirement> &Requirements,
llvm::ArrayRef<BuiltInverseRequirement> InverseRequirements) {
// FIXME: Handle inverse requirements.
return SILBoxTypeWithLayoutTypeRef::create(*this, Fields, Substitutions,
Requirements);
}
Expand Down
Loading