Skip to content

[NCGenerics] fold InverseType into PCT #70278

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 1 commit into from
Dec 8, 2023
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
11 changes: 8 additions & 3 deletions include/swift/AST/DiagnosticsSema.def
Original file line number Diff line number Diff line change
Expand Up @@ -3158,11 +3158,11 @@ ERROR(requires_not_suitable_archetype,none,
(Type))

ERROR(requires_not_suitable_inverse_subject,none,
"cannot apply inverse %1 to type %0 in conformance requirement",
(Type, Type))
"cannot apply inverse '~%1' to type %0 in conformance requirement",
(Type, StringRef))

ERROR(requires_not_suitable_inverse_outer_subject,none,
"cannot add inverse constraint '%0: %1' "
"cannot add inverse constraint '%0: ~%1' "
"on generic parameter '%0' defined in outer scope",
(StringRef, StringRef))

Expand Down Expand Up @@ -7558,6 +7558,11 @@ ERROR(accessor_macro_not_single_var, none,
ERROR(noncopyable_but_copyable, none,
"%kind0 required to be 'Copyable' but is marked with '~Copyable'",
(const ValueDecl *))
ERROR(noncopyable_generic_but_copyable, none,
"%0 required to be '%1' but is marked with '~%1'",
(Type, StringRef))
WARNING(redundant_inverse_constraint,none,
"redundant constraint %0 : '~%1'", (Type, StringRef))
ERROR(noncopyable_class, none,
"classes cannot be noncopyable",
())
Expand Down
1 change: 0 additions & 1 deletion include/swift/AST/ExistentialLayout.h
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,6 @@ struct ExistentialLayout {
}

ExistentialLayout(CanProtocolType type);
ExistentialLayout(CanInverseType type);
ExistentialLayout(CanProtocolCompositionType type);
ExistentialLayout(CanParameterizedProtocolType type);

Expand Down
4 changes: 2 additions & 2 deletions include/swift/AST/LayoutConstraint.h
Original file line number Diff line number Diff line change
Expand Up @@ -171,10 +171,10 @@ class LayoutConstraintInfo
std::string getString(const PrintOptions &PO = PrintOptions()) const;

/// Return the name of this layout constraint.
StringRef getName(bool useClassLayoutName = false) const;
StringRef getName(bool internalName = false) const;

/// Return the name of a layout constraint with a given kind.
static StringRef getName(LayoutConstraintKind Kind, bool useClassLayoutName = false);
static StringRef getName(LayoutConstraintKind Kind, bool internalName = false);

static bool isKnownLayout(LayoutConstraintKind Kind);

Expand Down
5 changes: 2 additions & 3 deletions include/swift/AST/PrintOptions.h
Original file line number Diff line number Diff line change
Expand Up @@ -328,9 +328,8 @@ struct PrintOptions {
/// Whether to print generic requirements in a where clause.
bool PrintGenericRequirements = true;

/// Whether to print the real layout name instead of AnyObject
/// for class layout
bool PrintClassLayoutName = false;
/// Whether to print the internal layout name instead of AnyObject, etc.
bool PrintInternalLayoutName = false;

/// Suppress emitting @available(*, noasync)
bool SuppressNoAsyncAvailabilityAttr = false;
Expand Down
27 changes: 27 additions & 0 deletions include/swift/AST/Requirement.h
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,8 @@

namespace swift {

enum class InvertibleProtocolKind : uint8_t;

/// Return type of Requirement::checkRequirement().
enum class CheckRequirementResult : uint8_t {
/// The requirement was fully satisfied.
Expand Down Expand Up @@ -222,6 +224,31 @@ struct StructuralRequirement {
/// diagnosed as redundant, since we want to give users the option of
/// spelling out these requirements explicitly.
bool inferred = false;

/// A flag indicating whether this requirement was produced via the expansion
/// of default conformances to invertible protocols.
bool fromDefault = false;
};

struct InverseRequirement {
Type subject;
ProtocolDecl *protocol;
SourceLoc loc;

InverseRequirement(Type subject, ProtocolDecl *protocol, SourceLoc loc);

InvertibleProtocolKind getKind() const;

static void enumerateDefaultedParams(TypeDecl *decl,
SmallVectorImpl<Type> &result);

static void expandDefault(Type gp,
SourceLoc loc,
SmallVectorImpl<StructuralRequirement> &result);

static void expandDefaults(ASTContext &ctx,
ArrayRef<Type> gps,
SmallVectorImpl<StructuralRequirement> &result);
};

} // end namespace swift
Expand Down
8 changes: 0 additions & 8 deletions include/swift/AST/TypeMatcher.h
Original file line number Diff line number Diff line change
Expand Up @@ -495,14 +495,6 @@ class TypeMatcher {
sugaredFirstType);
}

bool visitInverseType(CanInverseType firstInverse,
Type secondType,
Type sugaredFirstType) {
// NOTE: If this visitor is reached, determine whether it should've been
// before implementing this.
llvm_unreachable("Yahaha! You found me!");
}

bool visitLValueType(CanLValueType firstLValue, Type secondType,
Type sugaredFirstType) {
if (auto secondLValue = secondType->getAs<LValueType>()) {
Expand Down
1 change: 0 additions & 1 deletion include/swift/AST/TypeNodes.def
Original file line number Diff line number Diff line change
Expand Up @@ -180,7 +180,6 @@ ARTIFICIAL_TYPE(SILMoveOnlyWrapped, Type)
ALWAYS_CANONICAL_ARTIFICIAL_TYPE(SILPack, Type)
ARTIFICIAL_TYPE(SILToken, Type)
TYPE(ProtocolComposition, Type)
UNCHECKED_TYPE(Inverse, Type)
TYPE(ParameterizedProtocol, Type)
TYPE(Existential, Type)
TYPE(LValue, Type)
Expand Down
49 changes: 4 additions & 45 deletions include/swift/AST/Types.h
Original file line number Diff line number Diff line change
Expand Up @@ -1532,48 +1532,6 @@ class NominalOrBoundGenericNominalType : public AnyGenericType {
};
DEFINE_EMPTY_CAN_TYPE_WRAPPER(NominalOrBoundGenericNominalType, AnyGenericType)

/// InverseType represents the "inverse" of a ProtocolType as a constraint.
/// An inverse represents the _absence_ of an implicit constraint to the given
/// protocol.
///
/// Otherwise, an inverse is not a real type! It's an annotation for other types
/// to signal whether an implicit requirement on that type should be omitted.
/// Because that annotation is expressed in the surface language as if it _were_
/// a type (that is, as a type constraint) we still model it as a Type through
/// typechecking.
class InverseType final : public TypeBase {
Type protocol;

InverseType(Type type,
const ASTContext *canonicalContext,
RecursiveTypeProperties properties)
: TypeBase(TypeKind::Inverse, canonicalContext, properties),
protocol(type) {
assert(protocol->is<ProtocolType>());
}

public:
/// Produce an inverse constraint type for the given protocol type.
static Type get(Type protocolType);


/// Obtain the underlying \c ProtocolType that was inverted.
Type getInvertedProtocol() const {
return protocol;
}

/// Get known kind of inverse this type represents.
InvertibleProtocolKind getInverseKind() const;

// Implement isa/cast/dyncast/etc.
static bool classof(const TypeBase *T) {
return T->getKind() == TypeKind::Inverse;
}
};
BEGIN_CAN_TYPE_WRAPPER(InverseType, Type)
PROXY_CAN_TYPE_SIMPLE_GETTER(getInvertedProtocol)
END_CAN_TYPE_WRAPPER(InverseType, Type)

/// ErrorType - Represents the type of an erroneously constructed declaration,
/// expression, or type. When creating ErrorTypes, an associated error
/// diagnostic should always be emitted. That way when later stages of
Expand Down Expand Up @@ -5811,6 +5769,9 @@ class ProtocolCompositionType final : public TypeBase,
/// Constructs a protocol composition corresponding to the `AnyObject` type.
static Type theAnyObjectType(const ASTContext &C);

/// Constructs a protocol composition corresponding to the `~IP` type.
static Type getInverseOf(const ASTContext &C, InvertibleProtocolKind IP);

/// Canonical protocol composition types are minimized only to a certain
/// degree to preserve ABI compatibility. This routine enables performing
/// slower, but stricter minimization at need (e.g. redeclaration checking).
Expand Down Expand Up @@ -7294,8 +7255,7 @@ inline bool TypeBase::isConstraintType() const {
inline bool CanType::isConstraintTypeImpl(CanType type) {
return (isa<ProtocolType>(type) ||
isa<ProtocolCompositionType>(type) ||
isa<ParameterizedProtocolType>(type) ||
isa<InverseType>(type));
isa<ParameterizedProtocolType>(type));
}

inline bool TypeBase::isExistentialType() {
Expand All @@ -7311,7 +7271,6 @@ inline bool CanType::isExistentialTypeImpl(CanType type) {
isa<ProtocolCompositionType>(type) ||
isa<ExistentialType>(type) ||
isa<ParameterizedProtocolType>(type);
// TODO(kavon): treat InverseType as an existential, etc?
}

inline bool CanType::isAnyExistentialTypeImpl(CanType type) {
Expand Down
23 changes: 0 additions & 23 deletions lib/AST/ASTContext.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -460,7 +460,6 @@ struct ASTContext::Implementation {
llvm::DenseMap<std::pair<ClassDecl*, Type>, ClassType*> ClassTypes;
llvm::DenseMap<std::pair<ProtocolDecl*, Type>, ProtocolType*> ProtocolTypes;
llvm::DenseMap<Type, ExistentialType *> ExistentialTypes;
llvm::DenseMap<Type, InverseType *> InverseTypes;
llvm::FoldingSet<UnboundGenericType> UnboundGenericTypes;
llvm::FoldingSet<BoundGenericType> BoundGenericTypes;
llvm::FoldingSet<ProtocolCompositionType> ProtocolCompositionTypes;
Expand Down Expand Up @@ -3842,28 +3841,6 @@ Type ExistentialMetatypeType::getExistentialInstanceType() {
return ExistentialType::get(getInstanceType());
}

InvertibleProtocolKind InverseType::getInverseKind() const {
return *getInvertibleProtocolKind(*protocol->getKnownProtocol());
}

Type InverseType::get(Type invertedProto) {
auto &C = invertedProto->getASTContext();

auto properties = invertedProto->getRecursiveProperties();
auto arena = getArena(properties);

auto &entry = C.getImpl().getArena(arena).InverseTypes[invertedProto];
if (entry)
return entry;

const ASTContext *canonicalContext =
invertedProto->isCanonical() ? &C : nullptr;

return entry = new (C, arena) InverseType(invertedProto,
canonicalContext,
properties);
}

ModuleType *ModuleType::get(ModuleDecl *M) {
ASTContext &C = M->getASTContext();

Expand Down
6 changes: 0 additions & 6 deletions lib/AST/ASTDumper.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4368,12 +4368,6 @@ namespace {
printFoot();
}

void visitInverseType(InverseType *T, StringRef label) {
printCommon("inverse_type", label);
printRec(T->getInvertedProtocol());
printFoot();
}

void visitLValueType(LValueType *T, StringRef label) {
printCommon("lvalue_type", label);
printRec(T->getObjectType());
Expand Down
3 changes: 0 additions & 3 deletions lib/AST/ASTMangler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1401,9 +1401,6 @@ void ASTMangler::appendType(Type type, GenericSignature sig,
case TypeKind::LValue:
llvm_unreachable("@lvalue types should not occur in function interfaces");

case TypeKind::Inverse:
llvm_unreachable("inverse types should not appear in interfaces");

case TypeKind::InOut:
appendType(cast<InOutType>(tybase)->getObjectType(), sig, forDecl);
return appendOperator("z");
Expand Down
9 changes: 2 additions & 7 deletions lib/AST/ASTPrinter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6310,11 +6310,6 @@ class TypePrinter : public TypeVisitor<TypePrinter> {
Printer << "_";
}

void visitInverseType(InverseType *T) {
Printer << "~";
visit(T->getInvertedProtocol());
}

void visitPlaceholderType(PlaceholderType *T) {
if (Options.PrintTypesForDebugging) {
Printer << "<<placeholder for ";
Expand Down Expand Up @@ -7663,15 +7658,15 @@ void LayoutConstraint::print(raw_ostream &OS,

void LayoutConstraintInfo::print(ASTPrinter &Printer,
const PrintOptions &PO) const {
Printer << getName(PO.PrintClassLayoutName);
Printer << getName(PO.PrintInternalLayoutName);
switch (getKind()) {
case LayoutConstraintKind::UnknownLayout:
case LayoutConstraintKind::RefCountedObject:
case LayoutConstraintKind::NativeRefCountedObject:
case LayoutConstraintKind::Class:
case LayoutConstraintKind::NativeClass:
case LayoutConstraintKind::Trivial:
return;
return; // non-parameterized cases
case LayoutConstraintKind::TrivialOfAtMostSize:
case LayoutConstraintKind::TrivialOfExactSize:
Printer << "(";
Expand Down
2 changes: 1 addition & 1 deletion lib/AST/Attr.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1261,7 +1261,7 @@ bool DeclAttribute::printImpl(ASTPrinter &Printer, const PrintOptions &Options,
Printer << "@_noMetadata ";
}
auto OptionsCopy = Options;
OptionsCopy.PrintClassLayoutName = typeErased;
OptionsCopy.PrintInternalLayoutName = typeErased;
req.print(Printer, OptionsCopy);
},
[&] { Printer << ", "; });
Expand Down
5 changes: 0 additions & 5 deletions lib/AST/ExistentialGeneralization.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -110,11 +110,6 @@ class Generalizer : public CanTypeVisitor<Generalizer, Type> {
origType->hasExplicitAnyObject());
}

Type visitInverseType(CanInverseType type) {
// TODO(kavon): determine how to handle inverses for ExistentialGeneralization
llvm_unreachable("unimplemented");
}

// Generalize the type arguments of nominal types.
Type visitBoundGenericType(CanBoundGenericType origType) {
return generalizeGenericArguments(origType->getDecl(), origType);
Expand Down
8 changes: 4 additions & 4 deletions lib/AST/LayoutConstraint.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -51,16 +51,16 @@ LayoutConstraint getLayoutConstraint(Identifier ID, ASTContext &Ctx) {
LayoutConstraintKind::UnknownLayout, Ctx);
}

StringRef LayoutConstraintInfo::getName(bool useClassLayoutName) const {
return getName(getKind(), useClassLayoutName);
StringRef LayoutConstraintInfo::getName(bool internalName) const {
return getName(getKind(), internalName);
}

StringRef LayoutConstraintInfo::getName(LayoutConstraintKind Kind, bool useClassLayoutName) {
StringRef LayoutConstraintInfo::getName(LayoutConstraintKind Kind, bool internalName) {
switch (Kind) {
case LayoutConstraintKind::UnknownLayout:
return "_UnknownLayout";
case LayoutConstraintKind::Class:
return useClassLayoutName ? "_Class" : "AnyObject";
return internalName ? "_Class" : "AnyObject";
case LayoutConstraintKind::NativeClass:
return "_NativeClass";
case LayoutConstraintKind::RefCountedObject:
Expand Down
Loading