mirror of
https://github.com/apple/swift.git
synced 2025-12-14 20:36:38 +01:00
[Archetype builder] Clean up PotentialArchetype a bit.
Clean up the representation of PotentialArchetype in a few small ways: * Eliminate the GenericTypeParamType* at the root, and instead just store a GenericParamKey. That makes the potential archetypes independent of a particular set of generic parameters. * Give potential archetypes a link back to their owning ArchetypeBuilder, so we can get contextual information (etc.) when needed. We can remove the "builder" arguments as a separate step. Also, collapse getName()/getDebugName()/getFullName() into getNestedName() and getDebugName(). Generic parameters don't have "names" per se, so they should only show up in debug dumps. In support of the former, clean up some of the diagnostics emitted by the archetype builder that were using 'Identifier' or 'StringRef' where they should have been using a 'Type' (i.e., the type behind the dependent archetype).
This commit is contained in:
@@ -19,6 +19,7 @@
|
||||
#ifndef SWIFT_ARCHETYPEBUILDER_H
|
||||
#define SWIFT_ARCHETYPEBUILDER_H
|
||||
|
||||
#include "swift/AST/Decl.h"
|
||||
#include "swift/AST/Identifier.h"
|
||||
#include "swift/AST/Types.h"
|
||||
#include "swift/AST/TypeLoc.h"
|
||||
@@ -33,20 +34,15 @@
|
||||
|
||||
namespace swift {
|
||||
|
||||
class AbstractTypeParamDecl;
|
||||
class ArchetypeType;
|
||||
class AssociatedTypeDecl;
|
||||
class DeclContext;
|
||||
class DependentMemberType;
|
||||
class GenericParamList;
|
||||
class GenericSignature;
|
||||
class GenericTypeParamDecl;
|
||||
class GenericTypeParamType;
|
||||
class LazyResolver;
|
||||
class ModuleDecl;
|
||||
class Pattern;
|
||||
class ProtocolConformance;
|
||||
class ProtocolDecl;
|
||||
class Requirement;
|
||||
class RequirementRepr;
|
||||
class SILModule;
|
||||
@@ -227,10 +223,6 @@ public:
|
||||
RequirementRHS constraint,
|
||||
RequirementSource source)> f);
|
||||
|
||||
private:
|
||||
PotentialArchetype *addGenericParameter(GenericTypeParamType *GenericParam,
|
||||
Identifier ParamName);
|
||||
|
||||
public:
|
||||
/// \brief Add a new generic parameter for which there may be requirements.
|
||||
void addGenericParameter(GenericTypeParamDecl *GenericParam);
|
||||
@@ -333,19 +325,37 @@ public:
|
||||
};
|
||||
|
||||
class ArchetypeBuilder::PotentialArchetype {
|
||||
/// Either the parent of this potential archetype (for an associated
|
||||
/// type) or the generic type parameter type to which this potential
|
||||
/// archetype corresponds.
|
||||
llvm::PointerUnion<PotentialArchetype*, GenericTypeParamType*> ParentOrParam;
|
||||
/// The parent of this potential archetype (for a nested type) or the
|
||||
/// archetype builder in which this root resides.
|
||||
llvm::PointerUnion<PotentialArchetype*, ArchetypeBuilder*> parentOrBuilder;
|
||||
|
||||
/// \brief The name of this potential archetype or, for an
|
||||
/// associated type, the declaration of the associated type to which
|
||||
/// this potential archetype has been resolved. Or, for a type alias,
|
||||
/// the type alias decl.
|
||||
llvm::PointerUnion3<Identifier, AssociatedTypeDecl *,
|
||||
TypeAliasDecl *> NameOrAssociatedType;
|
||||
/// The identifier describing this particular archetype.
|
||||
///
|
||||
/// \c parentOrBuilder determines whether we have a nested type vs. a root,
|
||||
/// while `isUnresolvedNestedType` determines whether we have an unresolved
|
||||
/// nested type (vs. a resolved one);
|
||||
union PAIdentifier {
|
||||
/// The name of an unresolved, nested type.
|
||||
Identifier name;
|
||||
|
||||
/// \brief The representative of the equivalent class of potential archetypes
|
||||
/// The associated type or typealias for a resolved nested type.
|
||||
TypeDecl *assocTypeOrAlias;
|
||||
|
||||
/// The generic parameter key for a root.
|
||||
GenericParamKey genericParam;
|
||||
|
||||
PAIdentifier(Identifier name) : name(name) { }
|
||||
|
||||
PAIdentifier(AssociatedTypeDecl *assocType)
|
||||
: assocTypeOrAlias(assocType) { }
|
||||
|
||||
PAIdentifier(TypeAliasDecl *typeAlias)
|
||||
: assocTypeOrAlias(typeAlias) { }
|
||||
|
||||
PAIdentifier(GenericParamKey genericParam) : genericParam(genericParam) { }
|
||||
} identifier;
|
||||
|
||||
/// \brief The representative of the equivalence class of potential archetypes
|
||||
/// to which this potential archetype belongs.
|
||||
PotentialArchetype *Representative;
|
||||
|
||||
@@ -383,6 +393,9 @@ class ArchetypeBuilder::PotentialArchetype {
|
||||
/// The source of the concrete type requirement.
|
||||
Optional<RequirementSource> ConcreteTypeSource;
|
||||
|
||||
/// Whether this is an unresolved nested type.
|
||||
unsigned isUnresolvedNestedType : 1;
|
||||
|
||||
/// \brief Recursively conforms to itself.
|
||||
unsigned IsRecursive : 1;
|
||||
|
||||
@@ -410,108 +423,97 @@ class ArchetypeBuilder::PotentialArchetype {
|
||||
|
||||
/// \brief Construct a new potential archetype for an unresolved
|
||||
/// associated type.
|
||||
PotentialArchetype(PotentialArchetype *Parent, Identifier Name)
|
||||
: ParentOrParam(Parent), NameOrAssociatedType(Name), Representative(this),
|
||||
PotentialArchetype(PotentialArchetype *parent, Identifier name)
|
||||
: parentOrBuilder(parent), identifier(name), Representative(this),
|
||||
isUnresolvedNestedType(true),
|
||||
IsRecursive(false), Invalid(false),
|
||||
RecursiveConcreteType(false), RecursiveSuperclassType(false),
|
||||
DiagnosedRename(false)
|
||||
{
|
||||
assert(Parent != nullptr && "Not an associated type?");
|
||||
assert(parent != nullptr && "Not an associated type?");
|
||||
EquivalenceClass.push_back(this);
|
||||
}
|
||||
|
||||
/// \brief Construct a new potential archetype for an associated type.
|
||||
PotentialArchetype(PotentialArchetype *Parent, AssociatedTypeDecl *AssocType)
|
||||
: ParentOrParam(Parent), NameOrAssociatedType(AssocType),
|
||||
Representative(this), IsRecursive(false), Invalid(false),
|
||||
PotentialArchetype(PotentialArchetype *parent, AssociatedTypeDecl *assocType)
|
||||
: parentOrBuilder(parent), identifier(assocType),
|
||||
Representative(this), isUnresolvedNestedType(false),
|
||||
IsRecursive(false), Invalid
|
||||
(false),
|
||||
RecursiveConcreteType(false),
|
||||
RecursiveSuperclassType(false), DiagnosedRename(false)
|
||||
{
|
||||
assert(Parent != nullptr && "Not an associated type?");
|
||||
assert(parent != nullptr && "Not an associated type?");
|
||||
EquivalenceClass.push_back(this);
|
||||
}
|
||||
|
||||
/// \brief Construct a new potential archetype for a type alias.
|
||||
PotentialArchetype(PotentialArchetype *Parent, TypeAliasDecl *TypeAlias)
|
||||
: ParentOrParam(Parent), NameOrAssociatedType(TypeAlias),
|
||||
Representative(this), IsRecursive(false), Invalid(false),
|
||||
PotentialArchetype(PotentialArchetype *parent, TypeAliasDecl *typeAlias)
|
||||
: parentOrBuilder(parent), identifier(typeAlias),
|
||||
Representative(this), isUnresolvedNestedType(false),
|
||||
IsRecursive(false), Invalid(false),
|
||||
RecursiveConcreteType(false),
|
||||
RecursiveSuperclassType(false), DiagnosedRename(false)
|
||||
{
|
||||
assert(Parent != nullptr && "Not an associated type?");
|
||||
assert(parent != nullptr && "Not an associated type?");
|
||||
EquivalenceClass.push_back(this);
|
||||
}
|
||||
|
||||
/// \brief Construct a new potential archetype for a generic parameter.
|
||||
PotentialArchetype(GenericTypeParamType *GenericParam,
|
||||
Identifier Name)
|
||||
: ParentOrParam(GenericParam),
|
||||
NameOrAssociatedType(Name), Representative(this), IsRecursive(false),
|
||||
Invalid(false),
|
||||
PotentialArchetype(ArchetypeBuilder *builder, GenericParamKey genericParam)
|
||||
: parentOrBuilder(builder), identifier(genericParam),
|
||||
Representative(this), isUnresolvedNestedType(false),
|
||||
IsRecursive(false), Invalid(false),
|
||||
RecursiveConcreteType(false), RecursiveSuperclassType(false),
|
||||
DiagnosedRename(false)
|
||||
{
|
||||
EquivalenceClass.push_back(this);
|
||||
}
|
||||
|
||||
/// \brief Recursively build the full name.
|
||||
void buildFullName(bool forDebug, SmallVectorImpl<char> &result) const;
|
||||
|
||||
/// Retrieve the generic parameter at the root of this potential archetype.
|
||||
GenericTypeParamType *getRootParam() const {
|
||||
if (auto parent = getParent())
|
||||
return parent->getRootParam();
|
||||
|
||||
return getGenericParam();
|
||||
}
|
||||
|
||||
/// \brief Retrieve the representative for this archetype, performing
|
||||
/// path compression on the way.
|
||||
PotentialArchetype *getRepresentative();
|
||||
|
||||
/// Retrieve the archetype builder with which this archetype is associated.
|
||||
ArchetypeBuilder *getBuilder() const {
|
||||
const PotentialArchetype *pa = this;
|
||||
while (auto parent = pa->getParent())
|
||||
pa = parent;
|
||||
return pa->parentOrBuilder.get<ArchetypeBuilder *>();
|
||||
}
|
||||
|
||||
friend class ArchetypeBuilder;
|
||||
friend class GenericSignature;
|
||||
|
||||
public:
|
||||
~PotentialArchetype();
|
||||
|
||||
/// \brief Retrieve the name of this potential archetype.
|
||||
Identifier getName() const;
|
||||
|
||||
/// \brief Retrieve the full display name of this potential archetype.
|
||||
std::string getFullName() const;
|
||||
|
||||
/// \brief Retrieve the debug name of this potential archetype.
|
||||
std::string getDebugName() const;
|
||||
|
||||
public:
|
||||
~PotentialArchetype();
|
||||
|
||||
/// Retrieve the parent of this potential archetype, which will be non-null
|
||||
/// when this potential archetype is an associated type.
|
||||
PotentialArchetype *getParent() const {
|
||||
return ParentOrParam.dyn_cast<PotentialArchetype *>();
|
||||
return parentOrBuilder.dyn_cast<PotentialArchetype *>();
|
||||
}
|
||||
|
||||
/// Retrieve the associated type to which this potential archetype
|
||||
/// has been resolved.
|
||||
AssociatedTypeDecl *getResolvedAssociatedType() const {
|
||||
assert(getParent() && "Not an associated type");
|
||||
return NameOrAssociatedType.dyn_cast<AssociatedTypeDecl *>();
|
||||
if (isUnresolvedNestedType)
|
||||
return nullptr;
|
||||
|
||||
return dyn_cast<AssociatedTypeDecl>(identifier.assocTypeOrAlias);
|
||||
}
|
||||
|
||||
/// Resolve the potential archetype to the given associated type.
|
||||
void resolveAssociatedType(AssociatedTypeDecl *assocType,
|
||||
ArchetypeBuilder &builder);
|
||||
|
||||
/// Retrieve the generic type parameter for this potential
|
||||
/// archetype, if it corresponds to a generic parameter.
|
||||
///
|
||||
/// FIXME: We should weaken this to just a depth/index key.
|
||||
GenericTypeParamType *getGenericParam() const {
|
||||
return ParentOrParam.dyn_cast<GenericTypeParamType *>();
|
||||
}
|
||||
|
||||
/// Determine whether this is a generic parameter.
|
||||
bool isGenericParam() const {
|
||||
return ParentOrParam.is<GenericTypeParamType *>();
|
||||
return parentOrBuilder.is<ArchetypeBuilder *>();
|
||||
}
|
||||
|
||||
/// Retrieve the generic parameter key for a potential archetype that
|
||||
@@ -519,18 +521,35 @@ public:
|
||||
///
|
||||
/// \pre \c isGenericParam()
|
||||
GenericParamKey getGenericParamKey() const {
|
||||
return getGenericParam();
|
||||
assert(isGenericParam() && "Not a generic parameter");
|
||||
return identifier.genericParam;
|
||||
}
|
||||
|
||||
/// Retrieve the generic parameter key for the generic parameter at the
|
||||
/// root of this potential archetype.
|
||||
GenericParamKey getRootGenericParamKey() const {
|
||||
return getRootParam();
|
||||
if (auto parent = getParent())
|
||||
return parent->getRootGenericParamKey();
|
||||
|
||||
return getGenericParamKey();
|
||||
}
|
||||
|
||||
/// Retrieve the name of a nested potential archetype.
|
||||
Identifier getNestedName() const {
|
||||
assert(getParent() && "Not a nested type");
|
||||
if (isUnresolvedNestedType)
|
||||
return identifier.name;
|
||||
|
||||
return identifier.assocTypeOrAlias->getName();
|
||||
}
|
||||
|
||||
/// Retrieve the type alias.
|
||||
TypeAliasDecl *getTypeAliasDecl() const {
|
||||
return NameOrAssociatedType.dyn_cast<TypeAliasDecl *>();
|
||||
assert(getParent() && "not a nested type");
|
||||
if (isUnresolvedNestedType)
|
||||
return nullptr;
|
||||
|
||||
return dyn_cast<TypeAliasDecl>(identifier.assocTypeOrAlias);
|
||||
}
|
||||
|
||||
/// Retrieve the set of protocols to which this type conforms.
|
||||
@@ -656,7 +675,7 @@ public:
|
||||
/// Note that this potential archetype was is going to be renamed (due to typo
|
||||
/// correction), saving the old name.
|
||||
void saveNameForRenaming() {
|
||||
OrigName = getName();
|
||||
OrigName = getNestedName();
|
||||
}
|
||||
|
||||
/// For a renamed potential archetype, retrieve the original name.
|
||||
|
||||
@@ -1561,13 +1561,13 @@ ERROR(requires_no_same_type_archetype,none,
|
||||
())
|
||||
ERROR(requires_generic_params_made_equal,none,
|
||||
"same-type requirement makes generic parameters %0 and %1 equivalent",
|
||||
(Identifier, Identifier))
|
||||
(Type, Type))
|
||||
ERROR(requires_generic_param_made_equal_to_concrete,none,
|
||||
"same-type requirement makes generic parameter %0 non-generic",
|
||||
(Identifier))
|
||||
(Type))
|
||||
ERROR(requires_superclass_conflict,none,
|
||||
"generic parameter %0 cannot be a subclass of both %1 and %2",
|
||||
(Identifier, Type, Type))
|
||||
(Type, Type, Type))
|
||||
ERROR(recursive_type_reference,none,
|
||||
"%0 %1 references itself", (DescriptiveDeclKind, Identifier))
|
||||
ERROR(recursive_requirement_reference,none,
|
||||
@@ -1578,7 +1578,7 @@ ERROR(recursive_superclass_constraint,none,
|
||||
"superclass constraint %0 : %1 is recursive", (Type, Type))
|
||||
ERROR(requires_same_type_conflict,none,
|
||||
"generic parameter %0 cannot be equal to both %1 and %2",
|
||||
(StringRef, Type, Type))
|
||||
(Type, Type, Type))
|
||||
ERROR(requires_generic_param_same_type_does_not_conform,none,
|
||||
"same-type constraint type %0 does not conform to required protocol %1",
|
||||
(Type, Identifier))
|
||||
|
||||
@@ -121,15 +121,22 @@ ArchetypeBuilder::PotentialArchetype::~PotentialArchetype() {
|
||||
}
|
||||
}
|
||||
|
||||
void ArchetypeBuilder::PotentialArchetype::buildFullName(
|
||||
bool forDebug,
|
||||
SmallVectorImpl<char> &result) const {
|
||||
if (auto parent = getParent()) {
|
||||
parent->buildFullName(forDebug, result);
|
||||
std::string ArchetypeBuilder::PotentialArchetype::getDebugName() const {
|
||||
llvm::SmallString<64> result;
|
||||
|
||||
auto parent = getParent();
|
||||
if (!parent) {
|
||||
return GenericTypeParamType::get(getGenericParamKey().Depth,
|
||||
getGenericParamKey().Index,
|
||||
getBuilder()->getASTContext())->getName()
|
||||
.str();
|
||||
}
|
||||
|
||||
// Nested types.
|
||||
result += parent->getDebugName();
|
||||
|
||||
// When building the name for debugging purposes, include the
|
||||
// protocol into which the associated type was resolved.
|
||||
if (forDebug) {
|
||||
if (auto assocType = getResolvedAssociatedType()) {
|
||||
result.push_back('[');
|
||||
result.push_back('.');
|
||||
@@ -137,30 +144,10 @@ void ArchetypeBuilder::PotentialArchetype::buildFullName(
|
||||
assocType->getProtocol()->getName().str().end());
|
||||
result.push_back(']');
|
||||
}
|
||||
}
|
||||
|
||||
result.push_back('.');
|
||||
}
|
||||
result.append(getName().str().begin(), getName().str().end());
|
||||
}
|
||||
result.append(getNestedName().str().begin(), getNestedName().str().end());
|
||||
|
||||
Identifier ArchetypeBuilder::PotentialArchetype::getName() const {
|
||||
if (auto assocType = NameOrAssociatedType.dyn_cast<AssociatedTypeDecl *>())
|
||||
return assocType->getName();
|
||||
if (auto typeAlias = NameOrAssociatedType.dyn_cast<TypeAliasDecl *>())
|
||||
return typeAlias->getName();
|
||||
return NameOrAssociatedType.get<Identifier>();
|
||||
}
|
||||
|
||||
std::string ArchetypeBuilder::PotentialArchetype::getFullName() const {
|
||||
llvm::SmallString<64> result;
|
||||
buildFullName(false, result);
|
||||
return result.str().str();
|
||||
}
|
||||
|
||||
std::string ArchetypeBuilder::PotentialArchetype::getDebugName() const {
|
||||
llvm::SmallString<64> result;
|
||||
buildFullName(true, result);
|
||||
return result.str().str();
|
||||
}
|
||||
|
||||
@@ -174,10 +161,10 @@ unsigned ArchetypeBuilder::PotentialArchetype::getNestingDepth() const {
|
||||
void ArchetypeBuilder::PotentialArchetype::resolveAssociatedType(
|
||||
AssociatedTypeDecl *assocType,
|
||||
ArchetypeBuilder &builder) {
|
||||
assert(!NameOrAssociatedType.is<AssociatedTypeDecl *>() &&
|
||||
"associated type is already resolved");
|
||||
NameOrAssociatedType = assocType;
|
||||
assert(assocType->getName() == getName());
|
||||
assert(!getResolvedAssociatedType() && "associated type is already resolved");
|
||||
isUnresolvedNestedType = false;
|
||||
identifier.assocTypeOrAlias = assocType;
|
||||
assert(assocType->getName() == getNestedName());
|
||||
assert(builder.Impl->NumUnresolvedNestedTypes > 0 &&
|
||||
"Mismatch in number of unresolved nested types");
|
||||
--builder.Impl->NumUnresolvedNestedTypes;
|
||||
@@ -382,7 +369,8 @@ static int compareDependentTypes(
|
||||
return compareBases;
|
||||
|
||||
// - by name, so t_n_m.`P.T` < t_n_m.`P.U`
|
||||
if (int compareNames = a->getName().str().compare(b->getName().str()))
|
||||
if (int compareNames = a->getNestedName().str().compare(
|
||||
b->getNestedName().str()))
|
||||
return compareNames;
|
||||
|
||||
if (auto *aa = a->getResolvedAssociatedType()) {
|
||||
@@ -483,7 +471,7 @@ static ArchetypeBuilder::PotentialArchetype*rebuildPotentialArchetypeAnchor(
|
||||
if (auto assocType = pa->getResolvedAssociatedType())
|
||||
return parentAnchor->getNestedType(assocType, builder);
|
||||
|
||||
return parentAnchor->getNestedType(pa->getName(), builder);
|
||||
return parentAnchor->getNestedType(pa->getNestedName(), builder);
|
||||
}
|
||||
|
||||
return pa;
|
||||
@@ -728,7 +716,7 @@ Type ArchetypeBuilder::PotentialArchetype::getTypeInContext(
|
||||
|
||||
// Check whether the parent already has a nested type with this name. If
|
||||
// so, return it directly.
|
||||
if (auto nested = ParentArchetype->getNestedTypeIfKnown(getName()))
|
||||
if (auto nested = ParentArchetype->getNestedTypeIfKnown(getNestedName()))
|
||||
return *nested;
|
||||
|
||||
// We will build the archetype below.
|
||||
@@ -797,7 +785,7 @@ Type ArchetypeBuilder::PotentialArchetype::getTypeInContext(
|
||||
superclass, layout);
|
||||
|
||||
// Register this archetype with its parent.
|
||||
ParentArchetype->registerNestedType(getName(), arch);
|
||||
ParentArchetype->registerNestedType(getNestedName(), arch);
|
||||
} else {
|
||||
// Create a top-level archetype.
|
||||
Identifier name =
|
||||
@@ -846,27 +834,29 @@ Type ArchetypeBuilder::PotentialArchetype::getDependentType(
|
||||
return ErrorType::get(getDependentType(genericParams,
|
||||
/*allowUnresolved=*/true));
|
||||
|
||||
return DependentMemberType::get(parentType, getName());
|
||||
return DependentMemberType::get(parentType, getNestedName());
|
||||
}
|
||||
|
||||
assert(isGenericParam() && "Not a generic parameter?");
|
||||
|
||||
unsigned index = getGenericParamKey().findIndexIn(genericParams);
|
||||
|
||||
// FIXME: This is a temporary workaround.
|
||||
if (genericParams.empty()) {
|
||||
return getGenericParam();
|
||||
return getBuilder()->Impl->GenericParams[index];
|
||||
}
|
||||
|
||||
return genericParams[getGenericParamKey().findIndexIn(genericParams)];
|
||||
return genericParams[index];
|
||||
}
|
||||
|
||||
void ArchetypeBuilder::PotentialArchetype::dump(llvm::raw_ostream &Out,
|
||||
SourceManager *SrcMgr,
|
||||
unsigned Indent) {
|
||||
// Print name.
|
||||
if (Indent == 0)
|
||||
if (Indent == 0 || isGenericParam())
|
||||
Out << getDebugName();
|
||||
else
|
||||
Out.indent(Indent) << getName();
|
||||
Out.indent(Indent) << getNestedName();
|
||||
|
||||
// Print superclass.
|
||||
if (Superclass) {
|
||||
@@ -895,7 +885,7 @@ void ArchetypeBuilder::PotentialArchetype::dump(llvm::raw_ostream &Out,
|
||||
}
|
||||
|
||||
if (Representative != this) {
|
||||
Out << " [represented by " << getRepresentative()->getFullName() << "]";
|
||||
Out << " [represented by " << getRepresentative()->getDebugName() << "]";
|
||||
}
|
||||
|
||||
if (EquivalenceClass.size() > 1) {
|
||||
@@ -972,28 +962,9 @@ auto ArchetypeBuilder::resolveArchetype(Type type) -> PotentialArchetype * {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
auto ArchetypeBuilder::addGenericParameter(GenericTypeParamType *GenericParam,
|
||||
Identifier ParamName)
|
||||
-> PotentialArchetype *
|
||||
{
|
||||
GenericParamKey Key(GenericParam);
|
||||
assert(Impl->GenericParams.empty() ||
|
||||
((Key.Depth == Impl->GenericParams.back()->getDepth() &&
|
||||
Key.Index == Impl->GenericParams.back()->getIndex() + 1) ||
|
||||
(Key.Depth > Impl->GenericParams.back()->getDepth() &&
|
||||
Key.Index == 0)));
|
||||
|
||||
// Create a potential archetype for this type parameter.
|
||||
auto PA = new PotentialArchetype(GenericParam, ParamName);
|
||||
Impl->GenericParams.push_back(GenericParam);
|
||||
Impl->PotentialArchetypes.push_back(PA);
|
||||
return PA;
|
||||
}
|
||||
|
||||
void ArchetypeBuilder::addGenericParameter(GenericTypeParamDecl *GenericParam) {
|
||||
addGenericParameter(
|
||||
GenericParam->getDeclaredInterfaceType()->castTo<GenericTypeParamType>(),
|
||||
GenericParam->getName());
|
||||
GenericParam->getDeclaredInterfaceType()->castTo<GenericTypeParamType>());
|
||||
}
|
||||
|
||||
bool ArchetypeBuilder::addGenericParameterRequirements(GenericTypeParamDecl *GenericParam) {
|
||||
@@ -1008,13 +979,17 @@ bool ArchetypeBuilder::addGenericParameterRequirements(GenericTypeParamDecl *Gen
|
||||
}
|
||||
|
||||
void ArchetypeBuilder::addGenericParameter(GenericTypeParamType *GenericParam) {
|
||||
auto name = GenericParam->getName();
|
||||
// Trim '$' so that archetypes are more readily discernible from abstract
|
||||
// parameters.
|
||||
if (name.str().startswith("$"))
|
||||
name = Context.getIdentifier(name.str().slice(1, name.str().size()));
|
||||
GenericParamKey Key(GenericParam);
|
||||
assert(Impl->GenericParams.empty() ||
|
||||
((Key.Depth == Impl->GenericParams.back()->getDepth() &&
|
||||
Key.Index == Impl->GenericParams.back()->getIndex() + 1) ||
|
||||
(Key.Depth > Impl->GenericParams.back()->getDepth() &&
|
||||
Key.Index == 0)));
|
||||
|
||||
addGenericParameter(GenericParam, name);
|
||||
// Create a potential archetype for this type parameter.
|
||||
auto PA = new PotentialArchetype(this, GenericParam);
|
||||
Impl->GenericParams.push_back(GenericParam);
|
||||
Impl->PotentialArchetypes.push_back(PA);
|
||||
}
|
||||
|
||||
bool ArchetypeBuilder::addConformanceRequirement(PotentialArchetype *PAT,
|
||||
@@ -1193,7 +1168,8 @@ bool ArchetypeBuilder::addSuperclassRequirement(PotentialArchetype *T,
|
||||
// constraint.
|
||||
} else if (!Superclass->isExactSuperclassOf(T->Superclass, nullptr)) {
|
||||
Diags.diagnose(Source.getLoc(),
|
||||
diag::requires_superclass_conflict, T->getName(),
|
||||
diag::requires_superclass_conflict,
|
||||
T->getDependentType(/*FIXME: */{ }, true),
|
||||
T->Superclass, Superclass)
|
||||
.highlight(T->SuperclassSource->getLoc());
|
||||
return true;
|
||||
@@ -1257,9 +1233,9 @@ bool ArchetypeBuilder::addSameTypeRequirementBetweenArchetypes(
|
||||
|
||||
if (concrete1 && concrete2) {
|
||||
if (!concrete1->isEqual(concrete2)) {
|
||||
StringRef Name = T1->getFullName();
|
||||
Diags.diagnose(Source.getLoc(), diag::requires_same_type_conflict,
|
||||
Name, concrete1, concrete2);
|
||||
T1->getDependentType(/*FIXME: */{ }, true), concrete1,
|
||||
concrete2);
|
||||
return true;
|
||||
|
||||
}
|
||||
@@ -1331,9 +1307,9 @@ bool ArchetypeBuilder::addSameTypeRequirementToConcrete(
|
||||
// problem.
|
||||
if (auto oldConcrete = T->getConcreteType()) {
|
||||
if (!oldConcrete->isEqual(Concrete)) {
|
||||
StringRef Name = T->getFullName();
|
||||
Diags.diagnose(Source.getLoc(), diag::requires_same_type_conflict,
|
||||
Name, oldConcrete, Concrete);
|
||||
T->getDependentType(/*FIXME: */{ }, true), oldConcrete,
|
||||
Concrete);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
@@ -1831,7 +1807,7 @@ void ArchetypeBuilder::inferRequirements(ParameterList *params,
|
||||
/// corrected name (if successful).
|
||||
static Identifier typoCorrectNestedType(
|
||||
ArchetypeBuilder::PotentialArchetype *pa) {
|
||||
StringRef name = pa->getName().str();
|
||||
StringRef name = pa->getNestedName().str();
|
||||
|
||||
// Look through all of the associated types of all of the protocols
|
||||
// to which the parent conforms.
|
||||
@@ -2042,7 +2018,8 @@ ArchetypeBuilder::finalize(SourceLoc loc,
|
||||
|
||||
Diags.diagnose(Source->getLoc(),
|
||||
diag::requires_generic_param_made_equal_to_concrete,
|
||||
rep->getName());
|
||||
rep->getDependentType(genericParams,
|
||||
/*allowUnresolved=*/true));
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -2071,7 +2048,8 @@ ArchetypeBuilder::finalize(SourceLoc loc,
|
||||
|
||||
Diags.diagnose(constraintLoc,
|
||||
diag::requires_generic_params_made_equal,
|
||||
pa->getName(), other->getName());
|
||||
pa->getDependentType(genericParams, true),
|
||||
other->getDependentType(genericParams, true));
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -2119,7 +2097,7 @@ bool ArchetypeBuilder::diagnoseRemainingRenames(
|
||||
Diags.diagnose(loc, diag::invalid_member_type_suggest,
|
||||
pa->getParent()->getDependentType(genericParams,
|
||||
/*allowUnresolved=*/true),
|
||||
pa->getOriginalName(), pa->getName());
|
||||
pa->getOriginalName(), pa->getNestedName());
|
||||
invalid = true;
|
||||
}
|
||||
|
||||
|
||||
@@ -157,7 +157,7 @@ Type CompleteGenericTypeResolver::resolveDependentMemberType(
|
||||
// If this potential archetype was renamed due to typo correction,
|
||||
// complain and fix it.
|
||||
if (nestedPA->wasRenamed()) {
|
||||
auto newName = nestedPA->getName();
|
||||
auto newName = nestedPA->getNestedName();
|
||||
TC.diagnose(ref->getIdLoc(), diag::invalid_member_type_suggest,
|
||||
baseTy, ref->getIdentifier(), newName)
|
||||
.fixItReplace(ref->getIdLoc(), newName.str());
|
||||
|
||||
@@ -56,14 +56,14 @@ func test3<T: Fooable, U: Fooable>(_ t: T, u: U) -> (X, X)
|
||||
func fail1<
|
||||
T: Fooable, U: Fooable
|
||||
>(_ t: T, u: U) -> (X, Y)
|
||||
where T.Foo == X, U.Foo == Y, T.Foo == U.Foo { // expected-error{{generic parameter T.Foo cannot be equal to both 'X' and 'Y'}}
|
||||
where T.Foo == X, U.Foo == Y, T.Foo == U.Foo { // expected-error{{generic parameter 'T.Foo' cannot be equal to both 'X' and 'Y'}}
|
||||
return (t.foo, u.foo)
|
||||
}
|
||||
|
||||
func fail2<
|
||||
T: Fooable, U: Fooable
|
||||
>(_ t: T, u: U) -> (X, Y)
|
||||
where T.Foo == U.Foo, T.Foo == X, U.Foo == Y { // expected-error{{generic parameter T.Foo cannot be equal to both 'X' and 'Y'}}
|
||||
where T.Foo == U.Foo, T.Foo == X, U.Foo == Y { // expected-error{{generic parameter 'T.Foo' cannot be equal to both 'X' and 'Y'}}
|
||||
return (t.foo, u.foo) // expected-error{{cannot convert return expression of type 'X' to return type 'Y'}}
|
||||
}
|
||||
|
||||
@@ -91,7 +91,7 @@ func test7<T: Barrable>(_ t: T) -> (Y, X) where T.Bar == Y, T.Bar.Foo == X {
|
||||
func fail4<T: Barrable>(_ t: T) -> (Y, Z)
|
||||
where
|
||||
T.Bar == Y,
|
||||
T.Bar.Foo == Z { // expected-error{{generic parameter T.Bar.Foo cannot be equal to both 'Y.Foo' (aka 'X') and 'Z'}}
|
||||
T.Bar.Foo == Z { // expected-error{{generic parameter 'T.Bar.Foo' cannot be equal to both 'Y.Foo' (aka 'X') and 'Z'}}
|
||||
return (t.bar, t.bar.foo) // expected-error{{cannot convert return expression of type 'X' to return type 'Z'}}
|
||||
}
|
||||
|
||||
@@ -99,11 +99,11 @@ func fail4<T: Barrable>(_ t: T) -> (Y, Z)
|
||||
func fail5<T: Barrable>(_ t: T) -> (Y, Z)
|
||||
where
|
||||
T.Bar.Foo == Z,
|
||||
T.Bar == Y { // expected-error 2{{generic parameter T.Bar.Foo cannot be equal to both 'Z' and 'Y.Foo' (aka 'X')}}
|
||||
T.Bar == Y { // expected-error 2{{generic parameter 'T.Bar.Foo' cannot be equal to both 'Z' and 'Y.Foo' (aka 'X')}}
|
||||
return (t.bar, t.bar.foo) // expected-error{{cannot convert return expression of type 'X' to return type 'Z'}}
|
||||
}
|
||||
|
||||
func test8<T: Fooable>(_ t: T) where T.Foo == X, T.Foo == Y {} // expected-error{{generic parameter T.Foo cannot be equal to both 'X' and 'Y'}}
|
||||
func test8<T: Fooable>(_ t: T) where T.Foo == X, T.Foo == Y {} // expected-error{{generic parameter 'T.Foo' cannot be equal to both 'X' and 'Y'}}
|
||||
|
||||
func testAssocTypeEquivalence<T: Fooable>(_ fooable: T) -> X.Type
|
||||
where T.Foo == X {
|
||||
|
||||
@@ -37,9 +37,9 @@ func typoAssoc4<T : P2>(_: T) where T.Assocp2.assoc : P3 {}
|
||||
|
||||
// CHECK-GENERIC-LABEL: .typoAssoc4@
|
||||
// CHECK-GENERIC-NEXT: Requirements:
|
||||
// CHECK-GENERIC-NEXT: T : P2 [inferred]
|
||||
// CHECK-GENERIC-NEXT: T[.P2].AssocP2 : P1 [protocol
|
||||
// CHECK-GENERIC-NEXT: T[.P2].AssocP2[.P1].Assoc : P3 [explicit
|
||||
// CHECK-GENERIC-NEXT: τ_0_0 : P2 [inferred]
|
||||
// CHECK-GENERIC-NEXT: τ_0_0[.P2].AssocP2 : P1 [protocol
|
||||
// CHECK-GENERIC-NEXT: τ_0_0[.P2].AssocP2[.P1].Assoc : P3 [explicit
|
||||
// CHECK-GENERIC-NEXT: Potential archetypes
|
||||
|
||||
// <rdar://problem/19620340>
|
||||
|
||||
@@ -57,7 +57,7 @@ class Fox : P1 {
|
||||
class Box<T : Fox> {
|
||||
// CHECK-LABEL: .unpack@
|
||||
// CHECK-NEXT: Requirements:
|
||||
// CHECK-NEXT: T : Fox [explicit]
|
||||
// CHECK-NEXT: τ_0_0 : Fox [explicit]
|
||||
func unpack(_ x: X1<T>) {}
|
||||
}
|
||||
|
||||
@@ -75,12 +75,12 @@ struct V<T : Canidae> {}
|
||||
|
||||
// CHECK-LABEL: .inferSuperclassRequirement1@
|
||||
// CHECK-NEXT: Requirements:
|
||||
// CHECK-NEXT: T : Canidae
|
||||
// CHECK-NEXT: τ_0_0 : Canidae
|
||||
func inferSuperclassRequirement1<T : Carnivora>(_ v: V<T>) {}
|
||||
|
||||
// CHECK-LABEL: .inferSuperclassRequirement2@
|
||||
// CHECK-NEXT: Requirements:
|
||||
// CHECK-NEXT: T : Canidae
|
||||
// CHECK-NEXT: τ_0_0 : Canidae
|
||||
func inferSuperclassRequirement2<T : Canidae>(_ v: U<T>) {}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
@@ -111,26 +111,26 @@ struct Model_P3_P4_Eq<T : P3, U : P4> where T.P3Assoc == U.P4Assoc {}
|
||||
|
||||
// CHECK-LABEL: .inferSameType1@
|
||||
// CHECK-NEXT: Requirements:
|
||||
// CHECK-NEXT: T : P3 [inferred @ {{.*}}:32]
|
||||
// CHECK-NEXT: U : P4 [inferred @ {{.*}}:32]
|
||||
// CHECK-NEXT: T[.P3].P3Assoc : P1 [redundant @ {{.*}}:18]
|
||||
// CHECK-NEXT: T[.P3].P3Assoc : P2 [protocol @ {{.*}}:18]
|
||||
// CHECK-NEXT: τ_0_0 : P3 [inferred @ {{.*}}:32]
|
||||
// CHECK-NEXT: τ_0_1 : P4 [inferred @ {{.*}}:32]
|
||||
// CHECK-NEXT: τ_0_0[.P3].P3Assoc : P1 [redundant @ {{.*}}:18]
|
||||
// CHECK-NEXT: τ_0_0[.P3].P3Assoc : P2 [protocol @ {{.*}}:18]
|
||||
func inferSameType1<T, U>(_ x: Model_P3_P4_Eq<T, U>) { }
|
||||
|
||||
// CHECK-LABEL: .inferSameType2@
|
||||
// CHECK-NEXT: Requirements:
|
||||
// CHECK-NEXT: T : P3 [inferred]
|
||||
// CHECK-NEXT: U : P4 [inferred]
|
||||
// CHECK-NEXT: T[.P3].P3Assoc : P1 [redundant @ {{.*}}requirement_inference.swift:{{.*}}:18]
|
||||
// CHECK-NEXT: T[.P3].P3Assoc : P2 [protocol @ {{.*}}requirement_inference.swift:{{.*}}:18]
|
||||
// CHECK-NEXT: T[.P3].P3Assoc == U[.P4].P4Assoc [explicit]
|
||||
// CHECK-NEXT: τ_0_0 : P3 [inferred]
|
||||
// CHECK-NEXT: τ_0_1 : P4 [inferred]
|
||||
// CHECK-NEXT: τ_0_0[.P3].P3Assoc : P1 [redundant @ {{.*}}requirement_inference.swift:{{.*}}:18]
|
||||
// CHECK-NEXT: τ_0_0[.P3].P3Assoc : P2 [protocol @ {{.*}}requirement_inference.swift:{{.*}}:18]
|
||||
// CHECK-NEXT: τ_0_0[.P3].P3Assoc == τ_0_1[.P4].P4Assoc [explicit]
|
||||
func inferSameType2<T : P3, U : P4>(_: T, _: U) where U.P4Assoc : P2, T.P3Assoc == U.P4Assoc {}
|
||||
|
||||
// CHECK-LABEL: .inferSameType3@
|
||||
// CHECK-NEXT: Requirements:
|
||||
// CHECK-NEXT: T : PCommonAssoc1 [inferred]
|
||||
// CHECK-NEXT: T : PCommonAssoc2 [inferred]
|
||||
// CHECK-NEXT: T[.PCommonAssoc1].CommonAssoc : P1 [explicit @ {{.*}}requirement_inference.swift:{{.*}}:68]
|
||||
// CHECK-NEXT: τ_0_0 : PCommonAssoc1 [inferred]
|
||||
// CHECK-NEXT: τ_0_0 : PCommonAssoc2 [inferred]
|
||||
// CHECK-NEXT: τ_0_0[.PCommonAssoc1].CommonAssoc : P1 [explicit @ {{.*}}requirement_inference.swift:{{.*}}:68]
|
||||
// CHECK-NEXT: Potential archetypes
|
||||
func inferSameType3<T : PCommonAssoc1>(_: T) where T.CommonAssoc : P1, T : PCommonAssoc2 {}
|
||||
|
||||
|
||||
@@ -65,17 +65,17 @@ extension P2 where Self.T : C {
|
||||
|
||||
// CHECK: superclassConformance1
|
||||
// CHECK: Requirements:
|
||||
// CHECK-NEXT: T : C [explicit @
|
||||
// CHECK-NEXT: T : P3 [inherited @
|
||||
// CHECK-NEXT: T[.P3].T == C.T [redundant]
|
||||
// CHECK-NEXT: τ_0_0 : C [explicit @
|
||||
// CHECK-NEXT: τ_0_0 : P3 [inherited @
|
||||
// CHECK-NEXT: τ_0_0[.P3].T == C.T [redundant]
|
||||
// CHECK: Canonical generic signature: <τ_0_0 where τ_0_0 : C>
|
||||
func superclassConformance1<T>(t: T) where T : C, T : P3 {}
|
||||
|
||||
// CHECK: superclassConformance2
|
||||
// CHECK: Requirements:
|
||||
// CHECK-NEXT: T : C [explicit @
|
||||
// CHECK-NEXT: T : P3 [inherited @
|
||||
// CHECK-NEXT: T[.P3].T == C.T [redundant]
|
||||
// CHECK-NEXT: τ_0_0 : C [explicit @
|
||||
// CHECK-NEXT: τ_0_0 : P3 [inherited @
|
||||
// CHECK-NEXT: τ_0_0[.P3].T == C.T [redundant]
|
||||
// CHECK: Canonical generic signature: <τ_0_0 where τ_0_0 : C>
|
||||
func superclassConformance2<T>(t: T) where T : C, T : P3 {}
|
||||
|
||||
@@ -85,7 +85,7 @@ class C2 : C, P4 { }
|
||||
|
||||
// CHECK: superclassConformance3
|
||||
// CHECK: Requirements:
|
||||
// CHECK-NEXT: T : C2 [explicit @
|
||||
// CHECK-NEXT: T : P4 [inherited @
|
||||
// CHECK-NEXT: τ_0_0 : C2 [explicit @
|
||||
// CHECK-NEXT: τ_0_0 : P4 [inherited @
|
||||
// CHECK: Canonical generic signature: <τ_0_0 where τ_0_0 : C2>
|
||||
func superclassConformance3<T>(t: T) where T : C, T : P4, T : C2 {}
|
||||
|
||||
@@ -85,7 +85,7 @@ struct FloatElement : HasElt {
|
||||
typealias Element = Float
|
||||
}
|
||||
@_specialize(where T == FloatElement)
|
||||
@_specialize(where T == IntElement) // expected-error{{generic parameter T.Element cannot be equal to both 'Float' and 'IntElement.Element' (aka 'Int')}}
|
||||
@_specialize(where T == IntElement) // expected-error{{generic parameter 'T.Element' cannot be equal to both 'Float' and 'IntElement.Element' (aka 'Int')}}
|
||||
func sameTypeRequirement<T : HasElt>(_ t: T) where T.Element == Float {}
|
||||
|
||||
@_specialize(where T == Sub)
|
||||
|
||||
Reference in New Issue
Block a user