Skip to content

Commit 09db290

Browse files
committed
Strip TypeExpr of its TypeLoc
Remove duplication in the modeling of TypeExpr. The type of a TypeExpr node is always a metatype corresponding to the contextual type of the type it's referencing. For some reason, the instance type was also stored in this TypeLoc at random points in semantic analysis. Under the assumption that this instance type is always going to be the instance type of the contextual type of the expression, introduce a number of simplifications: 1) Explicit TypeExpr nodes must be created with a TypeRepr node 2) Implicit TypeExpr nodes must be created with a contextual type 3) The typing rules for implicit TypeExpr simply opens this type
1 parent 83422c8 commit 09db290

File tree

12 files changed

+70
-68
lines changed

12 files changed

+70
-68
lines changed

include/swift/AST/Expr.h

Lines changed: 6 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -497,9 +497,7 @@ class alignas(8) Expr {
497497
bool isImplicit() const {
498498
return Bits.Expr.Implicit;
499499
}
500-
void setImplicit(bool Implicit = true) {
501-
Bits.Expr.Implicit = Implicit;
502-
}
500+
void setImplicit(bool Implicit = true);
503501

504502
/// Retrieves the declaration that is being referenced by this
505503
/// expression, if any.
@@ -1337,11 +1335,10 @@ class SuperRefExpr : public Expr {
13371335
///
13381336
/// The type of this expression is always \c MetaTypeType.
13391337
class TypeExpr : public Expr {
1340-
TypeLoc Info;
1341-
TypeExpr(Type Ty);
1338+
TypeRepr *Repr;
13421339
public:
13431340
// Create a TypeExpr with location information.
1344-
TypeExpr(TypeLoc Ty);
1341+
TypeExpr(TypeRepr *Ty);
13451342

13461343
// The type of a TypeExpr is always a metatype type. Return the instance
13471344
// type, ErrorType if an error, or null if not set yet.
@@ -1353,9 +1350,7 @@ class TypeExpr : public Expr {
13531350
}) const;
13541351

13551352
// Create an implicit TypeExpr, which has no location information.
1356-
static TypeExpr *createImplicit(Type Ty, ASTContext &C) {
1357-
return new (C) TypeExpr(Ty);
1358-
}
1353+
static TypeExpr *createImplicit(Type Ty, ASTContext &C);
13591354

13601355
// Create an implicit TypeExpr, with location information even though it
13611356
// shouldn't have one. This is presently used to work around other location
@@ -1389,13 +1384,11 @@ class TypeExpr : public Expr {
13891384
SourceRange AngleLocs,
13901385
ASTContext &C);
13911386

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

1398-
SourceRange getSourceRange() const { return Info.getSourceRange(); }
1391+
SourceRange getSourceRange() const { return TypeLoc(Repr).getSourceRange(); }
13991392
// TODO: optimize getStartLoc() and getEndLoc() when TypeLoc allows it.
14001393

14011394
static bool classof(const Expr *E) {

lib/AST/ASTWalker.cpp

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -481,8 +481,9 @@ class Traversal : public ASTVisitor<Traversal, Expr*, Stmt*,
481481
Expr *visitDiscardAssignmentExpr(DiscardAssignmentExpr *E) { return E; }
482482
Expr *visitTypeExpr(TypeExpr *E) {
483483
if (!E->isImplicit())
484-
if (doIt(E->getTypeLoc()))
485-
return nullptr;
484+
if (auto *typerepr = E->getTypeRepr())
485+
if (doIt(typerepr))
486+
return nullptr;
486487

487488
return E;
488489
}

lib/AST/Expr.cpp

Lines changed: 26 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -130,6 +130,12 @@ void Expr::setType(Type T) {
130130
Ty = T;
131131
}
132132

133+
void Expr::setImplicit(bool Implicit) {
134+
assert(!isa<TypeExpr>(this) || getType() &&
135+
"Cannot make a TypeExpr implicit without a contextual type.");
136+
Bits.Expr.Implicit = Implicit;
137+
}
138+
133139
template <class T> static SourceRange getSourceRangeImpl(const T *E) {
134140
static_assert(isOverriddenFromExpr(&T::getSourceRange) ||
135141
(isOverriddenFromExpr(&T::getStartLoc) &&
@@ -936,8 +942,9 @@ static void
936942
computeSingleArgumentType(ASTContext &ctx, Expr *arg, bool implicit,
937943
llvm::function_ref<Type(const Expr *)> getType) {
938944
// Propagate 'implicit' to the argument.
939-
if (implicit)
945+
if (implicit) {
940946
arg->setImplicit(true);
947+
}
941948

942949
// Handle parenthesized expressions.
943950
if (auto paren = dyn_cast<ParenExpr>(arg)) {
@@ -1918,17 +1925,15 @@ Expr *AutoClosureExpr::getUnwrappedCurryThunkExpr() const {
19181925

19191926
FORWARD_SOURCE_LOCS_TO(UnresolvedPatternExpr, subPattern)
19201927

1921-
TypeExpr::TypeExpr(TypeLoc TyLoc)
1922-
: Expr(ExprKind::Type, /*implicit*/false), Info(TyLoc) {
1923-
Type Ty = TyLoc.getType();
1924-
if (Ty && Ty->hasCanonicalTypeComputed())
1925-
setType(MetatypeType::get(Ty, Ty->getASTContext()));
1926-
}
1928+
TypeExpr::TypeExpr(TypeRepr *Repr)
1929+
: Expr(ExprKind::Type, /*implicit*/false), Repr(Repr) {}
19271930

1928-
TypeExpr::TypeExpr(Type Ty)
1929-
: Expr(ExprKind::Type, /*implicit*/true), Info(TypeLoc::withoutLoc(Ty)) {
1930-
if (Ty->hasCanonicalTypeComputed())
1931-
setType(MetatypeType::get(Ty, Ty->getASTContext()));
1931+
TypeExpr *TypeExpr::createImplicit(Type Ty, ASTContext &C) {
1932+
assert(Ty);
1933+
auto *result = new (C) TypeExpr(nullptr);
1934+
result->setType(MetatypeType::get(Ty, Ty->getASTContext()));
1935+
result->setImplicit();
1936+
return result;
19321937
}
19331938

19341939
// The type of a TypeExpr is always a metatype type. Return the instance
@@ -1953,9 +1958,11 @@ TypeExpr *TypeExpr::createForDecl(DeclNameLoc Loc, TypeDecl *Decl,
19531958
assert(Loc.isValid() || isImplicit);
19541959
auto *Repr = new (C) SimpleIdentTypeRepr(Loc, Decl->createNameRef());
19551960
Repr->setValue(Decl, DC);
1956-
auto result = new (C) TypeExpr(TypeLoc(Repr, Type()));
1957-
if (isImplicit)
1961+
auto result = new (C) TypeExpr(Repr);
1962+
if (isImplicit) {
1963+
result->setType(DC->mapTypeIntoContext(Decl->getInterfaceType()));
19581964
result->setImplicit();
1965+
}
19591966
return result;
19601967
}
19611968

@@ -1983,7 +1990,7 @@ TypeExpr *TypeExpr::createForMemberDecl(DeclNameLoc ParentNameLoc,
19831990
Components.push_back(NewComp);
19841991

19851992
auto *NewTypeRepr = IdentTypeRepr::create(C, Components);
1986-
return new (C) TypeExpr(TypeLoc(NewTypeRepr, Type()));
1993+
return new (C) TypeExpr(NewTypeRepr);
19871994
}
19881995

19891996
TypeExpr *TypeExpr::createForMemberDecl(IdentTypeRepr *ParentTR,
@@ -2004,7 +2011,7 @@ TypeExpr *TypeExpr::createForMemberDecl(IdentTypeRepr *ParentTR,
20042011
Components.push_back(NewComp);
20052012

20062013
auto *NewTypeRepr = IdentTypeRepr::create(C, Components);
2007-
return new (C) TypeExpr(TypeLoc(NewTypeRepr, Type()));
2014+
return new (C) TypeExpr(NewTypeRepr);
20082015
}
20092016

20102017
TypeExpr *TypeExpr::createForSpecializedDecl(IdentTypeRepr *ParentTR,
@@ -2053,7 +2060,7 @@ TypeExpr *TypeExpr::createForSpecializedDecl(IdentTypeRepr *ParentTR,
20532060
components.push_back(genericComp);
20542061

20552062
auto *genericRepr = IdentTypeRepr::create(C, components);
2056-
return new (C) TypeExpr(TypeLoc(genericRepr, Type()));
2063+
return new (C) TypeExpr(genericRepr);
20572064
}
20582065

20592066
return nullptr;
@@ -2064,11 +2071,12 @@ TypeExpr *TypeExpr::createForSpecializedDecl(IdentTypeRepr *ParentTR,
20642071
// processing bugs. If you have an implicit location, use createImplicit.
20652072
TypeExpr *TypeExpr::createImplicitHack(SourceLoc Loc, Type Ty, ASTContext &C) {
20662073
// FIXME: This is horrible.
2074+
assert(Ty);
20672075
if (Loc.isInvalid()) return createImplicit(Ty, C);
20682076
auto *Repr = new (C) FixedTypeRepr(Ty, Loc);
2069-
auto *Res = new (C) TypeExpr(TypeLoc(Repr, Ty));
2070-
Res->setImplicit();
2077+
auto *Res = new (C) TypeExpr(Repr);
20712078
Res->setType(MetatypeType::get(Ty, C));
2079+
Res->setImplicit();
20722080
return Res;
20732081
}
20742082

lib/IDE/ExprContextAnalysis.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -375,8 +375,8 @@ static void collectPossibleCalleesByQualifiedLookup(
375375
// Re-typecheck TypeExpr so it's typechecked without the arguments which may
376376
// affects the inference of the generic arguments.
377377
if (TypeExpr *tyExpr = dyn_cast<TypeExpr>(baseExpr)) {
378-
tyExpr->setType(nullptr);
379-
tyExpr->getTypeLoc().setType(nullptr);
378+
if (!tyExpr->isImplicit())
379+
tyExpr->setType(nullptr);
380380
}
381381

382382
auto baseTyOpt = getTypeOfCompletionContextExpr(

lib/Parse/ParseExpr.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -395,7 +395,7 @@ ParserResult<Expr> Parser::parseExprSequenceElement(Diag<> message,
395395
ParserResult<TypeRepr> ty = parseType();
396396
if (ty.isNonNull())
397397
return makeParserResult(
398-
new (Context) TypeExpr(TypeLoc(ty.get(), Type())));
398+
new (Context) TypeExpr(ty.get()));
399399
checkForInputIncomplete();
400400
return nullptr;
401401
}
@@ -1534,7 +1534,7 @@ ParserResult<Expr> Parser::parseExprPrimary(Diag<> ID, bool isExprBasic) {
15341534
case tok::kw_Any: { // Any
15351535
ExprContext.setCreateSyntax(SyntaxKind::TypeExpr);
15361536
auto TyR = parseAnyType();
1537-
return makeParserResult(new (Context) TypeExpr(TypeLoc(TyR.get())));
1537+
return makeParserResult(new (Context) TypeExpr(TyR.get()));
15381538
}
15391539

15401540
case tok::dollarident: // $1

lib/Sema/BuilderTransform.cpp

Lines changed: 10 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -73,25 +73,26 @@ class BuilderClosureVisitor
7373
if (!cs)
7474
return nullptr;
7575

76-
// FIXME: Setting a TypeLoc on this expression is necessary in order
76+
// FIXME: Setting a base on this expression is necessary in order
7777
// to get diagnostics if something about this builder call fails,
7878
// e.g. if there isn't a matching overload for `buildBlock`.
79-
// But we can only do this if there isn't a type variable in the type.
80-
TypeLoc typeLoc;
81-
if (!builderType->hasTypeVariable()) {
82-
typeLoc = TypeLoc(new (ctx) FixedTypeRepr(builderType, loc), builderType);
79+
TypeExpr *typeExpr;
80+
auto simplifiedTy = cs->simplifyType(builderType);
81+
if (!simplifiedTy->hasTypeVariable()) {
82+
typeExpr = TypeExpr::createImplicitHack(loc, simplifiedTy, ctx);
83+
} else {
84+
// HACK: If there's not enough information in the constraint system,
85+
// create a garbage base type to force it to diagnose
86+
// this as an ambiguous expression.
87+
typeExpr = TypeExpr::createImplicitHack(loc, ErrorType::get(ctx), ctx);
8388
}
84-
85-
auto typeExpr = new (ctx) TypeExpr(typeLoc);
8689
cs->setType(typeExpr, MetatypeType::get(builderType));
87-
cs->setType(&typeExpr->getTypeLoc(), builderType);
8890

8991
SmallVector<SourceLoc, 4> argLabelLocs;
9092
for (auto i : indices(argLabels)) {
9193
argLabelLocs.push_back(args[i]->getStartLoc());
9294
}
9395

94-
typeExpr->setImplicit();
9596
auto memberRef = new (ctx) UnresolvedDotExpr(
9697
typeExpr, loc, DeclNameRef(fnName), DeclNameLoc(loc),
9798
/*implicit=*/true);

lib/Sema/CSApply.cpp

Lines changed: 5 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2650,9 +2650,9 @@ namespace {
26502650
}
26512651

26522652
Expr *visitTypeExpr(TypeExpr *expr) {
2653-
auto toType = simplifyType(cs.getType(expr->getTypeLoc()));
2654-
expr->getTypeLoc().setType(toType);
2655-
cs.setType(expr, MetatypeType::get(toType));
2653+
auto toType = simplifyType(cs.getType(expr));
2654+
assert(toType->is<MetatypeType>());
2655+
cs.setType(expr, toType);
26562656
return expr;
26572657
}
26582658

@@ -3887,16 +3887,14 @@ namespace {
38873887
if (!TE)
38883888
return subExpr;
38893889

3890-
auto type = TE->getInstanceType(
3891-
[&](const Expr *expr) { return cs.hasType(expr); },
3892-
[&](const Expr *expr) { return cs.getType(expr); });
3890+
auto type = cs.getInstanceType(TE);
38933891

38943892
assert(!type->hasError());
38953893

38963894
if (!type->isEqual(toType))
38973895
return subExpr;
38983896

3899-
return cs.cacheType(new (ctx) TypeExpr(expr->getCastTypeLoc()));
3897+
return cs.cacheType(TypeExpr::createImplicitHack(expr->getLoc(), toType, ctx));
39003898
});
39013899
}
39023900

lib/Sema/CSDiagnostics.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5163,7 +5163,7 @@ bool MissingGenericArgumentsFailure::findArgumentLocations(
51635163

51645164
TypeLoc typeLoc;
51655165
if (auto *TE = getAsExpr<TypeExpr>(anchor))
5166-
typeLoc = TE->getTypeLoc();
5166+
typeLoc = TE->getTypeRepr();
51675167
else if (auto *ECE = getAsExpr<ExplicitCastExpr>(anchor))
51685168
typeLoc = ECE->getCastTypeLoc();
51695169

lib/Sema/CSGen.cpp

Lines changed: 10 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1461,20 +1461,19 @@ namespace {
14611461
Type visitTypeExpr(TypeExpr *E) {
14621462
Type type;
14631463
// If this is an implicit TypeExpr, don't validate its contents.
1464-
auto &typeLoc = E->getTypeLoc();
1465-
if (typeLoc.wasValidated()) {
1466-
type = typeLoc.getType();
1467-
} else if (typeLoc.hasLocation()) {
1468-
type = resolveTypeReferenceInExpression(typeLoc);
1469-
} else if (E->isImplicit() && CS.hasType(&typeLoc)) {
1470-
type = CS.getType(typeLoc);
1464+
if (E->isImplicit()) {
1465+
type = CS.getInstanceType(CS.cacheType(E));
1466+
assert(type && "Implicit type expr must have type set!");
1467+
} else {
1468+
auto *repr = E->getTypeRepr();
1469+
assert(repr && "Explicit node has no type repr!");
1470+
type = resolveTypeReferenceInExpression(repr);
14711471
}
14721472

14731473
if (!type || type->hasError()) return Type();
14741474

14751475
auto locator = CS.getConstraintLocator(E);
14761476
type = CS.openUnboundGenericType(type, locator);
1477-
CS.setType(E->getTypeLoc(), type);
14781477
return MetatypeType::get(type);
14791478
}
14801479

@@ -4022,11 +4021,11 @@ namespace {
40224021
// result of the join.
40234022
auto joinMetaTy =
40244023
CG.resultOfTypeOperation(typeOperation, apply->getArg());
4025-
auto joinTy = joinMetaTy->castTo<MetatypeType>()->getInstanceType();
4024+
auto joinTy = joinMetaTy->castTo<MetatypeType>();
40264025

4027-
auto *TE = TypeExpr::createImplicit(joinTy, CS.getASTContext());
4026+
auto *TE = TypeExpr::createImplicit(joinTy->getInstanceType(),
4027+
CS.getASTContext());
40284028
CS.cacheType(TE);
4029-
CS.setType(TE->getTypeLoc(), joinTy);
40304029

40314030
auto *DSE = new (CS.getASTContext())
40324031
DotSelfExpr(TE, SourceLoc(), SourceLoc(), CS.getType(TE));

lib/Sema/DerivedConformanceCodable.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -470,7 +470,7 @@ static CallExpr *createContainerKeyedByCall(ASTContext &C, DeclContext *DC,
470470
// CodingKeys.self expr
471471
auto *codingKeysExpr = TypeExpr::createForDecl(DeclNameLoc(),
472472
param,
473-
param->getDeclContext(),
473+
DC,
474474
/*Implicit=*/true);
475475
auto *codingKeysMetaTypeExpr = new (C) DotSelfExpr(codingKeysExpr,
476476
SourceLoc(), SourceLoc());

lib/Sema/TypeCheckPattern.cpp

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -615,7 +615,9 @@ Pattern *TypeChecker::resolvePattern(Pattern *P, DeclContext *DC,
615615
Context.Diags.diagnose(TE->getStartLoc(), diag::type_pattern_missing_is)
616616
.fixItInsert(TE->getStartLoc(), "is ");
617617

618-
P = new (Context) IsPattern(TE->getStartLoc(), TE->getTypeLoc(),
618+
P = new (Context) IsPattern(TE->getStartLoc(),
619+
TypeLoc(TE->getTypeRepr(),
620+
TE->getInstanceType()),
619621
/*subpattern*/nullptr,
620622
CheckedCastKind::Unresolved);
621623
}

test/Sema/diag_erroneous_iuo.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -116,7 +116,7 @@ _ = [Int!]() // expected-error {{'!' is not allowed here; perhaps '?' was intend
116116
let _: [Int!] = [1] // expected-error {{'!' is not allowed here; perhaps '?' was intended?}}{{12-13=?}}
117117
_ = Optional<Int!>(nil) // expected-error {{'!' is not allowed here; perhaps '?' was intended?}}{{17-18=?}}
118118
let _: Optional<Int!> = nil // expected-error {{'!' is not allowed here; perhaps '?' was intended?}}{{20-21=?}}
119-
_ = Int!?(0) // expected-error {{'!' is not allowed here; perhaps '?' was intended?}}{{8-9=?}}
119+
_ = Int!?(0) // expected-error 3 {{'!' is not allowed here; perhaps '?' was intended?}}{{8-9=?}}
120120
let _: Int!? = 0 // expected-error {{'!' is not allowed here; perhaps '?' was intended?}}{{11-12=?}}
121121
_ = (
122122
Int!, // expected-error {{'!' is not allowed here; perhaps '?' was intended?}}{{6-7=?}}

0 commit comments

Comments
 (0)