Skip to content

Strip TypeExpr of its TypeLoc #31253

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 5 commits into from
Apr 28, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
105 changes: 61 additions & 44 deletions include/swift/AST/Expr.h
Original file line number Diff line number Diff line change
Expand Up @@ -497,9 +497,7 @@ class alignas(8) Expr {
bool isImplicit() const {
return Bits.Expr.Implicit;
}
void setImplicit(bool Implicit = true) {
Bits.Expr.Implicit = Implicit;
}
void setImplicit(bool Implicit = true);

/// Retrieves the declaration that is being referenced by this
/// expression, if any.
Expand Down Expand Up @@ -1333,40 +1331,63 @@ class SuperRefExpr : public Expr {
}
};

/// A reference to a type in expression context, spelled out as a TypeLoc.
/// A reference to a type in expression context.
///
/// The type of this expression is always \c MetaTypeType.
/// The type of this expression is always \c MetatypeType.
class TypeExpr : public Expr {
TypeLoc Info;
TypeExpr(Type Ty);
TypeRepr *Repr;
public:
// Create a TypeExpr with location information.
TypeExpr(TypeLoc Ty);

// The type of a TypeExpr is always a metatype type. Return the instance
// type, ErrorType if an error, or null if not set yet.
Type getInstanceType(llvm::function_ref<bool(const Expr *)> hasType =
[](const Expr *E) -> bool { return !!E->getType(); },
llvm::function_ref<Type(const Expr *)> getType =
[](const Expr *E) -> Type {
return E->getType();
}) const;
/// Create a \c TypeExpr from a parsed \c TypeRepr.
TypeExpr(TypeRepr *Ty);

// Create an implicit TypeExpr, which has no location information.
static TypeExpr *createImplicit(Type Ty, ASTContext &C) {
return new (C) TypeExpr(Ty);
}
/// Retrieves the corresponding instance type of the type referenced by this
/// expression.
///
/// If this node has no type, the resulting instance type is also the
/// null \c Type(). If the type of this node is not a \c MetatypeType, the
/// resulting instance type is \c ErrorType.
Type getInstanceType() const;

// Create an implicit TypeExpr, with location information even though it
// shouldn't have one. This is presently used to work around other location
// processing bugs. If you have an implicit location, use createImplicit.
public:
/// Create an implicit \c TypeExpr.
///
/// The given type is required to be non-null and must be not be
/// a \c MetatypeType as this function will wrap the given type in one.
///
/// FIXME: This behavior is bizarre.
static TypeExpr *createImplicit(Type Ty, ASTContext &C);

/// Create an implicit \c TypeExpr that has artificial
/// location information attached.
///
/// The given type is required to be non-null and must be not be
/// a \c MetatypeType as this function will wrap the given type in one.
///
/// FIXME: This behavior is bizarre.
///
/// Due to limitations in the modeling of certain AST elements, implicit
/// \c TypeExpr nodes are often the only source of location information the
/// expression checker has when it comes time to diagnose an error.
static TypeExpr *createImplicitHack(SourceLoc Loc, Type Ty, ASTContext &C);


/// Create a TypeExpr for a TypeDecl at the specified location.
static TypeExpr *createForDecl(DeclNameLoc Loc, TypeDecl *D,
DeclContext *DC,
bool isImplicit);
/// Create an implicit \c TypeExpr for a given \c TypeDecl at the specified location.
///
/// The given type is required to be non-null and must be not be
/// a \c MetatypeType as this function will wrap the given type in one.
///
/// FIXME: This behavior is bizarre.
///
/// Unlike the non-implicit case, the given location is not required to be
/// valid.
static TypeExpr *createImplicitForDecl(DeclNameLoc Loc, TypeDecl *D,
DeclContext *DC, Type ty);

public:
/// Create a \c TypeExpr for a given \c TypeDecl at the specified location.
///
/// The given location must be valid. If it is not, you must use
/// \c TypeExpr::createImplicitForDecl instead.
static TypeExpr *createForDecl(DeclNameLoc Loc, TypeDecl *D, DeclContext *DC);

/// Create a TypeExpr for a member TypeDecl of the given parent TypeDecl.
static TypeExpr *createForMemberDecl(DeclNameLoc ParentNameLoc,
Expand All @@ -1389,13 +1410,11 @@ class TypeExpr : public Expr {
SourceRange AngleLocs,
ASTContext &C);

TypeLoc &getTypeLoc() { return Info; }
TypeLoc getTypeLoc() const { return Info; }
TypeRepr *getTypeRepr() const { return Info.getTypeRepr(); }
TypeRepr *getTypeRepr() const { return Repr; }
// NOTE: TypeExpr::getType() returns the type of the expr node, which is the
// metatype of what is stored as an operand type.

SourceRange getSourceRange() const { return Info.getSourceRange(); }
SourceRange getSourceRange() const;
// TODO: optimize getStartLoc() and getEndLoc() when TypeLoc allows it.

static bool classof(const Expr *E) {
Expand Down Expand Up @@ -4490,8 +4509,7 @@ class ExplicitCastExpr : public Expr {
TypeLoc CastTy;

protected:
ExplicitCastExpr(ExprKind kind, Expr *sub, SourceLoc AsLoc, TypeLoc castTy,
Type resultTy)
ExplicitCastExpr(ExprKind kind, Expr *sub, SourceLoc AsLoc, TypeLoc castTy)
: Expr(kind, /*Implicit=*/false), SubExpr(sub), AsLoc(AsLoc), CastTy(castTy)
{}

Expand Down Expand Up @@ -4547,8 +4565,8 @@ StringRef getCheckedCastKindName(CheckedCastKind kind);
class CheckedCastExpr : public ExplicitCastExpr {
public:
CheckedCastExpr(ExprKind kind,
Expr *sub, SourceLoc asLoc, TypeLoc castTy, Type resultTy)
: ExplicitCastExpr(kind, sub, asLoc, castTy, resultTy)
Expr *sub, SourceLoc asLoc, TypeLoc castTy)
: ExplicitCastExpr(kind, sub, asLoc, castTy)
{
Bits.CheckedCastExpr.CastKind = unsigned(CheckedCastKind::Unresolved);
}
Expand Down Expand Up @@ -4583,7 +4601,7 @@ class ForcedCheckedCastExpr : public CheckedCastExpr {
ForcedCheckedCastExpr(Expr *sub, SourceLoc asLoc, SourceLoc exclaimLoc,
TypeLoc type)
: CheckedCastExpr(ExprKind::ForcedCheckedCast,
sub, asLoc, type, type.getType()),
sub, asLoc, type),
ExclaimLoc(exclaimLoc)
{
}
Expand Down Expand Up @@ -4612,7 +4630,7 @@ class ConditionalCheckedCastExpr : public CheckedCastExpr {
ConditionalCheckedCastExpr(Expr *sub, SourceLoc asLoc, SourceLoc questionLoc,
TypeLoc type)
: CheckedCastExpr(ExprKind::ConditionalCheckedCast,
sub, asLoc, type, type.getType()),
sub, asLoc, type),
QuestionLoc(questionLoc)
{ }

Expand All @@ -4637,8 +4655,7 @@ class ConditionalCheckedCastExpr : public CheckedCastExpr {
class IsExpr : public CheckedCastExpr {
public:
IsExpr(Expr *sub, SourceLoc isLoc, TypeLoc type)
: CheckedCastExpr(ExprKind::Is,
sub, isLoc, type, Type())
: CheckedCastExpr(ExprKind::Is, sub, isLoc, type)
{}

IsExpr(SourceLoc isLoc, TypeLoc type)
Expand All @@ -4661,7 +4678,7 @@ class CoerceExpr : public ExplicitCastExpr {

public:
CoerceExpr(Expr *sub, SourceLoc asLoc, TypeLoc type)
: ExplicitCastExpr(ExprKind::Coerce, sub, asLoc, type, type.getType())
: ExplicitCastExpr(ExprKind::Coerce, sub, asLoc, type)
{ }

CoerceExpr(SourceLoc asLoc, TypeLoc type)
Expand All @@ -4671,7 +4688,7 @@ class CoerceExpr : public ExplicitCastExpr {
private:
CoerceExpr(SourceRange initRange, Expr *literal, TypeLoc type)
: ExplicitCastExpr(ExprKind::Coerce, literal, initRange.Start,
type, type.getType()), InitRangeEnd(initRange.End)
type), InitRangeEnd(initRange.End)
{ setImplicit(); }

public:
Expand Down
5 changes: 3 additions & 2 deletions lib/AST/ASTWalker.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -481,8 +481,9 @@ class Traversal : public ASTVisitor<Traversal, Expr*, Stmt*,
Expr *visitDiscardAssignmentExpr(DiscardAssignmentExpr *E) { return E; }
Expr *visitTypeExpr(TypeExpr *E) {
if (!E->isImplicit())
if (doIt(E->getTypeLoc()))
return nullptr;
if (auto *typerepr = E->getTypeRepr())
if (doIt(typerepr))
return nullptr;

return E;
}
Expand Down
75 changes: 46 additions & 29 deletions lib/AST/Expr.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,12 @@ void Expr::setType(Type T) {
Ty = T;
}

void Expr::setImplicit(bool Implicit) {
assert(!isa<TypeExpr>(this) || getType() &&
"Cannot make a TypeExpr implicit without a contextual type.");
Bits.Expr.Implicit = Implicit;
}

template <class T> static SourceRange getSourceRangeImpl(const T *E) {
static_assert(isOverriddenFromExpr(&T::getSourceRange) ||
(isOverriddenFromExpr(&T::getStartLoc) &&
Expand Down Expand Up @@ -936,8 +942,9 @@ static void
computeSingleArgumentType(ASTContext &ctx, Expr *arg, bool implicit,
llvm::function_ref<Type(const Expr *)> getType) {
// Propagate 'implicit' to the argument.
if (implicit)
if (implicit) {
arg->setImplicit(true);
}

// Handle parenthesized expressions.
if (auto paren = dyn_cast<ParenExpr>(arg)) {
Expand Down Expand Up @@ -1918,44 +1925,48 @@ Expr *AutoClosureExpr::getUnwrappedCurryThunkExpr() const {

FORWARD_SOURCE_LOCS_TO(UnresolvedPatternExpr, subPattern)

TypeExpr::TypeExpr(TypeLoc TyLoc)
: Expr(ExprKind::Type, /*implicit*/false), Info(TyLoc) {
Type Ty = TyLoc.getType();
if (Ty && Ty->hasCanonicalTypeComputed())
setType(MetatypeType::get(Ty, Ty->getASTContext()));
}
TypeExpr::TypeExpr(TypeRepr *Repr)
: Expr(ExprKind::Type, /*implicit*/false), Repr(Repr) {}

TypeExpr::TypeExpr(Type Ty)
: Expr(ExprKind::Type, /*implicit*/true), Info(TypeLoc::withoutLoc(Ty)) {
if (Ty->hasCanonicalTypeComputed())
setType(MetatypeType::get(Ty, Ty->getASTContext()));
TypeExpr *TypeExpr::createImplicit(Type Ty, ASTContext &C) {
assert(Ty);
auto *result = new (C) TypeExpr(nullptr);
result->setType(MetatypeType::get(Ty, Ty->getASTContext()));
result->setImplicit();
return result;
}

// The type of a TypeExpr is always a metatype type. Return the instance
// type or null if not set yet.
Type TypeExpr::getInstanceType(
llvm::function_ref<bool(const Expr *)> hasType,
llvm::function_ref<Type(const Expr *)> getType) const {
if (!hasType(this))
Type TypeExpr::getInstanceType() const {
auto ty = getType();
if (!ty)
return Type();

if (auto metaType = getType(this)->getAs<MetatypeType>())
if (auto metaType = ty->getAs<MetatypeType>())
return metaType->getInstanceType();

return ErrorType::get(getType(this)->getASTContext());
return ErrorType::get(ty->getASTContext());
}


TypeExpr *TypeExpr::createForDecl(DeclNameLoc Loc, TypeDecl *Decl,
DeclContext *DC,
bool isImplicit) {
DeclContext *DC) {
ASTContext &C = Decl->getASTContext();
assert(Loc.isValid());
auto *Repr = new (C) SimpleIdentTypeRepr(Loc, Decl->createNameRef());
Repr->setValue(Decl, DC);
return new (C) TypeExpr(Repr);
}

TypeExpr *TypeExpr::createImplicitForDecl(DeclNameLoc Loc, TypeDecl *Decl,
DeclContext *DC, Type ty) {
ASTContext &C = Decl->getASTContext();
assert(Loc.isValid() || isImplicit);
auto *Repr = new (C) SimpleIdentTypeRepr(Loc, Decl->createNameRef());
Repr->setValue(Decl, DC);
auto result = new (C) TypeExpr(TypeLoc(Repr, Type()));
if (isImplicit)
result->setImplicit();
auto result = new (C) TypeExpr(Repr);
assert(ty && !ty->hasTypeParameter());
result->setType(ty);
result->setImplicit();
return result;
}

Expand Down Expand Up @@ -1983,7 +1994,7 @@ TypeExpr *TypeExpr::createForMemberDecl(DeclNameLoc ParentNameLoc,
Components.push_back(NewComp);

auto *NewTypeRepr = IdentTypeRepr::create(C, Components);
return new (C) TypeExpr(TypeLoc(NewTypeRepr, Type()));
return new (C) TypeExpr(NewTypeRepr);
}

TypeExpr *TypeExpr::createForMemberDecl(IdentTypeRepr *ParentTR,
Expand All @@ -2004,7 +2015,7 @@ TypeExpr *TypeExpr::createForMemberDecl(IdentTypeRepr *ParentTR,
Components.push_back(NewComp);

auto *NewTypeRepr = IdentTypeRepr::create(C, Components);
return new (C) TypeExpr(TypeLoc(NewTypeRepr, Type()));
return new (C) TypeExpr(NewTypeRepr);
}

TypeExpr *TypeExpr::createForSpecializedDecl(IdentTypeRepr *ParentTR,
Expand Down Expand Up @@ -2053,7 +2064,7 @@ TypeExpr *TypeExpr::createForSpecializedDecl(IdentTypeRepr *ParentTR,
components.push_back(genericComp);

auto *genericRepr = IdentTypeRepr::create(C, components);
return new (C) TypeExpr(TypeLoc(genericRepr, Type()));
return new (C) TypeExpr(genericRepr);
}

return nullptr;
Expand All @@ -2064,14 +2075,20 @@ TypeExpr *TypeExpr::createForSpecializedDecl(IdentTypeRepr *ParentTR,
// processing bugs. If you have an implicit location, use createImplicit.
TypeExpr *TypeExpr::createImplicitHack(SourceLoc Loc, Type Ty, ASTContext &C) {
// FIXME: This is horrible.
assert(Ty);
if (Loc.isInvalid()) return createImplicit(Ty, C);
auto *Repr = new (C) FixedTypeRepr(Ty, Loc);
auto *Res = new (C) TypeExpr(TypeLoc(Repr, Ty));
Res->setImplicit();
auto *Res = new (C) TypeExpr(Repr);
Res->setType(MetatypeType::get(Ty, C));
Res->setImplicit();
return Res;
}

SourceRange TypeExpr::getSourceRange() const {
if (!getTypeRepr()) return SourceRange();
return getTypeRepr()->getSourceRange();
}

bool Expr::isSelfExprOf(const AbstractFunctionDecl *AFD, bool sameBase) const {
auto *E = getSemanticsProvidingExpr();

Expand Down
4 changes: 2 additions & 2 deletions lib/IDE/ExprContextAnalysis.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -375,8 +375,8 @@ static void collectPossibleCalleesByQualifiedLookup(
// Re-typecheck TypeExpr so it's typechecked without the arguments which may
// affects the inference of the generic arguments.
if (TypeExpr *tyExpr = dyn_cast<TypeExpr>(baseExpr)) {
tyExpr->setType(nullptr);
tyExpr->getTypeLoc().setType(nullptr);
if (!tyExpr->isImplicit())
tyExpr->setType(nullptr);
}

auto baseTyOpt = getTypeOfCompletionContextExpr(
Expand Down
6 changes: 3 additions & 3 deletions lib/Parse/ParseExpr.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -395,7 +395,7 @@ ParserResult<Expr> Parser::parseExprSequenceElement(Diag<> message,
ParserResult<TypeRepr> ty = parseType();
if (ty.isNonNull())
return makeParserResult(
new (Context) TypeExpr(TypeLoc(ty.get(), Type())));
new (Context) TypeExpr(ty.get()));
checkForInputIncomplete();
return nullptr;
}
Expand Down Expand Up @@ -1534,7 +1534,7 @@ ParserResult<Expr> Parser::parseExprPrimary(Diag<> ID, bool isExprBasic) {
case tok::kw_Any: { // Any
ExprContext.setCreateSyntax(SyntaxKind::TypeExpr);
auto TyR = parseAnyType();
return makeParserResult(new (Context) TypeExpr(TypeLoc(TyR.get())));
return makeParserResult(new (Context) TypeExpr(TyR.get()));
}

case tok::dollarident: // $1
Expand Down Expand Up @@ -2306,7 +2306,7 @@ Expr *Parser::parseExprIdentifier() {
// global or local declarations here.
assert(!TD->getDeclContext()->isTypeContext() ||
isa<GenericTypeParamDecl>(TD));
E = TypeExpr::createForDecl(loc, TD, /*DC*/nullptr, /*implicit*/false);
E = TypeExpr::createForDecl(loc, TD, /*DC*/ nullptr);
} else {
E = new (Context) DeclRefExpr(D, loc, /*Implicit=*/false);
}
Expand Down
Loading