mirror of
https://github.com/apple/swift.git
synced 2025-12-21 12:14:44 +01:00
Add GenericSubscriptExpr to represent subscripting into a generic type.
Swift SVN r2336
This commit is contained in:
@@ -816,7 +816,7 @@ public:
|
|||||||
SourceLoc RBracketLoc, SubscriptDecl *D);
|
SourceLoc RBracketLoc, SubscriptDecl *D);
|
||||||
|
|
||||||
/// getBase - Retrieve the base of the subscript expression, i.e., the
|
/// getBase - Retrieve the base of the subscript expression, i.e., the
|
||||||
/// value being indexed. This value has existential type.
|
/// value being indexed. This value has archetype type.
|
||||||
Expr *getBase() const { return Base; }
|
Expr *getBase() const { return Base; }
|
||||||
void setBase(Expr *E) { Base = E; }
|
void setBase(Expr *E) { Base = E; }
|
||||||
|
|
||||||
@@ -843,7 +843,49 @@ public:
|
|||||||
return E->getKind() == ExprKind::ArchetypeSubscript;
|
return E->getKind() == ExprKind::ArchetypeSubscript;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/// GenericSubscriptExpr - Subscripting expressions like a[i] that refer to
|
||||||
|
/// an element within a container, where the container is a generic type.
|
||||||
|
class GenericSubscriptExpr : public Expr {
|
||||||
|
SubscriptDecl *D;
|
||||||
|
SourceRange Brackets;
|
||||||
|
Expr *Base;
|
||||||
|
Expr *Index;
|
||||||
|
|
||||||
|
public:
|
||||||
|
GenericSubscriptExpr(Expr *Base, SourceLoc LBracketLoc, Expr *Index,
|
||||||
|
SourceLoc RBracketLoc, SubscriptDecl *D);
|
||||||
|
|
||||||
|
/// getBase - Retrieve the base of the subscript expression, i.e., the
|
||||||
|
/// value being indexed. This value has generic type.
|
||||||
|
Expr *getBase() const { return Base; }
|
||||||
|
void setBase(Expr *E) { Base = E; }
|
||||||
|
|
||||||
|
/// getIndex - Retrieve the index of the subscript expression, i.e., the
|
||||||
|
/// "offset" into the base value.
|
||||||
|
Expr *getIndex() const { return Index; }
|
||||||
|
void setIndex(Expr *E) { Index = E; }
|
||||||
|
|
||||||
|
/// getDecl - Retrieve the subscript declaration that this subscripting
|
||||||
|
/// operation refers to.
|
||||||
|
SubscriptDecl *getDecl() const { return D; }
|
||||||
|
void setDecl(SubscriptDecl *D) { this->D = D; }
|
||||||
|
|
||||||
|
SourceLoc getLBracketLoc() const { return Brackets.Start; }
|
||||||
|
SourceLoc getRBracketLoc() const { return Brackets.End; }
|
||||||
|
|
||||||
|
SourceRange getSourceRange() const {
|
||||||
|
return SourceRange(Base->getStartLoc(), Brackets.End);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Implement isa/cast/dyncast/etc.
|
||||||
|
static bool classof(const GenericSubscriptExpr *) { return true; }
|
||||||
|
static bool classof(const Expr *E) {
|
||||||
|
return E->getKind() == ExprKind::GenericSubscript;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
/// OverloadedSubscriptExpr - Subscripting expressions like a[i] that refer to
|
/// OverloadedSubscriptExpr - Subscripting expressions like a[i] that refer to
|
||||||
/// an element within a container, for which overload resolution has found
|
/// an element within a container, for which overload resolution has found
|
||||||
/// multiple potential subscript declarations that may apply.
|
/// multiple potential subscript declarations that may apply.
|
||||||
|
|||||||
@@ -74,6 +74,7 @@ EXPR(Subscript, Expr)
|
|||||||
UNCHECKED_EXPR(OverloadedSubscript, Expr)
|
UNCHECKED_EXPR(OverloadedSubscript, Expr)
|
||||||
EXPR(ExistentialSubscript, Expr)
|
EXPR(ExistentialSubscript, Expr)
|
||||||
EXPR(ArchetypeSubscript, Expr)
|
EXPR(ArchetypeSubscript, Expr)
|
||||||
|
EXPR(GenericSubscript, Expr)
|
||||||
EXPR(TupleElement, Expr)
|
EXPR(TupleElement, Expr)
|
||||||
ABSTRACT_EXPR(Capturing, Expr)
|
ABSTRACT_EXPR(Capturing, Expr)
|
||||||
EXPR(Func, CapturingExpr)
|
EXPR(Func, CapturingExpr)
|
||||||
|
|||||||
@@ -169,6 +169,19 @@ class Traversal : public ASTVisitor<Traversal, Expr*, Stmt*> {
|
|||||||
|
|
||||||
return E;
|
return E;
|
||||||
}
|
}
|
||||||
|
Expr *visitGenericSubscriptExpr(GenericSubscriptExpr *E) {
|
||||||
|
if (Expr *Base = doIt(E->getBase()))
|
||||||
|
E->setBase(Base);
|
||||||
|
else
|
||||||
|
return nullptr;
|
||||||
|
|
||||||
|
if (Expr *Index = doIt(E->getIndex()))
|
||||||
|
E->setIndex(Index);
|
||||||
|
else
|
||||||
|
return nullptr;
|
||||||
|
|
||||||
|
return E;
|
||||||
|
}
|
||||||
Expr *visitOverloadedSubscriptExpr(OverloadedSubscriptExpr *E) { return E; }
|
Expr *visitOverloadedSubscriptExpr(OverloadedSubscriptExpr *E) { return E; }
|
||||||
Expr *visitUnresolvedDotExpr(UnresolvedDotExpr *E) {
|
Expr *visitUnresolvedDotExpr(UnresolvedDotExpr *E) {
|
||||||
if (!E->getBase())
|
if (!E->getBase())
|
||||||
|
|||||||
@@ -254,6 +254,15 @@ ArchetypeSubscriptExpr(Expr *Base, SourceLoc LBracketLoc, Expr *Index,
|
|||||||
"use SubscriptExpr for non-archetype type subscript");
|
"use SubscriptExpr for non-archetype type subscript");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
GenericSubscriptExpr::
|
||||||
|
GenericSubscriptExpr(Expr *Base, SourceLoc LBracketLoc, Expr *Index,
|
||||||
|
SourceLoc RBracketLoc, SubscriptDecl *D)
|
||||||
|
: Expr(ExprKind::GenericSubscript, D? D->getElementType() : Type()),
|
||||||
|
D(D), Brackets(LBracketLoc, RBracketLoc), Base(Base), Index(Index) {
|
||||||
|
assert(Base->getType()->getRValueType()->is<BoundGenericType>() &&
|
||||||
|
"use SubscriptExpr for non-generic type subscript");
|
||||||
|
}
|
||||||
|
|
||||||
Expr *OverloadedSubscriptExpr::createWithCopy(Expr *Base,
|
Expr *OverloadedSubscriptExpr::createWithCopy(Expr *Base,
|
||||||
ArrayRef<ValueDecl*> Decls,
|
ArrayRef<ValueDecl*> Decls,
|
||||||
SourceLoc LBracketLoc,
|
SourceLoc LBracketLoc,
|
||||||
@@ -274,6 +283,11 @@ Expr *OverloadedSubscriptExpr::createWithCopy(Expr *Base,
|
|||||||
RBracketLoc,
|
RBracketLoc,
|
||||||
cast<SubscriptDecl>(Decls[0]));
|
cast<SubscriptDecl>(Decls[0]));
|
||||||
|
|
||||||
|
if (ContainerTy->is<BoundGenericType>())
|
||||||
|
return new (C) GenericSubscriptExpr(Base, LBracketLoc, Index,
|
||||||
|
RBracketLoc,
|
||||||
|
cast<SubscriptDecl>(Decls[0]));
|
||||||
|
|
||||||
return new (C) SubscriptExpr(Base, LBracketLoc, Index, RBracketLoc,
|
return new (C) SubscriptExpr(Base, LBracketLoc, Index, RBracketLoc,
|
||||||
cast<SubscriptDecl>(Decls[0]));
|
cast<SubscriptDecl>(Decls[0]));
|
||||||
}
|
}
|
||||||
@@ -505,6 +519,14 @@ public:
|
|||||||
printRec(E->getIndex());
|
printRec(E->getIndex());
|
||||||
OS << ')';
|
OS << ')';
|
||||||
}
|
}
|
||||||
|
void visitGenericSubscriptExpr(GenericSubscriptExpr *E) {
|
||||||
|
printCommon(E, "generic_subscript_expr");
|
||||||
|
OS << '\n';
|
||||||
|
printRec(E->getBase());
|
||||||
|
OS << '\n';
|
||||||
|
printRec(E->getIndex());
|
||||||
|
OS << ')';
|
||||||
|
}
|
||||||
void visitOverloadedSubscriptExpr(OverloadedSubscriptExpr *E) {
|
void visitOverloadedSubscriptExpr(OverloadedSubscriptExpr *E) {
|
||||||
printCommon(E, "overloaded_subscript_expr");
|
printCommon(E, "overloaded_subscript_expr");
|
||||||
OS << '\n';
|
OS << '\n';
|
||||||
|
|||||||
@@ -228,10 +228,17 @@ namespace {
|
|||||||
|
|
||||||
void visitExistentialSubscriptExpr(ExistentialSubscriptExpr *E) {
|
void visitExistentialSubscriptExpr(ExistentialSubscriptExpr *E) {
|
||||||
IGF.unimplemented(E->getLBracketLoc(), "existential subscripts");
|
IGF.unimplemented(E->getLBracketLoc(), "existential subscripts");
|
||||||
|
IGF.emitFakeExplosion(IGF.getFragileTypeInfo(E->getType()), Out);
|
||||||
}
|
}
|
||||||
|
|
||||||
void visitArchetypeSubscriptExpr(ArchetypeSubscriptExpr *E) {
|
void visitArchetypeSubscriptExpr(ArchetypeSubscriptExpr *E) {
|
||||||
IGF.unimplemented(E->getLBracketLoc(), "archetype subscripts");
|
IGF.unimplemented(E->getLBracketLoc(), "archetype subscripts");
|
||||||
|
IGF.emitFakeExplosion(IGF.getFragileTypeInfo(E->getType()), Out);
|
||||||
|
}
|
||||||
|
|
||||||
|
void visitGenericSubscriptExpr(GenericSubscriptExpr *E) {
|
||||||
|
IGF.unimplemented(E->getLBracketLoc(), "generic subscripts");
|
||||||
|
IGF.emitFakeExplosion(IGF.getFragileTypeInfo(E->getType()), Out);
|
||||||
}
|
}
|
||||||
|
|
||||||
void visitTupleShuffleExpr(TupleShuffleExpr *E) {
|
void visitTupleShuffleExpr(TupleShuffleExpr *E) {
|
||||||
@@ -478,6 +485,11 @@ namespace {
|
|||||||
return LValue();
|
return LValue();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
LValue visitGenericSubscriptExpr(GenericSubscriptExpr *E) {
|
||||||
|
IGF.unimplemented(E->getLBracketLoc(), "generic subscripts");
|
||||||
|
return LValue();
|
||||||
|
}
|
||||||
|
|
||||||
LValue visitArchetypeMemberRefExpr(ArchetypeMemberRefExpr *E) {
|
LValue visitArchetypeMemberRefExpr(ArchetypeMemberRefExpr *E) {
|
||||||
IGF.unimplemented(E->getLoc(), "archetype member reference");
|
IGF.unimplemented(E->getLoc(), "archetype member reference");
|
||||||
return LValue();
|
return LValue();
|
||||||
@@ -614,6 +626,7 @@ namespace {
|
|||||||
NON_LOCATEABLE(SubscriptExpr);
|
NON_LOCATEABLE(SubscriptExpr);
|
||||||
NON_LOCATEABLE(ExistentialSubscriptExpr)
|
NON_LOCATEABLE(ExistentialSubscriptExpr)
|
||||||
NON_LOCATEABLE(ArchetypeSubscriptExpr)
|
NON_LOCATEABLE(ArchetypeSubscriptExpr)
|
||||||
|
NON_LOCATEABLE(GenericSubscriptExpr)
|
||||||
#undef NON_LOCATEABLE
|
#undef NON_LOCATEABLE
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -275,6 +275,9 @@ public:
|
|||||||
CoercedResult visitArchetypeSubscriptExpr(ArchetypeSubscriptExpr *E) {
|
CoercedResult visitArchetypeSubscriptExpr(ArchetypeSubscriptExpr *E) {
|
||||||
return unchanged(E);
|
return unchanged(E);
|
||||||
}
|
}
|
||||||
|
CoercedResult visitGenericSubscriptExpr(GenericSubscriptExpr *E) {
|
||||||
|
return unchanged(E);
|
||||||
|
}
|
||||||
CoercedResult visitOverloadedSubscriptExpr(OverloadedSubscriptExpr *E) {
|
CoercedResult visitOverloadedSubscriptExpr(OverloadedSubscriptExpr *E) {
|
||||||
Type BaseTy = E->getBase()->getType()->getRValueType();
|
Type BaseTy = E->getBase()->getType()->getRValueType();
|
||||||
|
|
||||||
|
|||||||
@@ -183,6 +183,17 @@ Expr *TypeChecker::semaSubscriptExpr(SubscriptExpr *SE) {
|
|||||||
Sub));
|
Sub));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (BaseTy->is<BoundGenericType>()) {
|
||||||
|
// We picked a subscript operator in a generic type; create the
|
||||||
|
// appropriate AST node.
|
||||||
|
return semaSubscriptExpr(
|
||||||
|
new (Context) GenericSubscriptExpr(SE->getBase(),
|
||||||
|
SE->getLBracketLoc(),
|
||||||
|
SE->getIndex(),
|
||||||
|
SE->getRBracketLoc(),
|
||||||
|
Sub));
|
||||||
|
}
|
||||||
|
|
||||||
// Simple case: perform semantic analysis now that we have the declaration.
|
// Simple case: perform semantic analysis now that we have the declaration.
|
||||||
SE->setDecl(Sub);
|
SE->setDecl(Sub);
|
||||||
return semaSubscriptExpr(SE);
|
return semaSubscriptExpr(SE);
|
||||||
@@ -376,6 +387,60 @@ Expr *TypeChecker::semaSubscriptExpr(ArchetypeSubscriptExpr *E) {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Expr *TypeChecker::semaSubscriptExpr(GenericSubscriptExpr *E) {
|
||||||
|
// Propagate errors up.
|
||||||
|
if (E->getDecl()->getType()->is<ErrorType>()) {
|
||||||
|
E->setType(ErrorType::get(Context));
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Ensure that the base is an lvalue, materializing it if is not an
|
||||||
|
// lvalue yet.
|
||||||
|
Type ContainerTy = E->getBase()->getType()->getRValueType();
|
||||||
|
|
||||||
|
if (Expr *Base = coerceObjectArgument(E->getBase(), ContainerTy))
|
||||||
|
E->setBase(Base);
|
||||||
|
else {
|
||||||
|
E->setType(ErrorType::get(Context));
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
SubscriptDecl *SubDecl = E->getDecl();
|
||||||
|
|
||||||
|
// Determine the index type.
|
||||||
|
Type IndexType = SubDecl->getIndices()->getType();
|
||||||
|
IndexType = substMemberTypeWithBase(IndexType, ContainerTy);
|
||||||
|
if (!IndexType)
|
||||||
|
return nullptr;
|
||||||
|
|
||||||
|
// Coerce the index argument to the index type.
|
||||||
|
Expr *Index = coerceToType(E->getIndex(), IndexType);
|
||||||
|
if (!Index) {
|
||||||
|
diagnose(E->getBase()->getLoc(), diag::while_converting_subscript_index,
|
||||||
|
IndexType)
|
||||||
|
<< E->getIndex()->getSourceRange();
|
||||||
|
E->setType(ErrorType::get(Context));
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
E->setIndex(Index);
|
||||||
|
|
||||||
|
// Determine the value type.
|
||||||
|
Type ValueType = SubDecl->getElementType();
|
||||||
|
ValueType = substMemberTypeWithBase(ValueType, ContainerTy);
|
||||||
|
if (!ValueType) {
|
||||||
|
E->setType(ErrorType::get(Context));
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
ValueType = LValueType::get(ValueType,
|
||||||
|
LValueType::Qual::DefaultForMemberAccess,
|
||||||
|
Context);
|
||||||
|
E->setType(ValueType);
|
||||||
|
return E;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/// \brief Determine whether this expression refers to a type directly (ignoring
|
/// \brief Determine whether this expression refers to a type directly (ignoring
|
||||||
/// parentheses), rather than some variable of metatype type.
|
/// parentheses), rather than some variable of metatype type.
|
||||||
static bool isDirectTypeReference(Expr *E) {
|
static bool isDirectTypeReference(Expr *E) {
|
||||||
@@ -890,6 +955,9 @@ public:
|
|||||||
Expr *visitArchetypeSubscriptExpr(ArchetypeSubscriptExpr *E) {
|
Expr *visitArchetypeSubscriptExpr(ArchetypeSubscriptExpr *E) {
|
||||||
return TC.semaSubscriptExpr(E);
|
return TC.semaSubscriptExpr(E);
|
||||||
}
|
}
|
||||||
|
Expr *visitGenericSubscriptExpr(GenericSubscriptExpr *E) {
|
||||||
|
return TC.semaSubscriptExpr(E);
|
||||||
|
}
|
||||||
|
|
||||||
Expr *visitOverloadedSubscriptExpr(OverloadedSubscriptExpr *E) {
|
Expr *visitOverloadedSubscriptExpr(OverloadedSubscriptExpr *E) {
|
||||||
E->setType(UnstructuredUnresolvedType::get(TC.Context));
|
E->setType(UnstructuredUnresolvedType::get(TC.Context));
|
||||||
|
|||||||
@@ -316,6 +316,7 @@ public:
|
|||||||
Expr *semaSubscriptExpr(SubscriptExpr *SE);
|
Expr *semaSubscriptExpr(SubscriptExpr *SE);
|
||||||
Expr *semaSubscriptExpr(ExistentialSubscriptExpr *SE);
|
Expr *semaSubscriptExpr(ExistentialSubscriptExpr *SE);
|
||||||
Expr *semaSubscriptExpr(ArchetypeSubscriptExpr *SE);
|
Expr *semaSubscriptExpr(ArchetypeSubscriptExpr *SE);
|
||||||
|
Expr *semaSubscriptExpr(GenericSubscriptExpr *SE);
|
||||||
Expr *semaApplyExpr(ApplyExpr *E);
|
Expr *semaApplyExpr(ApplyExpr *E);
|
||||||
Expr *semaUnresolvedDotExpr(UnresolvedDotExpr *E);
|
Expr *semaUnresolvedDotExpr(UnresolvedDotExpr *E);
|
||||||
void typeCheckIgnoredExpr(Expr *E);
|
void typeCheckIgnoredExpr(Expr *E);
|
||||||
|
|||||||
Reference in New Issue
Block a user