[AST] Break down IdentTypeRepr to different subtypes.

This makes memory allocation for it more efficient and it's more convenient to handle.

Swift SVN r12541
This commit is contained in:
Argyrios Kyrtzidis
2014-01-18 20:19:09 +00:00
parent 20af73f973
commit 84e20a0620
16 changed files with 413 additions and 261 deletions

View File

@@ -135,6 +135,7 @@ public:
return static_cast<ImplClass*>(this)->visit##PARENT(T, \ return static_cast<ImplClass*>(this)->visit##PARENT(T, \
::std::forward<Args>(AA)...); \ ::std::forward<Args>(AA)...); \
} }
#define ABSTRACT_TYPEREPR(CLASS, PARENT) TYPEREPR(CLASS, PARENT)
#include "swift/AST/TypeReprNodes.def" #include "swift/AST/TypeReprNodes.def"
}; };

View File

@@ -144,38 +144,53 @@ private:
friend class TypeRepr; friend class TypeRepr;
}; };
/// \brief A type with identifier components. class ComponentIdentTypeRepr;
/// \brief This is the abstract base class for types with identifier components.
/// \code /// \code
/// Foo.Bar<Gen> /// Foo.Bar<Gen>
/// \endcode /// \endcode
/// FIXME: Investigate splitting into a TypeRepr for each component,
/// so that "Int" does not need an allocation for the components array and the
/// generic arguments info.
class IdentTypeRepr : public TypeRepr { class IdentTypeRepr : public TypeRepr {
protected:
explicit IdentTypeRepr(TypeReprKind K) : TypeRepr(K) {}
public: public:
class Component { /// Copies the provided array and creates a CompoundIdentTypeRepr or just
/// returns the single entry in the array if it contains only one.
static IdentTypeRepr *create(ASTContext &C,
ArrayRef<ComponentIdentTypeRepr *> Components);
class ComponentRange;
inline ComponentRange getComponentRange();
static bool classof(const TypeRepr *T) {
return T->getKind() == TypeReprKind::SimpleIdent ||
T->getKind() == TypeReprKind::GenericIdent ||
T->getKind() == TypeReprKind::CompoundIdent;
}
static bool classof(const IdentTypeRepr *T) { return true; }
};
class ComponentIdentTypeRepr : public IdentTypeRepr {
SourceLoc Loc; SourceLoc Loc;
Identifier Id; Identifier Id;
MutableArrayRef<TypeRepr*> GenericArgs;
/// Value is the decl, type, or module that this refers to. /// Value is the decl, type, or module that this refers to.
/// ///
/// After name binding, the value is set to the decl being referenced, and /// After name binding, the value is set to the decl being referenced.
/// the last entry in the component list is known to be a Type.
/// ///
/// FIXME: Can we sneak the Id into this union? /// FIXME: Can we sneak the Id into this union?
llvm::PointerUnion3<ValueDecl*, Type, Module*> Value; llvm::PointerUnion3<ValueDecl*, Type, Module*> Value;
public: protected:
Component(SourceLoc Loc, Identifier Id, ComponentIdentTypeRepr(TypeReprKind K, SourceLoc Loc, Identifier Id)
MutableArrayRef<TypeRepr*> GenericArgs) : : IdentTypeRepr(K), Loc(Loc), Id(Id) {}
Loc(Loc), Id(Id), GenericArgs(GenericArgs) {}
public:
SourceLoc getIdLoc() const { return Loc; } SourceLoc getIdLoc() const { return Loc; }
Identifier getIdentifier() const { return Id; } Identifier getIdentifier() const { return Id; }
MutableArrayRef<TypeRepr*> getGenericArgs() const { return GenericArgs; }
/// Return true if this Component has been name-bound already. /// Return true if this has been name-bound already.
bool isBound() const { return !Value.isNull(); } bool isBound() const { return !Value.isNull(); }
bool isBoundDecl() const { return Value.is<ValueDecl*>() && isBound(); } bool isBoundDecl() const { return Value.is<ValueDecl*>() && isBound(); }
bool isBoundType() const { return Value.is<Type>() && isBound(); } bool isBoundType() const { return Value.is<Type>() && isBound(); }
@@ -196,37 +211,121 @@ public:
void setValue(Module *M) { Value = M; } void setValue(Module *M) { Value = M; }
void revert() { Value = (ValueDecl*)nullptr; } void revert() { Value = (ValueDecl*)nullptr; }
};
public:
const MutableArrayRef<Component> Components;
IdentTypeRepr(MutableArrayRef<Component> Components)
: TypeRepr(TypeReprKind::Ident), Components(Components) {
assert(!Components.empty());
}
static IdentTypeRepr *create(ASTContext &C, ArrayRef<Component> Components);
static IdentTypeRepr *createSimple(ASTContext &C, SourceLoc Loc,
Identifier Id);
static bool classof(const TypeRepr *T) { static bool classof(const TypeRepr *T) {
return T->getKind() == TypeReprKind::Ident; return T->getKind() == TypeReprKind::SimpleIdent ||
T->getKind() == TypeReprKind::GenericIdent;
} }
static bool classof(const IdentTypeRepr *T) { return true; } static bool classof(const ComponentIdentTypeRepr *T) { return true; }
protected:
void printImpl(ASTPrinter &Printer, const PrintOptions &Opts) const;
};
/// \brief A simple identifier type like "Int".
class SimpleIdentTypeRepr : public ComponentIdentTypeRepr {
public:
SimpleIdentTypeRepr(SourceLoc Loc, Identifier Id)
: ComponentIdentTypeRepr(TypeReprKind::SimpleIdent, Loc, Id) {}
static bool classof(const TypeRepr *T) {
return T->getKind() == TypeReprKind::SimpleIdent;
}
static bool classof(const SimpleIdentTypeRepr *T) { return true; }
private: private:
SourceLoc getStartLocImpl() const { return Components.front().getIdLoc(); } SourceLoc getStartLocImpl() const { return getIdLoc(); }
SourceLoc getEndLocImpl() const { SourceLoc getEndLocImpl() const { return getIdLoc(); }
if (!Components.back().getGenericArgs().empty()) friend class TypeRepr;
return Components.back().getGenericArgs().back()->getEndLoc(); };
return Components.back().getIdLoc();
/// \brief An identifier type with generic arguments.
/// \code
/// Bar<Gen>
/// \endcode
class GenericIdentTypeRepr : public ComponentIdentTypeRepr {
ArrayRef<TypeRepr*> GenericArgs;
public:
GenericIdentTypeRepr(SourceLoc Loc, Identifier Id,
ArrayRef<TypeRepr*> GenericArgs)
: ComponentIdentTypeRepr(TypeReprKind::GenericIdent, Loc, Id),
GenericArgs(GenericArgs) {
assert(!GenericArgs.empty());
} }
ArrayRef<TypeRepr*> getGenericArgs() const { return GenericArgs; }
static bool classof(const TypeRepr *T) {
return T->getKind() == TypeReprKind::GenericIdent;
}
static bool classof(const GenericIdentTypeRepr *T) { return true; }
private:
SourceLoc getStartLocImpl() const { return getIdLoc(); }
SourceLoc getEndLocImpl() const { return GenericArgs.back()->getEndLoc(); }
friend class TypeRepr;
};
/// \brief A type with identifier components.
/// \code
/// Foo.Bar<Gen>
/// \endcode
class CompoundIdentTypeRepr : public IdentTypeRepr {
public:
const ArrayRef<ComponentIdentTypeRepr *> Components;
explicit CompoundIdentTypeRepr(ArrayRef<ComponentIdentTypeRepr *> Components)
: IdentTypeRepr(TypeReprKind::CompoundIdent),
Components(Components) {
assert(Components.size() > 1 &&
"should have just used the single ComponentIdentTypeRepr directly");
}
static bool classof(const TypeRepr *T) {
return T->getKind() == TypeReprKind::CompoundIdent;
}
static bool classof(const CompoundIdentTypeRepr *T) { return true; }
private:
SourceLoc getStartLocImpl() const { return Components.front()->getStartLoc();}
SourceLoc getEndLocImpl() const { return Components.back()->getEndLoc(); }
void printImpl(ASTPrinter &Printer, const PrintOptions &Opts) const; void printImpl(ASTPrinter &Printer, const PrintOptions &Opts) const;
friend class TypeRepr; friend class TypeRepr;
}; };
/// This wraps an IdentTypeRepr and provides an iterator interface for the
/// components (or the single component) it represents.
class IdentTypeRepr::ComponentRange {
IdentTypeRepr *IdT;
public:
explicit ComponentRange(IdentTypeRepr *T) : IdT(T) {}
typedef ComponentIdentTypeRepr * const* iterator;
iterator begin() const {
if (isa<ComponentIdentTypeRepr>(IdT))
return reinterpret_cast<iterator>(&IdT);
return cast<CompoundIdentTypeRepr>(IdT)->Components.begin();
}
iterator end() const {
if (isa<ComponentIdentTypeRepr>(IdT))
return reinterpret_cast<iterator>(&IdT) + 1;
return cast<CompoundIdentTypeRepr>(IdT)->Components.end();
}
bool empty() const { return begin() == end(); }
ComponentIdentTypeRepr *front() const { return *begin(); }
ComponentIdentTypeRepr *back() const { return *(end()-1); }
};
inline IdentTypeRepr::ComponentRange IdentTypeRepr::getComponentRange() {
return ComponentRange(this);
}
/// \brief A function type. /// \brief A function type.
/// \code /// \code
/// Foo -> Bar /// Foo -> Bar
@@ -469,7 +568,9 @@ inline bool TypeRepr::isSimple() const {
case TypeReprKind::Function: case TypeReprKind::Function:
case TypeReprKind::Array: case TypeReprKind::Array:
return false; return false;
case TypeReprKind::Ident: case TypeReprKind::SimpleIdent:
case TypeReprKind::GenericIdent:
case TypeReprKind::CompoundIdent:
case TypeReprKind::Metatype: case TypeReprKind::Metatype:
case TypeReprKind::Named: case TypeReprKind::Named:
case TypeReprKind::Optional: case TypeReprKind::Optional:

View File

@@ -21,9 +21,25 @@
# error Included TypeReprNodes.def without defining TYPEREPR! # error Included TypeReprNodes.def without defining TYPEREPR!
#endif #endif
/// An abstract node is an abstract base class in the hierarchy;
/// it is never a most-derived type, and it does not have an enumerator in
/// TypeReprKind.
///
/// Most metaprograms do not care about abstract classes, so the default
/// is to ignore them.
#ifndef ABSTRACT_TYPEREPR
#define ABSTRACT_TYPEREPR(Id, Parent)
#endif
TYPEREPR(Error, TypeRepr) TYPEREPR(Error, TypeRepr)
TYPEREPR(Attributed, TypeRepr) TYPEREPR(Attributed, TypeRepr)
TYPEREPR(Ident, TypeRepr)
ABSTRACT_TYPEREPR(Ident, TypeRepr)
ABSTRACT_TYPEREPR(ComponentIdent, IdentTypeRepr)
TYPEREPR(SimpleIdent, ComponentIdentTypeRepr)
TYPEREPR(GenericIdent, ComponentIdentTypeRepr)
TYPEREPR(CompoundIdent, IdentTypeRepr)
TYPEREPR(Function, TypeRepr) TYPEREPR(Function, TypeRepr)
TYPEREPR(Array, TypeRepr) TYPEREPR(Array, TypeRepr)
TYPEREPR(Optional, TypeRepr) TYPEREPR(Optional, TypeRepr)
@@ -32,4 +48,5 @@ TYPEREPR(Named, TypeRepr)
TYPEREPR(ProtocolComposition, TypeRepr) TYPEREPR(ProtocolComposition, TypeRepr)
TYPEREPR(Metatype, TypeRepr) TYPEREPR(Metatype, TypeRepr)
#undef ABSTRACT_TYPEREPR
#undef TYPEREPR #undef TYPEREPR

View File

@@ -1515,21 +1515,23 @@ public:
void visitIdentTypeRepr(IdentTypeRepr *T) { void visitIdentTypeRepr(IdentTypeRepr *T) {
printCommon(T, "type_ident"); printCommon(T, "type_ident");
Indent += 2; Indent += 2;
for (auto &comp : T->Components) { for (auto comp : T->getComponentRange()) {
OS << '\n'; OS << '\n';
printCommon(nullptr, "component"); printCommon(nullptr, "component");
OS << " id='" << comp.getIdentifier() << '\''; OS << " id='" << comp->getIdentifier() << '\'';
OS << " bind="; OS << " bind=";
if (comp.isBoundDecl()) OS << "decl"; if (comp->isBoundDecl()) OS << "decl";
else if (comp.isBoundModule()) OS << "module"; else if (comp->isBoundModule()) OS << "module";
else if (comp.isBoundType()) OS << "type"; else if (comp->isBoundType()) OS << "type";
else OS << "none"; else OS << "none";
OS << ')'; OS << ')';
for (auto genArg : comp.getGenericArgs()) { if (auto GenIdT = dyn_cast<GenericIdentTypeRepr>(comp)) {
for (auto genArg : GenIdT->getGenericArgs()) {
OS << '\n'; OS << '\n';
printRec(genArg); printRec(genArg);
} }
} }
}
OS << ')'; OS << ')';
Indent -= 2; Indent -= 2;
} }

View File

@@ -1066,12 +1066,22 @@ bool Traversal::visitAttributedTypeRepr(AttributedTypeRepr *T) {
return false; return false;
} }
bool Traversal::visitIdentTypeRepr(IdentTypeRepr *T) { bool Traversal::visitSimpleIdentTypeRepr(SimpleIdentTypeRepr *T) {
for (auto &comp : T->Components) { return false;
for (auto genArg : comp.getGenericArgs()) { }
bool Traversal::visitGenericIdentTypeRepr(GenericIdentTypeRepr *T) {
for (auto genArg : T->getGenericArgs()) {
if (doIt(genArg)) if (doIt(genArg))
return true; return true;
} }
return false;
}
bool Traversal::visitCompoundIdentTypeRepr(CompoundIdentTypeRepr *T) {
for (auto comp : T->Components) {
if (doIt(comp))
return true;
} }
return false; return false;
} }

View File

@@ -649,17 +649,17 @@ public:
return true; return true;
// For each of the components... // For each of the components...
for (auto &comp : identRepr->Components) { for (auto comp : identRepr->getComponentRange()) {
// If there is no type binding, we don't care. // If there is no type binding, we don't care.
if (!comp.isBoundType()) if (!comp->isBoundType())
continue; continue;
// If there are no generic arguments, we don't care. // If there are no generic arguments, we don't care.
if (comp.getGenericArgs().empty()) if (!isa<GenericIdentTypeRepr>(comp))
continue; continue;
// If it's not a bound generic type, we don't care. // If it's not a bound generic type, we don't care.
auto boundGeneric = comp.getBoundType()->getAs<BoundGenericType>(); auto boundGeneric = comp->getBoundType()->getAs<BoundGenericType>();
if (!boundGeneric) if (!boundGeneric)
continue; continue;

View File

@@ -728,11 +728,10 @@ void NominalTypeDecl::computeType() {
auto selfId = ctx.getIdentifier("Self"); auto selfId = ctx.getIdentifier("Self");
auto selfDecl = new (ctx) GenericTypeParamDecl(proto, selfId, auto selfDecl = new (ctx) GenericTypeParamDecl(proto, selfId,
proto->getLoc(), 0, 0); proto->getLoc(), 0, 0);
IdentTypeRepr::Component protoRef(proto->getLoc(), proto->getName(), { }); auto protoRef = new (ctx) SimpleIdentTypeRepr(proto->getLoc(),
protoRef.setValue(proto); proto->getName());
TypeLoc selfInherited[1] = { protoRef->setValue(proto);
TypeLoc(IdentTypeRepr::create(ctx, protoRef)) TypeLoc selfInherited[1] = { TypeLoc(protoRef) };
};
selfInherited[0].setType(DeclaredTy); selfInherited[0].setType(DeclaredTy);
selfDecl->setInherited(ctx.AllocateCopy(selfInherited)); selfDecl->setInherited(ctx.AllocateCopy(selfInherited));
selfDecl->setImplicit(); selfDecl->setImplicit();

View File

@@ -104,28 +104,27 @@ TypeRepr *CloneVisitor::visitAttributedTypeRepr(AttributedTypeRepr *T) {
return new (Ctx) AttributedTypeRepr(T->getAttrs(), visit(T->getTypeRepr())); return new (Ctx) AttributedTypeRepr(T->getAttrs(), visit(T->getTypeRepr()));
} }
TypeRepr *CloneVisitor::visitIdentTypeRepr(IdentTypeRepr *T) { TypeRepr *CloneVisitor::visitSimpleIdentTypeRepr(SimpleIdentTypeRepr *T) {
// Clone the components. return new (Ctx) SimpleIdentTypeRepr(T->getIdLoc(), T->getIdentifier());
auto componentsMem = (IdentTypeRepr::Component*)
Ctx.Allocate(sizeof(IdentTypeRepr::Component) * T->Components.size(),
alignof(IdentTypeRepr::Component));
MutableArrayRef<IdentTypeRepr::Component> components(componentsMem,
T->Components.size());
for (unsigned i : indices(components)) {
auto &old = T->Components[i];
// Clone the generic arguments.
auto genericArgs = Ctx.Allocate<TypeRepr*>(old.getGenericArgs().size());
for (unsigned argI : indices(genericArgs)) {
genericArgs[argI] = visit(old.getGenericArgs()[argI]);
} }
new (&components[i]) IdentTypeRepr::Component(old.getIdLoc(), TypeRepr *CloneVisitor::visitGenericIdentTypeRepr(GenericIdentTypeRepr *T) {
old.getIdentifier(), // Clone the generic arguments.
auto genericArgs = Ctx.Allocate<TypeRepr*>(T->getGenericArgs().size());
for (unsigned argI : indices(genericArgs)) {
genericArgs[argI] = visit(T->getGenericArgs()[argI]);
}
return new (Ctx) GenericIdentTypeRepr(T->getIdLoc(), T->getIdentifier(),
genericArgs); genericArgs);
} }
return new (Ctx) IdentTypeRepr(components);
TypeRepr *CloneVisitor::visitCompoundIdentTypeRepr(CompoundIdentTypeRepr *T) {
// Clone the components.
auto components = Ctx.Allocate<ComponentIdentTypeRepr*>(T->Components.size());
for (unsigned I : indices(components)) {
components[I] = cast<ComponentIdentTypeRepr>(visit(T->Components[I]));
}
return new (Ctx) CompoundIdentTypeRepr(components);
} }
TypeRepr *CloneVisitor::visitFunctionTypeRepr(FunctionTypeRepr *T) { TypeRepr *CloneVisitor::visitFunctionTypeRepr(FunctionTypeRepr *T) {
@@ -207,14 +206,12 @@ void AttributedTypeRepr::printAttrs(ASTPrinter &Printer) const {
} }
IdentTypeRepr *IdentTypeRepr::create(ASTContext &C, IdentTypeRepr *IdentTypeRepr::create(ASTContext &C,
ArrayRef<Component> Components) { ArrayRef<ComponentIdentTypeRepr *> Components) {
return new (C) IdentTypeRepr(C.AllocateCopy(Components)); assert(!Components.empty());
} if (Components.size() == 1)
return Components.front();
IdentTypeRepr *IdentTypeRepr::createSimple(ASTContext &C, SourceLoc Loc, return new (C) CompoundIdentTypeRepr(C.AllocateCopy(Components));
Identifier Id) {
IdentTypeRepr::Component IdTypeComponent(Loc, Id, {});
return create(C, llvm::makeArrayRef(IdTypeComponent));
} }
static void printGenericArgs(ASTPrinter &Printer, const PrintOptions &Opts, static void printGenericArgs(ASTPrinter &Printer, const PrintOptions &Opts,
@@ -234,26 +231,28 @@ static void printGenericArgs(ASTPrinter &Printer, const PrintOptions &Opts,
Printer << ">"; Printer << ">";
} }
void IdentTypeRepr::printImpl(ASTPrinter &Printer, void ComponentIdentTypeRepr::printImpl(ASTPrinter &Printer,
const PrintOptions &Opts) const { const PrintOptions &Opts) const {
bool isFirst = true; if (Module *Mod = getBoundModule()) {
for (const Component &C : Components) { Printer.printModuleRef(Mod, getIdentifier().str());
if (!isFirst) } else if (Type Ty = getBoundType()) {
Printer << ".";
else
isFirst = false;
if (Module *Mod = C.getBoundModule()) {
Printer.printModuleRef(Mod, C.getIdentifier().str());
} else if (Type Ty = C.getBoundType()) {
if (auto NTD = Ty->getAnyNominal()) if (auto NTD = Ty->getAnyNominal())
Printer.printTypeRef(NTD, C.getIdentifier().str()); Printer.printTypeRef(NTD, getIdentifier().str());
else else
Printer << C.getIdentifier().str(); Printer << getIdentifier().str();
} else { } else {
Printer << C.getIdentifier().str(); Printer << getIdentifier().str();
} }
printGenericArgs(Printer, Opts, C.getGenericArgs()); if (auto GenIdT = dyn_cast<GenericIdentTypeRepr>(this))
printGenericArgs(Printer, Opts, GenIdT->getGenericArgs());
}
void CompoundIdentTypeRepr::printImpl(ASTPrinter &Printer,
const PrintOptions &Opts) const {
Components.front()->print(Printer, Opts);
for (auto C : Components.slice(1)) {
Printer << ".";
C->print(Printer, Opts);
} }
} }

View File

@@ -185,13 +185,11 @@ bool SemaAnnotator::walkToTypeReprPre(TypeRepr *T) {
if (isDone()) if (isDone())
return false; return false;
if (IdentTypeRepr *IdT = dyn_cast<IdentTypeRepr>(T)) { if (auto IdT = dyn_cast<ComponentIdentTypeRepr>(T)) {
for (auto &Comp : IdT->Components) { if (ValueDecl *VD = IdT->getBoundDecl())
if (ValueDecl *VD = Comp.getBoundDecl()) return passReference(VD, IdT->getIdLoc());
return passReference(VD, Comp.getIdLoc()); if (TypeDecl *TyD = getTypeDecl(IdT->getBoundType()))
if (TypeDecl *TyD = getTypeDecl(Comp.getBoundType())) return passReference(TyD, IdT->getIdLoc());
return passReference(TyD, Comp.getIdLoc());
}
} }
return true; return true;
} }

View File

@@ -294,15 +294,13 @@ bool ModelASTWalker::walkToTypeReprPre(TypeRepr *T) {
if (!handleAttrs(AttrT->getAttrs())) if (!handleAttrs(AttrT->getAttrs()))
return false; return false;
} else if (auto IdT = dyn_cast<IdentTypeRepr>(T)) { } else if (auto IdT = dyn_cast<ComponentIdentTypeRepr>(T)) {
for (auto &comp : IdT->Components) {
if (!passNonTokenNode({ SyntaxNodeKind::TypeId, if (!passNonTokenNode({ SyntaxNodeKind::TypeId,
CharSourceRange(comp.getIdLoc(), CharSourceRange(IdT->getIdLoc(),
comp.getIdentifier().getLength()) IdT->getIdentifier().getLength())
})) }))
return false; return false;
} }
}
return true; return true;
} }

View File

@@ -919,7 +919,7 @@ ParserResult<ExtensionDecl> Parser::parseDeclExtension(unsigned Flags,
diag::invalid_diagnostic).isError()) diag::invalid_diagnostic).isError())
return nullptr; return nullptr;
Ty = makeParserErrorResult( Ty = makeParserErrorResult(
IdentTypeRepr::createSimple(Context, NameLoc, ExtensionName)); new (Context) SimpleIdentTypeRepr(NameLoc, ExtensionName));
} }
if (Ty.isNull()) if (Ty.isNull())
return nullptr; return nullptr;

View File

@@ -262,7 +262,7 @@ ParserResult<IdentTypeRepr> Parser::parseTypeIdentifier() {
} }
ParserStatus Status; ParserStatus Status;
SmallVector<IdentTypeRepr::Component, 4> ComponentsR; SmallVector<ComponentIdentTypeRepr *, 4> ComponentsR;
SourceLoc EndLoc; SourceLoc EndLoc;
while (true) { while (true) {
SourceLoc Loc; SourceLoc Loc;
@@ -292,7 +292,13 @@ ParserResult<IdentTypeRepr> Parser::parseTypeIdentifier() {
} }
EndLoc = Loc; EndLoc = Loc;
ComponentsR.push_back({Loc, Name, Context.AllocateCopy(GenericArgs)}); ComponentIdentTypeRepr *CompT;
if (!GenericArgs.empty())
CompT = new (Context) GenericIdentTypeRepr(Loc, Name,
Context.AllocateCopy(GenericArgs));
else
CompT = new (Context) SimpleIdentTypeRepr(Loc, Name);
ComponentsR.push_back(CompT);
} }
// Treat 'Foo.<anything>' as an attempt to write a dotted type // Treat 'Foo.<anything>' as an attempt to write a dotted type
@@ -314,11 +320,11 @@ ParserResult<IdentTypeRepr> Parser::parseTypeIdentifier() {
} }
IdentTypeRepr *ITR = nullptr; IdentTypeRepr *ITR = nullptr;
if (ComponentsR.size() != 0) { if (!ComponentsR.empty()) {
// Lookup element #0 through our current scope chains in case it is some thing // Lookup element #0 through our current scope chains in case it is some thing
// local (this returns null if nothing is found). // local (this returns null if nothing is found).
if (auto Entry = lookupInScope(ComponentsR[0].getIdentifier())) if (auto Entry = lookupInScope(ComponentsR[0]->getIdentifier()))
ComponentsR[0].setValue(Entry); ComponentsR[0]->setValue(Entry);
ITR = IdentTypeRepr::create(Context, ComponentsR); ITR = IdentTypeRepr::create(Context, ComponentsR);
} }

View File

@@ -651,13 +651,13 @@ static void revertDependentTypeLoc(TypeLoc &tl) {
if (!identType) if (!identType)
return true; return true;
for (auto &comp : identType->Components) { for (auto &comp : identType->getComponentRange()) {
// If it's not a bound type, we're done. // If it's not a bound type, we're done.
if (!comp.isBoundType()) if (!comp->isBoundType())
return true; return true;
// If the bound type isn't dependent, there's nothing to do. // If the bound type isn't dependent, there's nothing to do.
auto type = comp.getBoundType(); auto type = comp->getBoundType();
if (!type->isDependentType()) if (!type->isDependentType())
return true; return true;
@@ -666,10 +666,10 @@ static void revertDependentTypeLoc(TypeLoc &tl) {
if (auto genericParamType if (auto genericParamType
= dyn_cast<GenericTypeParamType>(type.getPointer())) { = dyn_cast<GenericTypeParamType>(type.getPointer())) {
// FIXME: Assert that it has a decl. // FIXME: Assert that it has a decl.
comp.setValue(genericParamType->getDecl()); comp->setValue(genericParamType->getDecl());
} else { } else {
// FIXME: Often, we could revert to a decl here. // FIXME: Often, we could revert to a decl here.
comp.revert(); comp->revert();
} }
} }

View File

@@ -78,7 +78,7 @@ namespace {
// Build up an IdentTypeRepr and see what it resolves to. // Build up an IdentTypeRepr and see what it resolves to.
struct ExprToIdentTypeRepr : public ASTVisitor<ExprToIdentTypeRepr, bool> struct ExprToIdentTypeRepr : public ASTVisitor<ExprToIdentTypeRepr, bool>
{ {
SmallVectorImpl<IdentTypeRepr::Component> &components; SmallVectorImpl<ComponentIdentTypeRepr *> &components;
ASTContext &C; ASTContext &C;
ExprToIdentTypeRepr(decltype(components) &components, ASTContext &C) ExprToIdentTypeRepr(decltype(components) &components, ASTContext &C)
@@ -93,8 +93,9 @@ struct ExprToIdentTypeRepr : public ASTVisitor<ExprToIdentTypeRepr, bool>
// Get the declared type. // Get the declared type.
if (auto *td = dyn_cast<TypeDecl>(dre->getDecl())) { if (auto *td = dyn_cast<TypeDecl>(dre->getDecl())) {
components.push_back({dre->getLoc(), dre->getDecl()->getName(), {}}); components.push_back(
components.back().setValue(td); new (C) SimpleIdentTypeRepr(dre->getLoc(), dre->getDecl()->getName()));
components.back()->setValue(td);
return true; return true;
} }
return false; return false;
@@ -105,15 +106,17 @@ struct ExprToIdentTypeRepr : public ASTVisitor<ExprToIdentTypeRepr, bool>
// Add the declared module. // Add the declared module.
auto module = me->getType()->getAs<ModuleType>()->getModule(); auto module = me->getType()->getAs<ModuleType>()->getModule();
components.push_back({me->getLoc(), module->Name, {}}); components.push_back(
components.back().setValue(module); new (C) SimpleIdentTypeRepr(me->getLoc(), module->Name));
components.back()->setValue(module);
return true; return true;
} }
bool visitUnresolvedDeclRefExpr(UnresolvedDeclRefExpr *udre) { bool visitUnresolvedDeclRefExpr(UnresolvedDeclRefExpr *udre) {
assert(components.empty() && "decl ref should be root element of expr"); assert(components.empty() && "decl ref should be root element of expr");
// Track the AST location of the component. // Track the AST location of the component.
components.push_back({udre->getLoc(), udre->getName(), {}}); components.push_back(
new (C) SimpleIdentTypeRepr(udre->getLoc(), udre->getName()));
return true; return true;
} }
@@ -124,7 +127,8 @@ struct ExprToIdentTypeRepr : public ASTVisitor<ExprToIdentTypeRepr, bool>
assert(!components.empty() && "no components before dot expr?!"); assert(!components.empty() && "no components before dot expr?!");
// Track the AST location of the new component. // Track the AST location of the new component.
components.push_back({ude->getLoc(), ude->getName(), {}}); components.push_back(
new (C) SimpleIdentTypeRepr(ude->getLoc(), ude->getName()));
return true; return true;
} }
@@ -139,9 +143,9 @@ struct ExprToIdentTypeRepr : public ASTVisitor<ExprToIdentTypeRepr, bool>
for (auto &arg : use->getUnresolvedParams()) for (auto &arg : use->getUnresolvedParams())
argTypeReprs.push_back(arg.getTypeRepr()); argTypeReprs.push_back(arg.getTypeRepr());
auto origComponent = components.back(); auto origComponent = components.back();
components.back() = {origComponent.getIdLoc(), components.back() = new (C) GenericIdentTypeRepr(origComponent->getIdLoc(),
origComponent.getIdentifier(), origComponent->getIdentifier(),
C.AllocateCopy(argTypeReprs)}; C.AllocateCopy(argTypeReprs));
return true; return true;
} }
@@ -259,12 +263,11 @@ public:
// member name is a member of the enum. // member name is a member of the enum.
Pattern *visitUnresolvedDotExpr(UnresolvedDotExpr *ude) { Pattern *visitUnresolvedDotExpr(UnresolvedDotExpr *ude) {
DependentGenericTypeResolver resolver; DependentGenericTypeResolver resolver;
SmallVector<IdentTypeRepr::Component, 2> components; SmallVector<ComponentIdentTypeRepr *, 2> components;
if (!ExprToIdentTypeRepr(components, TC.Context).visit(ude->getBase())) if (!ExprToIdentTypeRepr(components, TC.Context).visit(ude->getBase()))
return nullptr; return nullptr;
auto *repr auto *repr = IdentTypeRepr::create(TC.Context, components);
= new (TC.Context) IdentTypeRepr(TC.Context.AllocateCopy(components));
// See if the repr resolves to a type. // See if the repr resolves to a type.
Type ty = TC.resolveIdentifierType(DC, repr, Type ty = TC.resolveIdentifierType(DC, repr,
@@ -334,12 +337,13 @@ public:
Pattern *visitCallExpr(CallExpr *ce) { Pattern *visitCallExpr(CallExpr *ce) {
DependentGenericTypeResolver resolver; DependentGenericTypeResolver resolver;
SmallVector<IdentTypeRepr::Component, 2> components; SmallVector<ComponentIdentTypeRepr *, 2> components;
if (!ExprToIdentTypeRepr(components, TC.Context).visit(ce->getFn())) if (!ExprToIdentTypeRepr(components, TC.Context).visit(ce->getFn()))
return nullptr; return nullptr;
auto *repr if (components.empty())
= new (TC.Context) IdentTypeRepr(TC.Context.AllocateCopy(components)); return nullptr;
auto *repr = IdentTypeRepr::create(TC.Context, components);
// See first if the entire repr resolves to a type. // See first if the entire repr resolves to a type.
Type ty = TC.resolveIdentifierType(DC, repr, Type ty = TC.resolveIdentifierType(DC, repr,
@@ -386,11 +390,10 @@ public:
} }
// If we had a single component, try looking up an enum element in context. // If we had a single component, try looking up an enum element in context.
if (repr->Components.size() == 1) { if (auto compId = dyn_cast<ComponentIdentTypeRepr>(repr)) {
auto &backComp = repr->Components.back();
// Try looking up an enum element in context. // Try looking up an enum element in context.
EnumElementDecl *referencedElement EnumElementDecl *referencedElement
= lookupUnqualifiedEnumMemberElement(TC, DC, backComp.getIdentifier()); = lookupUnqualifiedEnumMemberElement(TC, DC, compId->getIdentifier());
if (!referencedElement) if (!referencedElement)
return nullptr; return nullptr;
@@ -402,44 +405,48 @@ public:
auto *subPattern = getSubExprPattern(ce->getArg()); auto *subPattern = getSubExprPattern(ce->getArg());
return new (TC.Context) EnumElementPattern(loc, return new (TC.Context) EnumElementPattern(loc,
SourceLoc(), SourceLoc(),
backComp.getIdLoc(), compId->getIdLoc(),
backComp.getIdentifier(), compId->getIdentifier(),
referencedElement, referencedElement,
subPattern); subPattern);
} }
// Otherwise, see whether we had an enum type as the penultimate component, // Otherwise, see whether we had an enum type as the penultimate component,
// and look up an element inside it. // and look up an element inside it.
if (repr->Components.empty()) auto compoundR = cast<CompoundIdentTypeRepr>(repr);
return nullptr; if (!compoundR->Components.end()[-2]->isBoundType())
if (!repr->Components.end()[-2].isBoundType())
return nullptr; return nullptr;
Type enumTy = repr->Components.end()[-2].getBoundType(); Type enumTy = compoundR->Components.end()[-2]->getBoundType();
auto *enumDecl = dyn_cast_or_null<EnumDecl>(enumTy->getAnyNominal()); auto *enumDecl = dyn_cast_or_null<EnumDecl>(enumTy->getAnyNominal());
if (!enumDecl) if (!enumDecl)
return nullptr; return nullptr;
auto &tailComponent = repr->Components.back(); auto tailComponent = compoundR->Components.back();
EnumElementDecl *referencedElement EnumElementDecl *referencedElement
= lookupEnumMemberElement(TC, enumDecl, enumTy, = lookupEnumMemberElement(TC, enumDecl, enumTy,
tailComponent.getIdentifier()); tailComponent->getIdentifier());
if (!referencedElement) if (!referencedElement)
return nullptr; return nullptr;
// Build a TypeRepr from the head of the full path. // Build a TypeRepr from the head of the full path.
TypeLoc loc; TypeLoc loc;
auto subRepr = new (TC.Context) IdentTypeRepr( IdentTypeRepr *subRepr;
repr->Components.slice(0, repr->Components.size() - 1)); auto headComps =
compoundR->Components.slice(0, compoundR->Components.size() - 1);
if (headComps.size() == 1)
subRepr = headComps.front();
else
subRepr = new (TC.Context) CompoundIdentTypeRepr(headComps);
loc = TypeLoc(subRepr); loc = TypeLoc(subRepr);
loc.setType(enumTy); loc.setType(enumTy);
auto *subPattern = getSubExprPattern(ce->getArg()); auto *subPattern = getSubExprPattern(ce->getArg());
return new (TC.Context) EnumElementPattern(loc, return new (TC.Context) EnumElementPattern(loc,
SourceLoc(), SourceLoc(),
tailComponent.getIdLoc(), tailComponent->getIdLoc(),
tailComponent.getIdentifier(), tailComponent->getIdentifier(),
referencedElement, referencedElement,
subPattern); subPattern);
} }

View File

@@ -244,7 +244,7 @@ Type TypeChecker::applyGenericArguments(Type type,
static Type applyGenericTypeReprArgs(TypeChecker &TC, Type type, SourceLoc loc, static Type applyGenericTypeReprArgs(TypeChecker &TC, Type type, SourceLoc loc,
DeclContext *dc, DeclContext *dc,
MutableArrayRef<TypeRepr *> genericArgs, ArrayRef<TypeRepr *> genericArgs,
GenericTypeResolver *resolver) { GenericTypeResolver *resolver) {
SmallVector<TypeLoc, 8> args; SmallVector<TypeLoc, 8> args;
for (auto tyR : genericArgs) for (auto tyR : genericArgs)
@@ -267,7 +267,7 @@ static void diagnoseUnboundGenericType(TypeChecker &tc, Type ty,SourceLoc loc) {
/// \brief Returns a valid type or ErrorType in case of an error. /// \brief Returns a valid type or ErrorType in case of an error.
static Type resolveTypeDecl(TypeChecker &TC, TypeDecl *typeDecl, SourceLoc loc, static Type resolveTypeDecl(TypeChecker &TC, TypeDecl *typeDecl, SourceLoc loc,
DeclContext *dc, DeclContext *dc,
MutableArrayRef<TypeRepr *> genericArgs, ArrayRef<TypeRepr *> genericArgs,
bool allowUnboundGenerics, bool allowUnboundGenerics,
GenericTypeResolver *resolver) { GenericTypeResolver *resolver) {
TC.validateDecl(typeDecl); TC.validateDecl(typeDecl);
@@ -304,17 +304,17 @@ static Type resolveTypeDecl(TypeChecker &TC, TypeDecl *typeDecl, SourceLoc loc,
static llvm::PointerUnion<Type, Module *> static llvm::PointerUnion<Type, Module *>
resolveIdentTypeComponent(TypeChecker &TC, DeclContext *DC, resolveIdentTypeComponent(TypeChecker &TC, DeclContext *DC,
MutableArrayRef<IdentTypeRepr::Component> components, ArrayRef<ComponentIdentTypeRepr *> components,
bool allowUnboundGenerics, bool allowUnboundGenerics,
bool diagnoseErrors, bool diagnoseErrors,
GenericTypeResolver *resolver) { GenericTypeResolver *resolver) {
auto &comp = components.back(); auto &comp = components.back();
if (!comp.isBound()) { if (!comp->isBound()) {
auto parentComps = components.slice(0, components.size()-1); auto parentComps = components.slice(0, components.size()-1);
if (parentComps.empty()) { if (parentComps.empty()) {
// Resolve the first component, which is the only one that requires // Resolve the first component, which is the only one that requires
// unqualified name lookup. // unqualified name lookup.
UnqualifiedLookup Globals(comp.getIdentifier(), DC, &TC, comp.getIdLoc(), UnqualifiedLookup Globals(comp->getIdentifier(), DC, &TC,comp->getIdLoc(),
/*TypeLookup*/true); /*TypeLookup*/true);
// Process the names we found. // Process the names we found.
@@ -331,7 +331,7 @@ resolveIdentTypeComponent(TypeChecker &TC, DeclContext *DC,
// Save this result. // Save this result.
current = result.getNamedModule(); current = result.getNamedModule();
comp.setValue(result.getNamedModule()); comp->setValue(result.getNamedModule());
continue; continue;
} }
@@ -340,19 +340,22 @@ resolveIdentTypeComponent(TypeChecker &TC, DeclContext *DC,
if (!typeDecl) if (!typeDecl)
continue; continue;
Type type = resolveTypeDecl(TC, typeDecl, comp.getIdLoc(), ArrayRef<TypeRepr *> genericArgs;
DC, comp.getGenericArgs(), if (auto genComp = dyn_cast<GenericIdentTypeRepr>(comp))
genericArgs = genComp->getGenericArgs();
Type type = resolveTypeDecl(TC, typeDecl, comp->getIdLoc(),
DC, genericArgs,
allowUnboundGenerics, allowUnboundGenerics,
resolver); resolver);
if (type->is<ErrorType>()) { if (type->is<ErrorType>()) {
comp.setValue(type); comp->setValue(type);
return type; return type;
} }
// If this is the first result we found, record it. // If this is the first result we found, record it.
if (current.isNull()) { if (current.isNull()) {
current = type; current = type;
comp.setValue(type); comp->setValue(type);
continue; continue;
} }
@@ -369,13 +372,13 @@ resolveIdentTypeComponent(TypeChecker &TC, DeclContext *DC,
// If we found nothing, complain and fail. // If we found nothing, complain and fail.
if (current.isNull()) { if (current.isNull()) {
if (diagnoseErrors) if (diagnoseErrors)
TC.diagnose(comp.getIdLoc(), components.size() == 1 ? TC.diagnose(comp->getIdLoc(), components.size() == 1 ?
diag::use_undeclared_type : diag::unknown_name_in_type, diag::use_undeclared_type : diag::unknown_name_in_type,
comp.getIdentifier()) comp->getIdentifier())
.highlight(SourceRange(comp.getIdLoc(), .highlight(SourceRange(comp->getIdLoc(),
components.back().getIdLoc())); components.back()->getIdLoc()));
Type ty = ErrorType::get(TC.Context); Type ty = ErrorType::get(TC.Context);
comp.setValue(ty); comp->setValue(ty);
return ty; return ty;
} }
@@ -383,19 +386,19 @@ resolveIdentTypeComponent(TypeChecker &TC, DeclContext *DC,
// FIXME: We could recover by looking at later components. // FIXME: We could recover by looking at later components.
if (isAmbiguous) { if (isAmbiguous) {
if (diagnoseErrors) { if (diagnoseErrors) {
TC.diagnose(comp.getIdLoc(), diag::ambiguous_type_base, TC.diagnose(comp->getIdLoc(), diag::ambiguous_type_base,
comp.getIdentifier()) comp->getIdentifier())
.highlight(SourceRange(comp.getIdLoc(), .highlight(SourceRange(comp->getIdLoc(),
components.back().getIdLoc())); components.back()->getIdLoc()));
for (auto Result : Globals.Results) { for (auto Result : Globals.Results) {
if (Globals.Results[0].hasValueDecl()) if (Globals.Results[0].hasValueDecl())
TC.diagnose(Result.getValueDecl(), diag::found_candidate); TC.diagnose(Result.getValueDecl(), diag::found_candidate);
else else
TC.diagnose(comp.getIdLoc(), diag::found_candidate); TC.diagnose(comp->getIdLoc(), diag::found_candidate);
} }
} }
Type ty = ErrorType::get(TC.Context); Type ty = ErrorType::get(TC.Context);
comp.setValue(ty); comp->setValue(ty);
return ty; return ty;
} }
@@ -408,8 +411,8 @@ resolveIdentTypeComponent(TypeChecker &TC, DeclContext *DC,
// If the last resolved component is a type, perform member type lookup. // If the last resolved component is a type, perform member type lookup.
if (parent.is<Type>()) { if (parent.is<Type>()) {
// FIXME: Want the end of the back range. // FIXME: Want the end of the back range.
SourceRange parentRange(parentComps.front().getIdLoc(), SourceRange parentRange(parentComps.front()->getIdLoc(),
parentComps.back().getIdLoc()); parentComps.back()->getIdLoc());
auto parentTy = parent.get<Type>(); auto parentTy = parent.get<Type>();
if (parentTy->is<ErrorType>()) if (parentTy->is<ErrorType>())
@@ -422,36 +425,36 @@ resolveIdentTypeComponent(TypeChecker &TC, DeclContext *DC,
Type memberType = resolver->resolveDependentMemberType( Type memberType = resolver->resolveDependentMemberType(
parentTy, DC, parentTy, DC,
parentRange, parentRange,
comp.getIdentifier(), comp->getIdentifier(),
comp.getIdLoc()); comp->getIdLoc());
assert(memberType && "Received null dependent member type"); assert(memberType && "Received null dependent member type");
if (!comp.getGenericArgs().empty() && !memberType->is<ErrorType>()) { if (isa<GenericIdentTypeRepr>(comp) && !memberType->is<ErrorType>()) {
// FIXME: Highlight generic arguments and introduce a Fix-It to // FIXME: Highlight generic arguments and introduce a Fix-It to
// remove them. // remove them.
if (diagnoseErrors) if (diagnoseErrors)
TC.diagnose(comp.getIdLoc(), diag::not_a_generic_type, memberType); TC.diagnose(comp->getIdLoc(), diag::not_a_generic_type, memberType);
// Drop the arguments. // Drop the arguments.
} }
comp.setValue(memberType); comp->setValue(memberType);
return memberType; return memberType;
} }
// Look for member types with the given name. // Look for member types with the given name.
auto memberTypes = TC.lookupMemberType(parentTy, comp.getIdentifier(), auto memberTypes = TC.lookupMemberType(parentTy, comp->getIdentifier(),
DC); DC);
// If we didn't find anything, complain. // If we didn't find anything, complain.
// FIXME: Typo correction! // FIXME: Typo correction!
if (!memberTypes) { if (!memberTypes) {
if (diagnoseErrors) if (diagnoseErrors)
TC.diagnose(comp.getIdLoc(), diag::invalid_member_type, TC.diagnose(comp->getIdLoc(), diag::invalid_member_type,
comp.getIdentifier(), parent.get<Type>()) comp->getIdentifier(), parent.get<Type>())
.highlight(parentRange); .highlight(parentRange);
Type ty = ErrorType::get(TC.Context); Type ty = ErrorType::get(TC.Context);
comp.setValue(ty); comp->setValue(ty);
return ty; return ty;
} }
@@ -462,47 +465,48 @@ resolveIdentTypeComponent(TypeChecker &TC, DeclContext *DC,
if (diagnoseErrors) if (diagnoseErrors)
TC.diagnoseAmbiguousMemberType(parent.get<Type>(), TC.diagnoseAmbiguousMemberType(parent.get<Type>(),
parentRange, parentRange,
comp.getIdentifier(), comp->getIdentifier(),
comp.getIdLoc(), comp->getIdLoc(),
memberTypes); memberTypes);
Type ty = ErrorType::get(TC.Context); Type ty = ErrorType::get(TC.Context);
comp.setValue(ty); comp->setValue(ty);
return ty; return ty;
} }
auto memberType = memberTypes.back().second; auto memberType = memberTypes.back().second;
// If there are generic arguments, apply them now. // If there are generic arguments, apply them now.
if (!comp.getGenericArgs().empty()) if (auto genComp = dyn_cast<GenericIdentTypeRepr>(comp))
memberType = applyGenericTypeReprArgs(TC, memberType, comp.getIdLoc(), memberType = applyGenericTypeReprArgs(TC, memberType,
DC, comp.getGenericArgs(), genComp->getIdLoc(),
DC, genComp->getGenericArgs(),
resolver); resolver);
comp.setValue(memberType); comp->setValue(memberType);
return memberType; return memberType;
} }
// Lookup into a module. // Lookup into a module.
auto module = parent.get<Module *>(); auto module = parent.get<Module *>();
LookupTypeResult foundModuleTypes = LookupTypeResult foundModuleTypes =
TC.lookupMemberType(ModuleType::get(module), comp.getIdentifier(), DC); TC.lookupMemberType(ModuleType::get(module), comp->getIdentifier(), DC);
// If we didn't find a type, complain. // If we didn't find a type, complain.
if (!foundModuleTypes) { if (!foundModuleTypes) {
// FIXME: Fully-qualified module name? // FIXME: Fully-qualified module name?
if (diagnoseErrors) if (diagnoseErrors)
TC.diagnose(comp.getIdLoc(), diag::no_module_type, comp.getIdentifier(), TC.diagnose(comp->getIdLoc(), diag::no_module_type,
module->Name); comp->getIdentifier(), module->Name);
Type ty = ErrorType::get(TC.Context); Type ty = ErrorType::get(TC.Context);
comp.setValue(ty); comp->setValue(ty);
return ty; return ty;
} }
// If lookup was ambiguous, complain. // If lookup was ambiguous, complain.
if (foundModuleTypes.isAmbiguous()) { if (foundModuleTypes.isAmbiguous()) {
if (diagnoseErrors) { if (diagnoseErrors) {
TC.diagnose(comp.getIdLoc(), diag::ambiguous_module_type, TC.diagnose(comp->getIdLoc(), diag::ambiguous_module_type,
comp.getIdentifier(), module->Name); comp->getIdentifier(), module->Name);
for (auto foundType : foundModuleTypes) { for (auto foundType : foundModuleTypes) {
// Only consider type declarations. // Only consider type declarations.
auto typeDecl = foundType.first; auto typeDecl = foundType.first;
@@ -514,44 +518,48 @@ resolveIdentTypeComponent(TypeChecker &TC, DeclContext *DC,
} }
} }
Type ty = ErrorType::get(TC.Context); Type ty = ErrorType::get(TC.Context);
comp.setValue(ty); comp->setValue(ty);
return ty; return ty;
} }
Type foundType = foundModuleTypes[0].second; Type foundType = foundModuleTypes[0].second;
// If there are generic arguments, apply them now. // If there are generic arguments, apply them now.
if (!comp.getGenericArgs().empty()) { if (auto genComp = dyn_cast<GenericIdentTypeRepr>(comp)) {
foundType = applyGenericTypeReprArgs(TC, foundType, comp.getIdLoc(), foundType = applyGenericTypeReprArgs(TC, foundType, genComp->getIdLoc(),
DC, comp.getGenericArgs(), DC, genComp->getGenericArgs(),
resolver); resolver);
} }
comp.setValue(foundType); comp->setValue(foundType);
} }
} }
assert(comp.isBound()); assert(comp->isBound());
if (Type ty = comp.getBoundType()) if (Type ty = comp->getBoundType())
return ty; return ty;
if (Module *mod = comp.getBoundModule()) if (Module *mod = comp->getBoundModule())
return mod; return mod;
ValueDecl *VD = comp.getBoundDecl(); ValueDecl *VD = comp->getBoundDecl();
auto typeDecl = dyn_cast<TypeDecl>(VD); auto typeDecl = dyn_cast<TypeDecl>(VD);
if (!typeDecl) { if (!typeDecl) {
if (diagnoseErrors) { if (diagnoseErrors) {
TC.diagnose(comp.getIdLoc(), diag::use_non_type_value, VD->getName()); TC.diagnose(comp->getIdLoc(), diag::use_non_type_value, VD->getName());
TC.diagnose(VD, diag::use_non_type_value_prev, VD->getName()); TC.diagnose(VD, diag::use_non_type_value_prev, VD->getName());
} }
Type ty = ErrorType::get(TC.Context); Type ty = ErrorType::get(TC.Context);
comp.setValue(ty); comp->setValue(ty);
return ty; return ty;
} }
Type type = resolveTypeDecl(TC, typeDecl, comp.getIdLoc(), nullptr, ArrayRef<TypeRepr *> genericArgs;
comp.getGenericArgs(), allowUnboundGenerics, if (auto genComp = dyn_cast<GenericIdentTypeRepr>(comp))
genericArgs = genComp->getGenericArgs();
Type type = resolveTypeDecl(TC, typeDecl, comp->getIdLoc(), nullptr,
genericArgs, allowUnboundGenerics,
resolver); resolver);
comp.setValue(type); comp->setValue(type);
return type; return type;
} }
@@ -563,17 +571,20 @@ Type TypeChecker::resolveIdentifierType(DeclContext *DC,
GenericTypeResolver *resolver) { GenericTypeResolver *resolver) {
assert(resolver && "Missing generic type resolver"); assert(resolver && "Missing generic type resolver");
auto ComponentRange = IdType->getComponentRange();
auto Components = llvm::makeArrayRef(ComponentRange.begin(),
ComponentRange.end());
llvm::PointerUnion<Type, Module *> llvm::PointerUnion<Type, Module *>
result = resolveIdentTypeComponent(*this, DC, IdType->Components, result = resolveIdentTypeComponent(*this, DC, Components,
allowUnboundGenerics, allowUnboundGenerics,
diagnoseErrors, diagnoseErrors,
resolver); resolver);
if (auto mod = result.dyn_cast<Module*>()) { if (auto mod = result.dyn_cast<Module*>()) {
if (diagnoseErrors) if (diagnoseErrors)
diagnose(IdType->Components.back().getIdLoc(), diagnose(Components.back()->getIdLoc(),
diag::use_module_as_type, mod->Name); diag::use_module_as_type, mod->Name);
Type ty = ErrorType::get(Context); Type ty = ErrorType::get(Context);
IdType->Components.back().setValue(ty); Components.back()->setValue(ty);
return ty; return ty;
} }
@@ -667,7 +678,9 @@ Type TypeResolver::resolveType(TypeRepr *repr, bool isSILType) {
case TypeReprKind::Attributed: case TypeReprKind::Attributed:
return resolveAttributedType(cast<AttributedTypeRepr>(repr), isSILType); return resolveAttributedType(cast<AttributedTypeRepr>(repr), isSILType);
case TypeReprKind::Ident: case TypeReprKind::SimpleIdent:
case TypeReprKind::GenericIdent:
case TypeReprKind::CompoundIdent:
return TC.resolveIdentifierType(DC, cast<IdentTypeRepr>(repr), return TC.resolveIdentifierType(DC, cast<IdentTypeRepr>(repr),
AllowUnboundGenerics, AllowUnboundGenerics,
/*diagnoseErrors*/ true, /*diagnoseErrors*/ true,

View File

@@ -418,12 +418,13 @@ static bool mayConformToKnownProtocol(const DeclTy *D) {
if (!identRepr) if (!identRepr)
continue; continue;
const IdentTypeRepr::Component &lastID = identRepr->Components.back(); auto lastSimpleID =
if (!lastID.getGenericArgs().empty()) dyn_cast<SimpleIdentTypeRepr>(identRepr->getComponentRange().back());
if (!lastSimpleID)
continue; continue;
bool matchesKnownProtocol = bool matchesKnownProtocol =
llvm::StringSwitch<bool>(lastID.getIdentifier().str()) llvm::StringSwitch<bool>(lastSimpleID->getIdentifier().str())
#define PROTOCOL(Name) \ #define PROTOCOL(Name) \
.Case(#Name, true) .Case(#Name, true)
#include "swift/AST/KnownProtocols.def" #include "swift/AST/KnownProtocols.def"