[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:
Doug Gregor
2017-02-07 10:36:53 -08:00
parent 900a60e6f0
commit 0c76a9d828
9 changed files with 193 additions and 196 deletions

View File

@@ -19,6 +19,7 @@
#ifndef SWIFT_ARCHETYPEBUILDER_H #ifndef SWIFT_ARCHETYPEBUILDER_H
#define SWIFT_ARCHETYPEBUILDER_H #define SWIFT_ARCHETYPEBUILDER_H
#include "swift/AST/Decl.h"
#include "swift/AST/Identifier.h" #include "swift/AST/Identifier.h"
#include "swift/AST/Types.h" #include "swift/AST/Types.h"
#include "swift/AST/TypeLoc.h" #include "swift/AST/TypeLoc.h"
@@ -33,20 +34,15 @@
namespace swift { namespace swift {
class AbstractTypeParamDecl;
class ArchetypeType;
class AssociatedTypeDecl;
class DeclContext; class DeclContext;
class DependentMemberType; class DependentMemberType;
class GenericParamList; class GenericParamList;
class GenericSignature; class GenericSignature;
class GenericTypeParamDecl;
class GenericTypeParamType; class GenericTypeParamType;
class LazyResolver; class LazyResolver;
class ModuleDecl; class ModuleDecl;
class Pattern; class Pattern;
class ProtocolConformance; class ProtocolConformance;
class ProtocolDecl;
class Requirement; class Requirement;
class RequirementRepr; class RequirementRepr;
class SILModule; class SILModule;
@@ -227,10 +223,6 @@ public:
RequirementRHS constraint, RequirementRHS constraint,
RequirementSource source)> f); RequirementSource source)> f);
private:
PotentialArchetype *addGenericParameter(GenericTypeParamType *GenericParam,
Identifier ParamName);
public: public:
/// \brief Add a new generic parameter for which there may be requirements. /// \brief Add a new generic parameter for which there may be requirements.
void addGenericParameter(GenericTypeParamDecl *GenericParam); void addGenericParameter(GenericTypeParamDecl *GenericParam);
@@ -333,19 +325,37 @@ public:
}; };
class ArchetypeBuilder::PotentialArchetype { class ArchetypeBuilder::PotentialArchetype {
/// Either the parent of this potential archetype (for an associated /// The parent of this potential archetype (for a nested type) or the
/// type) or the generic type parameter type to which this potential /// archetype builder in which this root resides.
/// archetype corresponds. llvm::PointerUnion<PotentialArchetype*, ArchetypeBuilder*> parentOrBuilder;
llvm::PointerUnion<PotentialArchetype*, GenericTypeParamType*> ParentOrParam;
/// \brief The name of this potential archetype or, for an /// The identifier describing this particular archetype.
/// associated type, the declaration of the associated type to which ///
/// this potential archetype has been resolved. Or, for a type alias, /// \c parentOrBuilder determines whether we have a nested type vs. a root,
/// the type alias decl. /// while `isUnresolvedNestedType` determines whether we have an unresolved
llvm::PointerUnion3<Identifier, AssociatedTypeDecl *, /// nested type (vs. a resolved one);
TypeAliasDecl *> NameOrAssociatedType; 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. /// to which this potential archetype belongs.
PotentialArchetype *Representative; PotentialArchetype *Representative;
@@ -383,6 +393,9 @@ class ArchetypeBuilder::PotentialArchetype {
/// The source of the concrete type requirement. /// The source of the concrete type requirement.
Optional<RequirementSource> ConcreteTypeSource; Optional<RequirementSource> ConcreteTypeSource;
/// Whether this is an unresolved nested type.
unsigned isUnresolvedNestedType : 1;
/// \brief Recursively conforms to itself. /// \brief Recursively conforms to itself.
unsigned IsRecursive : 1; unsigned IsRecursive : 1;
@@ -410,108 +423,97 @@ class ArchetypeBuilder::PotentialArchetype {
/// \brief Construct a new potential archetype for an unresolved /// \brief Construct a new potential archetype for an unresolved
/// associated type. /// associated type.
PotentialArchetype(PotentialArchetype *Parent, Identifier Name) PotentialArchetype(PotentialArchetype *parent, Identifier name)
: ParentOrParam(Parent), NameOrAssociatedType(Name), Representative(this), : parentOrBuilder(parent), identifier(name), Representative(this),
isUnresolvedNestedType(true),
IsRecursive(false), Invalid(false), IsRecursive(false), Invalid(false),
RecursiveConcreteType(false), RecursiveSuperclassType(false), RecursiveConcreteType(false), RecursiveSuperclassType(false),
DiagnosedRename(false) DiagnosedRename(false)
{ {
assert(Parent != nullptr && "Not an associated type?"); assert(parent != nullptr && "Not an associated type?");
EquivalenceClass.push_back(this); EquivalenceClass.push_back(this);
} }
/// \brief Construct a new potential archetype for an associated type. /// \brief Construct a new potential archetype for an associated type.
PotentialArchetype(PotentialArchetype *Parent, AssociatedTypeDecl *AssocType) PotentialArchetype(PotentialArchetype *parent, AssociatedTypeDecl *assocType)
: ParentOrParam(Parent), NameOrAssociatedType(AssocType), : parentOrBuilder(parent), identifier(assocType),
Representative(this), IsRecursive(false), Invalid(false), Representative(this), isUnresolvedNestedType(false),
IsRecursive(false), Invalid
(false),
RecursiveConcreteType(false), RecursiveConcreteType(false),
RecursiveSuperclassType(false), DiagnosedRename(false) RecursiveSuperclassType(false), DiagnosedRename(false)
{ {
assert(Parent != nullptr && "Not an associated type?"); assert(parent != nullptr && "Not an associated type?");
EquivalenceClass.push_back(this); EquivalenceClass.push_back(this);
} }
/// \brief Construct a new potential archetype for a type alias. /// \brief Construct a new potential archetype for a type alias.
PotentialArchetype(PotentialArchetype *Parent, TypeAliasDecl *TypeAlias) PotentialArchetype(PotentialArchetype *parent, TypeAliasDecl *typeAlias)
: ParentOrParam(Parent), NameOrAssociatedType(TypeAlias), : parentOrBuilder(parent), identifier(typeAlias),
Representative(this), IsRecursive(false), Invalid(false), Representative(this), isUnresolvedNestedType(false),
IsRecursive(false), Invalid(false),
RecursiveConcreteType(false), RecursiveConcreteType(false),
RecursiveSuperclassType(false), DiagnosedRename(false) RecursiveSuperclassType(false), DiagnosedRename(false)
{ {
assert(Parent != nullptr && "Not an associated type?"); assert(parent != nullptr && "Not an associated type?");
EquivalenceClass.push_back(this); EquivalenceClass.push_back(this);
} }
/// \brief Construct a new potential archetype for a generic parameter. /// \brief Construct a new potential archetype for a generic parameter.
PotentialArchetype(GenericTypeParamType *GenericParam, PotentialArchetype(ArchetypeBuilder *builder, GenericParamKey genericParam)
Identifier Name) : parentOrBuilder(builder), identifier(genericParam),
: ParentOrParam(GenericParam), Representative(this), isUnresolvedNestedType(false),
NameOrAssociatedType(Name), Representative(this), IsRecursive(false), IsRecursive(false), Invalid(false),
Invalid(false),
RecursiveConcreteType(false), RecursiveSuperclassType(false), RecursiveConcreteType(false), RecursiveSuperclassType(false),
DiagnosedRename(false) DiagnosedRename(false)
{ {
EquivalenceClass.push_back(this); 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 /// \brief Retrieve the representative for this archetype, performing
/// path compression on the way. /// path compression on the way.
PotentialArchetype *getRepresentative(); 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 ArchetypeBuilder;
friend class GenericSignature; 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. /// \brief Retrieve the debug name of this potential archetype.
std::string getDebugName() const; std::string getDebugName() const;
public:
~PotentialArchetype();
/// Retrieve the parent of this potential archetype, which will be non-null /// Retrieve the parent of this potential archetype, which will be non-null
/// when this potential archetype is an associated type. /// when this potential archetype is an associated type.
PotentialArchetype *getParent() const { PotentialArchetype *getParent() const {
return ParentOrParam.dyn_cast<PotentialArchetype *>(); return parentOrBuilder.dyn_cast<PotentialArchetype *>();
} }
/// Retrieve the associated type to which this potential archetype /// Retrieve the associated type to which this potential archetype
/// has been resolved. /// has been resolved.
AssociatedTypeDecl *getResolvedAssociatedType() const { AssociatedTypeDecl *getResolvedAssociatedType() const {
assert(getParent() && "Not an associated type"); 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. /// Resolve the potential archetype to the given associated type.
void resolveAssociatedType(AssociatedTypeDecl *assocType, void resolveAssociatedType(AssociatedTypeDecl *assocType,
ArchetypeBuilder &builder); 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. /// Determine whether this is a generic parameter.
bool isGenericParam() const { bool isGenericParam() const {
return ParentOrParam.is<GenericTypeParamType *>(); return parentOrBuilder.is<ArchetypeBuilder *>();
} }
/// Retrieve the generic parameter key for a potential archetype that /// Retrieve the generic parameter key for a potential archetype that
@@ -519,18 +521,35 @@ public:
/// ///
/// \pre \c isGenericParam() /// \pre \c isGenericParam()
GenericParamKey getGenericParamKey() const { 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 /// Retrieve the generic parameter key for the generic parameter at the
/// root of this potential archetype. /// root of this potential archetype.
GenericParamKey getRootGenericParamKey() const { 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. /// Retrieve the type alias.
TypeAliasDecl *getTypeAliasDecl() const { 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. /// 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 /// Note that this potential archetype was is going to be renamed (due to typo
/// correction), saving the old name. /// correction), saving the old name.
void saveNameForRenaming() { void saveNameForRenaming() {
OrigName = getName(); OrigName = getNestedName();
} }
/// For a renamed potential archetype, retrieve the original name. /// For a renamed potential archetype, retrieve the original name.

View File

@@ -1561,13 +1561,13 @@ ERROR(requires_no_same_type_archetype,none,
()) ())
ERROR(requires_generic_params_made_equal,none, ERROR(requires_generic_params_made_equal,none,
"same-type requirement makes generic parameters %0 and %1 equivalent", "same-type requirement makes generic parameters %0 and %1 equivalent",
(Identifier, Identifier)) (Type, Type))
ERROR(requires_generic_param_made_equal_to_concrete,none, ERROR(requires_generic_param_made_equal_to_concrete,none,
"same-type requirement makes generic parameter %0 non-generic", "same-type requirement makes generic parameter %0 non-generic",
(Identifier)) (Type))
ERROR(requires_superclass_conflict,none, ERROR(requires_superclass_conflict,none,
"generic parameter %0 cannot be a subclass of both %1 and %2", "generic parameter %0 cannot be a subclass of both %1 and %2",
(Identifier, Type, Type)) (Type, Type, Type))
ERROR(recursive_type_reference,none, ERROR(recursive_type_reference,none,
"%0 %1 references itself", (DescriptiveDeclKind, Identifier)) "%0 %1 references itself", (DescriptiveDeclKind, Identifier))
ERROR(recursive_requirement_reference,none, ERROR(recursive_requirement_reference,none,
@@ -1578,7 +1578,7 @@ ERROR(recursive_superclass_constraint,none,
"superclass constraint %0 : %1 is recursive", (Type, Type)) "superclass constraint %0 : %1 is recursive", (Type, Type))
ERROR(requires_same_type_conflict,none, ERROR(requires_same_type_conflict,none,
"generic parameter %0 cannot be equal to both %1 and %2", "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, ERROR(requires_generic_param_same_type_does_not_conform,none,
"same-type constraint type %0 does not conform to required protocol %1", "same-type constraint type %0 does not conform to required protocol %1",
(Type, Identifier)) (Type, Identifier))

View File

@@ -121,15 +121,22 @@ ArchetypeBuilder::PotentialArchetype::~PotentialArchetype() {
} }
} }
void ArchetypeBuilder::PotentialArchetype::buildFullName( std::string ArchetypeBuilder::PotentialArchetype::getDebugName() const {
bool forDebug, llvm::SmallString<64> result;
SmallVectorImpl<char> &result) const {
if (auto parent = getParent()) { auto parent = getParent();
parent->buildFullName(forDebug, result); 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 // When building the name for debugging purposes, include the
// protocol into which the associated type was resolved. // protocol into which the associated type was resolved.
if (forDebug) {
if (auto assocType = getResolvedAssociatedType()) { if (auto assocType = getResolvedAssociatedType()) {
result.push_back('['); result.push_back('[');
result.push_back('.'); result.push_back('.');
@@ -137,30 +144,10 @@ void ArchetypeBuilder::PotentialArchetype::buildFullName(
assocType->getProtocol()->getName().str().end()); assocType->getProtocol()->getName().str().end());
result.push_back(']'); result.push_back(']');
} }
}
result.push_back('.'); result.push_back('.');
} result.append(getNestedName().str().begin(), getNestedName().str().end());
result.append(getName().str().begin(), getName().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(); return result.str().str();
} }
@@ -174,10 +161,10 @@ unsigned ArchetypeBuilder::PotentialArchetype::getNestingDepth() const {
void ArchetypeBuilder::PotentialArchetype::resolveAssociatedType( void ArchetypeBuilder::PotentialArchetype::resolveAssociatedType(
AssociatedTypeDecl *assocType, AssociatedTypeDecl *assocType,
ArchetypeBuilder &builder) { ArchetypeBuilder &builder) {
assert(!NameOrAssociatedType.is<AssociatedTypeDecl *>() && assert(!getResolvedAssociatedType() && "associated type is already resolved");
"associated type is already resolved"); isUnresolvedNestedType = false;
NameOrAssociatedType = assocType; identifier.assocTypeOrAlias = assocType;
assert(assocType->getName() == getName()); assert(assocType->getName() == getNestedName());
assert(builder.Impl->NumUnresolvedNestedTypes > 0 && assert(builder.Impl->NumUnresolvedNestedTypes > 0 &&
"Mismatch in number of unresolved nested types"); "Mismatch in number of unresolved nested types");
--builder.Impl->NumUnresolvedNestedTypes; --builder.Impl->NumUnresolvedNestedTypes;
@@ -382,7 +369,8 @@ static int compareDependentTypes(
return compareBases; return compareBases;
// - by name, so t_n_m.`P.T` < t_n_m.`P.U` // - 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; return compareNames;
if (auto *aa = a->getResolvedAssociatedType()) { if (auto *aa = a->getResolvedAssociatedType()) {
@@ -483,7 +471,7 @@ static ArchetypeBuilder::PotentialArchetype*rebuildPotentialArchetypeAnchor(
if (auto assocType = pa->getResolvedAssociatedType()) if (auto assocType = pa->getResolvedAssociatedType())
return parentAnchor->getNestedType(assocType, builder); return parentAnchor->getNestedType(assocType, builder);
return parentAnchor->getNestedType(pa->getName(), builder); return parentAnchor->getNestedType(pa->getNestedName(), builder);
} }
return pa; return pa;
@@ -728,7 +716,7 @@ Type ArchetypeBuilder::PotentialArchetype::getTypeInContext(
// Check whether the parent already has a nested type with this name. If // Check whether the parent already has a nested type with this name. If
// so, return it directly. // so, return it directly.
if (auto nested = ParentArchetype->getNestedTypeIfKnown(getName())) if (auto nested = ParentArchetype->getNestedTypeIfKnown(getNestedName()))
return *nested; return *nested;
// We will build the archetype below. // We will build the archetype below.
@@ -797,7 +785,7 @@ Type ArchetypeBuilder::PotentialArchetype::getTypeInContext(
superclass, layout); superclass, layout);
// Register this archetype with its parent. // Register this archetype with its parent.
ParentArchetype->registerNestedType(getName(), arch); ParentArchetype->registerNestedType(getNestedName(), arch);
} else { } else {
// Create a top-level archetype. // Create a top-level archetype.
Identifier name = Identifier name =
@@ -846,27 +834,29 @@ Type ArchetypeBuilder::PotentialArchetype::getDependentType(
return ErrorType::get(getDependentType(genericParams, return ErrorType::get(getDependentType(genericParams,
/*allowUnresolved=*/true)); /*allowUnresolved=*/true));
return DependentMemberType::get(parentType, getName()); return DependentMemberType::get(parentType, getNestedName());
} }
assert(isGenericParam() && "Not a generic parameter?"); assert(isGenericParam() && "Not a generic parameter?");
unsigned index = getGenericParamKey().findIndexIn(genericParams);
// FIXME: This is a temporary workaround. // FIXME: This is a temporary workaround.
if (genericParams.empty()) { 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, void ArchetypeBuilder::PotentialArchetype::dump(llvm::raw_ostream &Out,
SourceManager *SrcMgr, SourceManager *SrcMgr,
unsigned Indent) { unsigned Indent) {
// Print name. // Print name.
if (Indent == 0) if (Indent == 0 || isGenericParam())
Out << getDebugName(); Out << getDebugName();
else else
Out.indent(Indent) << getName(); Out.indent(Indent) << getNestedName();
// Print superclass. // Print superclass.
if (Superclass) { if (Superclass) {
@@ -895,7 +885,7 @@ void ArchetypeBuilder::PotentialArchetype::dump(llvm::raw_ostream &Out,
} }
if (Representative != this) { if (Representative != this) {
Out << " [represented by " << getRepresentative()->getFullName() << "]"; Out << " [represented by " << getRepresentative()->getDebugName() << "]";
} }
if (EquivalenceClass.size() > 1) { if (EquivalenceClass.size() > 1) {
@@ -972,28 +962,9 @@ auto ArchetypeBuilder::resolveArchetype(Type type) -> PotentialArchetype * {
return nullptr; 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) { void ArchetypeBuilder::addGenericParameter(GenericTypeParamDecl *GenericParam) {
addGenericParameter( addGenericParameter(
GenericParam->getDeclaredInterfaceType()->castTo<GenericTypeParamType>(), GenericParam->getDeclaredInterfaceType()->castTo<GenericTypeParamType>());
GenericParam->getName());
} }
bool ArchetypeBuilder::addGenericParameterRequirements(GenericTypeParamDecl *GenericParam) { bool ArchetypeBuilder::addGenericParameterRequirements(GenericTypeParamDecl *GenericParam) {
@@ -1008,13 +979,17 @@ bool ArchetypeBuilder::addGenericParameterRequirements(GenericTypeParamDecl *Gen
} }
void ArchetypeBuilder::addGenericParameter(GenericTypeParamType *GenericParam) { void ArchetypeBuilder::addGenericParameter(GenericTypeParamType *GenericParam) {
auto name = GenericParam->getName(); GenericParamKey Key(GenericParam);
// Trim '$' so that archetypes are more readily discernible from abstract assert(Impl->GenericParams.empty() ||
// parameters. ((Key.Depth == Impl->GenericParams.back()->getDepth() &&
if (name.str().startswith("$")) Key.Index == Impl->GenericParams.back()->getIndex() + 1) ||
name = Context.getIdentifier(name.str().slice(1, name.str().size())); (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, bool ArchetypeBuilder::addConformanceRequirement(PotentialArchetype *PAT,
@@ -1193,7 +1168,8 @@ bool ArchetypeBuilder::addSuperclassRequirement(PotentialArchetype *T,
// constraint. // constraint.
} else if (!Superclass->isExactSuperclassOf(T->Superclass, nullptr)) { } else if (!Superclass->isExactSuperclassOf(T->Superclass, nullptr)) {
Diags.diagnose(Source.getLoc(), Diags.diagnose(Source.getLoc(),
diag::requires_superclass_conflict, T->getName(), diag::requires_superclass_conflict,
T->getDependentType(/*FIXME: */{ }, true),
T->Superclass, Superclass) T->Superclass, Superclass)
.highlight(T->SuperclassSource->getLoc()); .highlight(T->SuperclassSource->getLoc());
return true; return true;
@@ -1257,9 +1233,9 @@ bool ArchetypeBuilder::addSameTypeRequirementBetweenArchetypes(
if (concrete1 && concrete2) { if (concrete1 && concrete2) {
if (!concrete1->isEqual(concrete2)) { if (!concrete1->isEqual(concrete2)) {
StringRef Name = T1->getFullName();
Diags.diagnose(Source.getLoc(), diag::requires_same_type_conflict, Diags.diagnose(Source.getLoc(), diag::requires_same_type_conflict,
Name, concrete1, concrete2); T1->getDependentType(/*FIXME: */{ }, true), concrete1,
concrete2);
return true; return true;
} }
@@ -1331,9 +1307,9 @@ bool ArchetypeBuilder::addSameTypeRequirementToConcrete(
// problem. // problem.
if (auto oldConcrete = T->getConcreteType()) { if (auto oldConcrete = T->getConcreteType()) {
if (!oldConcrete->isEqual(Concrete)) { if (!oldConcrete->isEqual(Concrete)) {
StringRef Name = T->getFullName();
Diags.diagnose(Source.getLoc(), diag::requires_same_type_conflict, Diags.diagnose(Source.getLoc(), diag::requires_same_type_conflict,
Name, oldConcrete, Concrete); T->getDependentType(/*FIXME: */{ }, true), oldConcrete,
Concrete);
return true; return true;
} }
return false; return false;
@@ -1831,7 +1807,7 @@ void ArchetypeBuilder::inferRequirements(ParameterList *params,
/// corrected name (if successful). /// corrected name (if successful).
static Identifier typoCorrectNestedType( static Identifier typoCorrectNestedType(
ArchetypeBuilder::PotentialArchetype *pa) { 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 // Look through all of the associated types of all of the protocols
// to which the parent conforms. // to which the parent conforms.
@@ -2042,7 +2018,8 @@ ArchetypeBuilder::finalize(SourceLoc loc,
Diags.diagnose(Source->getLoc(), Diags.diagnose(Source->getLoc(),
diag::requires_generic_param_made_equal_to_concrete, diag::requires_generic_param_made_equal_to_concrete,
rep->getName()); rep->getDependentType(genericParams,
/*allowUnresolved=*/true));
continue; continue;
} }
@@ -2071,7 +2048,8 @@ ArchetypeBuilder::finalize(SourceLoc loc,
Diags.diagnose(constraintLoc, Diags.diagnose(constraintLoc,
diag::requires_generic_params_made_equal, diag::requires_generic_params_made_equal,
pa->getName(), other->getName()); pa->getDependentType(genericParams, true),
other->getDependentType(genericParams, true));
break; break;
} }
} }
@@ -2119,7 +2097,7 @@ bool ArchetypeBuilder::diagnoseRemainingRenames(
Diags.diagnose(loc, diag::invalid_member_type_suggest, Diags.diagnose(loc, diag::invalid_member_type_suggest,
pa->getParent()->getDependentType(genericParams, pa->getParent()->getDependentType(genericParams,
/*allowUnresolved=*/true), /*allowUnresolved=*/true),
pa->getOriginalName(), pa->getName()); pa->getOriginalName(), pa->getNestedName());
invalid = true; invalid = true;
} }

View File

@@ -157,7 +157,7 @@ Type CompleteGenericTypeResolver::resolveDependentMemberType(
// If this potential archetype was renamed due to typo correction, // If this potential archetype was renamed due to typo correction,
// complain and fix it. // complain and fix it.
if (nestedPA->wasRenamed()) { if (nestedPA->wasRenamed()) {
auto newName = nestedPA->getName(); auto newName = nestedPA->getNestedName();
TC.diagnose(ref->getIdLoc(), diag::invalid_member_type_suggest, TC.diagnose(ref->getIdLoc(), diag::invalid_member_type_suggest,
baseTy, ref->getIdentifier(), newName) baseTy, ref->getIdentifier(), newName)
.fixItReplace(ref->getIdLoc(), newName.str()); .fixItReplace(ref->getIdLoc(), newName.str());

View File

@@ -56,14 +56,14 @@ func test3<T: Fooable, U: Fooable>(_ t: T, u: U) -> (X, X)
func fail1< func fail1<
T: Fooable, U: Fooable T: Fooable, U: Fooable
>(_ t: T, u: U) -> (X, Y) >(_ 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) return (t.foo, u.foo)
} }
func fail2< func fail2<
T: Fooable, U: Fooable T: Fooable, U: Fooable
>(_ t: T, u: U) -> (X, Y) >(_ 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'}} 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) func fail4<T: Barrable>(_ t: T) -> (Y, Z)
where where
T.Bar == Y, 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'}} 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) func fail5<T: Barrable>(_ t: T) -> (Y, Z)
where where
T.Bar.Foo == Z, 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'}} 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 func testAssocTypeEquivalence<T: Fooable>(_ fooable: T) -> X.Type
where T.Foo == X { where T.Foo == X {

View File

@@ -37,9 +37,9 @@ func typoAssoc4<T : P2>(_: T) where T.Assocp2.assoc : P3 {}
// CHECK-GENERIC-LABEL: .typoAssoc4@ // CHECK-GENERIC-LABEL: .typoAssoc4@
// CHECK-GENERIC-NEXT: Requirements: // CHECK-GENERIC-NEXT: Requirements:
// CHECK-GENERIC-NEXT: T : P2 [inferred] // CHECK-GENERIC-NEXT: τ_0_0 : P2 [inferred]
// CHECK-GENERIC-NEXT: T[.P2].AssocP2 : P1 [protocol // CHECK-GENERIC-NEXT: τ_0_0[.P2].AssocP2 : P1 [protocol
// CHECK-GENERIC-NEXT: T[.P2].AssocP2[.P1].Assoc : P3 [explicit // CHECK-GENERIC-NEXT: τ_0_0[.P2].AssocP2[.P1].Assoc : P3 [explicit
// CHECK-GENERIC-NEXT: Potential archetypes // CHECK-GENERIC-NEXT: Potential archetypes
// <rdar://problem/19620340> // <rdar://problem/19620340>

View File

@@ -57,7 +57,7 @@ class Fox : P1 {
class Box<T : Fox> { class Box<T : Fox> {
// CHECK-LABEL: .unpack@ // CHECK-LABEL: .unpack@
// CHECK-NEXT: Requirements: // CHECK-NEXT: Requirements:
// CHECK-NEXT: T : Fox [explicit] // CHECK-NEXT: τ_0_0 : Fox [explicit]
func unpack(_ x: X1<T>) {} func unpack(_ x: X1<T>) {}
} }
@@ -75,12 +75,12 @@ struct V<T : Canidae> {}
// CHECK-LABEL: .inferSuperclassRequirement1@ // CHECK-LABEL: .inferSuperclassRequirement1@
// CHECK-NEXT: Requirements: // CHECK-NEXT: Requirements:
// CHECK-NEXT: T : Canidae // CHECK-NEXT: τ_0_0 : Canidae
func inferSuperclassRequirement1<T : Carnivora>(_ v: V<T>) {} func inferSuperclassRequirement1<T : Carnivora>(_ v: V<T>) {}
// CHECK-LABEL: .inferSuperclassRequirement2@ // CHECK-LABEL: .inferSuperclassRequirement2@
// CHECK-NEXT: Requirements: // CHECK-NEXT: Requirements:
// CHECK-NEXT: T : Canidae // CHECK-NEXT: τ_0_0 : Canidae
func inferSuperclassRequirement2<T : Canidae>(_ v: U<T>) {} 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-LABEL: .inferSameType1@
// CHECK-NEXT: Requirements: // CHECK-NEXT: Requirements:
// CHECK-NEXT: T : P3 [inferred @ {{.*}}:32] // CHECK-NEXT: τ_0_0 : P3 [inferred @ {{.*}}:32]
// CHECK-NEXT: U : P4 [inferred @ {{.*}}:32] // CHECK-NEXT: τ_0_1 : P4 [inferred @ {{.*}}:32]
// CHECK-NEXT: T[.P3].P3Assoc : P1 [redundant @ {{.*}}:18] // CHECK-NEXT: τ_0_0[.P3].P3Assoc : P1 [redundant @ {{.*}}:18]
// CHECK-NEXT: T[.P3].P3Assoc : P2 [protocol @ {{.*}}:18] // CHECK-NEXT: τ_0_0[.P3].P3Assoc : P2 [protocol @ {{.*}}:18]
func inferSameType1<T, U>(_ x: Model_P3_P4_Eq<T, U>) { } func inferSameType1<T, U>(_ x: Model_P3_P4_Eq<T, U>) { }
// CHECK-LABEL: .inferSameType2@ // CHECK-LABEL: .inferSameType2@
// CHECK-NEXT: Requirements: // CHECK-NEXT: Requirements:
// CHECK-NEXT: T : P3 [inferred] // CHECK-NEXT: τ_0_0 : P3 [inferred]
// CHECK-NEXT: U : P4 [inferred] // CHECK-NEXT: τ_0_1 : P4 [inferred]
// CHECK-NEXT: T[.P3].P3Assoc : P1 [redundant @ {{.*}}requirement_inference.swift:{{.*}}:18] // CHECK-NEXT: τ_0_0[.P3].P3Assoc : P1 [redundant @ {{.*}}requirement_inference.swift:{{.*}}:18]
// CHECK-NEXT: T[.P3].P3Assoc : P2 [protocol @ {{.*}}requirement_inference.swift:{{.*}}:18] // CHECK-NEXT: τ_0_0[.P3].P3Assoc : P2 [protocol @ {{.*}}requirement_inference.swift:{{.*}}:18]
// CHECK-NEXT: T[.P3].P3Assoc == U[.P4].P4Assoc [explicit] // 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 {} func inferSameType2<T : P3, U : P4>(_: T, _: U) where U.P4Assoc : P2, T.P3Assoc == U.P4Assoc {}
// CHECK-LABEL: .inferSameType3@ // CHECK-LABEL: .inferSameType3@
// CHECK-NEXT: Requirements: // CHECK-NEXT: Requirements:
// CHECK-NEXT: T : PCommonAssoc1 [inferred] // CHECK-NEXT: τ_0_0 : PCommonAssoc1 [inferred]
// CHECK-NEXT: T : PCommonAssoc2 [inferred] // CHECK-NEXT: τ_0_0 : PCommonAssoc2 [inferred]
// CHECK-NEXT: T[.PCommonAssoc1].CommonAssoc : P1 [explicit @ {{.*}}requirement_inference.swift:{{.*}}:68] // CHECK-NEXT: τ_0_0[.PCommonAssoc1].CommonAssoc : P1 [explicit @ {{.*}}requirement_inference.swift:{{.*}}:68]
// CHECK-NEXT: Potential archetypes // CHECK-NEXT: Potential archetypes
func inferSameType3<T : PCommonAssoc1>(_: T) where T.CommonAssoc : P1, T : PCommonAssoc2 {} func inferSameType3<T : PCommonAssoc1>(_: T) where T.CommonAssoc : P1, T : PCommonAssoc2 {}

View File

@@ -65,17 +65,17 @@ extension P2 where Self.T : C {
// CHECK: superclassConformance1 // CHECK: superclassConformance1
// CHECK: Requirements: // CHECK: Requirements:
// CHECK-NEXT: T : C [explicit @ // CHECK-NEXT: τ_0_0 : C [explicit @
// CHECK-NEXT: T : P3 [inherited @ // CHECK-NEXT: τ_0_0 : P3 [inherited @
// CHECK-NEXT: T[.P3].T == C.T [redundant] // CHECK-NEXT: τ_0_0[.P3].T == C.T [redundant]
// CHECK: Canonical generic signature: <τ_0_0 where τ_0_0 : C> // CHECK: Canonical generic signature: <τ_0_0 where τ_0_0 : C>
func superclassConformance1<T>(t: T) where T : C, T : P3 {} func superclassConformance1<T>(t: T) where T : C, T : P3 {}
// CHECK: superclassConformance2 // CHECK: superclassConformance2
// CHECK: Requirements: // CHECK: Requirements:
// CHECK-NEXT: T : C [explicit @ // CHECK-NEXT: τ_0_0 : C [explicit @
// CHECK-NEXT: T : P3 [inherited @ // CHECK-NEXT: τ_0_0 : P3 [inherited @
// CHECK-NEXT: T[.P3].T == C.T [redundant] // CHECK-NEXT: τ_0_0[.P3].T == C.T [redundant]
// CHECK: Canonical generic signature: <τ_0_0 where τ_0_0 : C> // CHECK: Canonical generic signature: <τ_0_0 where τ_0_0 : C>
func superclassConformance2<T>(t: T) where T : C, T : P3 {} func superclassConformance2<T>(t: T) where T : C, T : P3 {}
@@ -85,7 +85,7 @@ class C2 : C, P4 { }
// CHECK: superclassConformance3 // CHECK: superclassConformance3
// CHECK: Requirements: // CHECK: Requirements:
// CHECK-NEXT: T : C2 [explicit @ // CHECK-NEXT: τ_0_0 : C2 [explicit @
// CHECK-NEXT: T : P4 [inherited @ // CHECK-NEXT: τ_0_0 : P4 [inherited @
// CHECK: Canonical generic signature: <τ_0_0 where τ_0_0 : C2> // CHECK: Canonical generic signature: <τ_0_0 where τ_0_0 : C2>
func superclassConformance3<T>(t: T) where T : C, T : P4, T : C2 {} func superclassConformance3<T>(t: T) where T : C, T : P4, T : C2 {}

View File

@@ -85,7 +85,7 @@ struct FloatElement : HasElt {
typealias Element = Float typealias Element = Float
} }
@_specialize(where T == FloatElement) @_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 {} func sameTypeRequirement<T : HasElt>(_ t: T) where T.Element == Float {}
@_specialize(where T == Sub) @_specialize(where T == Sub)