Skip to content

Commit 0fe4cea

Browse files
committed
[AST] Introduce a new type that has associated location in source
This type is intended to be used to wrap compiler synthesized nodes (i.e. variables) to make it easier for diagnostic to diagnose precise failure locations. Consider the situation like: ``` protocol P {} extension Array: P where Element: P {} func test<T: P>() -> T { $_a = ... $_b = ... return [$_a, $_b] } ``` This is a common pattern with result builders. In this case if one of the elements don't conform to `P` the best user experience would be to attach diagnostic to the element otherwise the developers would have to figure out where in result expression the error occured before attempting to fix it.
1 parent 9912c44 commit 0fe4cea

File tree

11 files changed

+108
-0
lines changed

11 files changed

+108
-0
lines changed

include/swift/AST/TypeNodes.def

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -210,6 +210,7 @@ UNCHECKED_TYPE(ErrorUnion, Type)
210210
ALWAYS_CANONICAL_TYPE(Integer, Type)
211211
ABSTRACT_SUGARED_TYPE(Sugar, Type)
212212
SUGARED_TYPE(TypeAlias, SugarType)
213+
SUGARED_TYPE(Locatable, SugarType)
213214
ABSTRACT_SUGARED_TYPE(SyntaxSugar, SugarType)
214215
ABSTRACT_SUGARED_TYPE(UnarySyntaxSugar, SyntaxSugarType)
215216
SUGARED_TYPE(ArraySlice, UnarySyntaxSugarType)

include/swift/AST/TypeTransform.h

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -533,6 +533,19 @@ case TypeKind::Id:
533533
newUnderlyingTy);
534534
}
535535

536+
case TypeKind::Locatable: {
537+
auto locatable = cast<LocatableType>(base);
538+
Type oldUnderlyingTy = Type(locatable->getSinglyDesugaredType());
539+
Type newUnderlyingTy = doIt(oldUnderlyingTy, pos);
540+
if (!newUnderlyingTy)
541+
return Type();
542+
543+
if (oldUnderlyingTy.getPointer() == newUnderlyingTy.getPointer())
544+
return t;
545+
546+
return LocatableType::get(locatable->getLoc(), newUnderlyingTy);
547+
}
548+
536549
case TypeKind::ErrorUnion: {
537550
auto errorUnion = cast<ErrorUnionType>(base);
538551
bool anyChanged = false;

include/swift/AST/Types.h

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,7 @@ enum class ReferenceCounting : uint8_t;
8484
enum class ResilienceExpansion : unsigned;
8585
class SILModule;
8686
class SILType;
87+
class SourceLoc;
8788
class TypeAliasDecl;
8889
class TypeDecl;
8990
class NominalTypeDecl;
@@ -2322,6 +2323,28 @@ class TypeAliasType final
23222323
}
23232324
};
23242325

2326+
/// A type has been introduced at some fixed location in the AST.
2327+
class LocatableType final : public SugarType, public llvm::FoldingSetNode {
2328+
SourceLoc Loc;
2329+
2330+
LocatableType(SourceLoc loc, Type underlying,
2331+
RecursiveTypeProperties properties);
2332+
2333+
public:
2334+
SourceLoc getLoc() const { return Loc; }
2335+
2336+
static LocatableType *get(SourceLoc loc, Type underlying);
2337+
2338+
void Profile(llvm::FoldingSetNodeID &id) const;
2339+
2340+
static void Profile(llvm::FoldingSetNodeID &id, SourceLoc loc,
2341+
Type underlying);
2342+
2343+
static bool classof(const TypeBase *T) {
2344+
return T->getKind() == TypeKind::Locatable;
2345+
}
2346+
};
2347+
23252348
/// The various spellings of ownership modifier that can be used in source.
23262349
enum class ParamSpecifier : uint8_t {
23272350
/// No explicit ownership specifier was provided. The parameter will use the

lib/AST/ASTContext.cpp

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -530,6 +530,7 @@ struct ASTContext::Implementation {
530530

531531
llvm::DenseMap<Type, ErrorType *> ErrorTypesWithOriginal;
532532
llvm::FoldingSet<TypeAliasType> TypeAliasTypes;
533+
llvm::FoldingSet<LocatableType> LocatableTypes;
533534
llvm::FoldingSet<TupleType> TupleTypes;
534535
llvm::FoldingSet<PackType> PackTypes;
535536
llvm::FoldingSet<PackExpansionType> PackExpansionTypes;
@@ -3270,6 +3271,7 @@ void ASTContext::Implementation::Arena::dump(llvm::raw_ostream &os) const {
32703271

32713272
SIZE_AND_BYTES(ErrorTypesWithOriginal);
32723273
SIZE(TypeAliasTypes);
3274+
SIZE(LocatableTypes);
32733275
SIZE(TupleTypes);
32743276
SIZE(PackTypes);
32753277
SIZE(PackExpansionTypes);
@@ -3452,6 +3454,45 @@ void TypeAliasType::Profile(
34523454
id.AddPointer(underlying.getPointer());
34533455
}
34543456

3457+
LocatableType::LocatableType(SourceLoc loc, Type underlying,
3458+
RecursiveTypeProperties properties)
3459+
: SugarType(TypeKind::Locatable, underlying, properties), Loc(loc) {
3460+
ASSERT(loc.isValid());
3461+
}
3462+
3463+
LocatableType *LocatableType::get(SourceLoc loc, Type underlying) {
3464+
auto properties = underlying->getRecursiveProperties();
3465+
3466+
// Figure out which arena this type will go into.
3467+
auto &ctx = underlying->getASTContext();
3468+
auto arena = getArena(properties);
3469+
3470+
// Profile the type.
3471+
llvm::FoldingSetNodeID id;
3472+
LocatableType::Profile(id, loc, underlying);
3473+
3474+
// Did we already record this type?
3475+
void *insertPos;
3476+
auto &types = ctx.getImpl().getArena(arena).LocatableTypes;
3477+
if (auto result = types.FindNodeOrInsertPos(id, insertPos))
3478+
return result;
3479+
3480+
// Build a new type.
3481+
auto result = new (ctx, arena) LocatableType(loc, underlying, properties);
3482+
types.InsertNode(result, insertPos);
3483+
return result;
3484+
}
3485+
3486+
void LocatableType::Profile(llvm::FoldingSetNodeID &id) const {
3487+
Profile(id, Loc, Type(getSinglyDesugaredType()));
3488+
}
3489+
3490+
void LocatableType::Profile(llvm::FoldingSetNodeID &id, SourceLoc loc,
3491+
Type underlying) {
3492+
id.AddPointer(loc.getOpaquePointerValue());
3493+
id.AddPointer(underlying.getPointer());
3494+
}
3495+
34553496
// Simple accessors.
34563497
Type ErrorType::get(const ASTContext &C) { return C.TheErrorType; }
34573498

lib/AST/ASTDumper.cpp

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4098,6 +4098,18 @@ namespace {
40984098
printFoot();
40994099
}
41004100

4101+
void visitLocatableType(LocatableType *T, StringRef label) {
4102+
printCommon("locatable_type", label);
4103+
printFieldQuotedRaw(
4104+
[&](raw_ostream &OS) {
4105+
auto &C = T->getASTContext();
4106+
T->getLoc().print(OS, C.SourceMgr);
4107+
},
4108+
"loc");
4109+
printRec(T->getSinglyDesugaredType(), "underlying");
4110+
printFoot();
4111+
}
4112+
41014113
void visitPackType(PackType *T, StringRef label) {
41024114
printCommon("pack_type", label);
41034115

lib/AST/ASTMangler.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1296,6 +1296,7 @@ void ASTMangler::appendType(Type type, GenericSignature sig,
12961296
case TypeKind::BuiltinUnsafeValueBuffer:
12971297
return appendOperator("BB");
12981298
case TypeKind::BuiltinUnboundGeneric:
1299+
case TypeKind::Locatable:
12991300
llvm_unreachable("not a real type");
13001301
case TypeKind::BuiltinFixedArray: {
13011302
auto bfa = cast<BuiltinFixedArrayType>(tybase);

lib/AST/ASTPrinter.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6009,6 +6009,10 @@ class TypePrinter : public TypeVisitor<TypePrinter> {
60096009
}
60106010
}
60116011

6012+
void visitLocatableType(LocatableType *T) {
6013+
visit(T->getSinglyDesugaredType());
6014+
}
6015+
60126016
void visitPackType(PackType *T) {
60136017
if (Options.PrintExplicitPackTypes || Options.PrintTypesForDebugging)
60146018
Printer << "Pack{";

lib/AST/Type.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1921,6 +1921,8 @@ Type SugarType::getSinglyDesugaredTypeSlow() {
19211921
#include "swift/AST/TypeNodes.def"
19221922
case TypeKind::TypeAlias:
19231923
llvm_unreachable("bound type alias types always have an underlying type");
1924+
case TypeKind::Locatable:
1925+
llvm_unreachable("locatable types always have an underlying type");
19241926
case TypeKind::ArraySlice:
19251927
case TypeKind::VariadicSequence:
19261928
implDecl = Context->getArrayDecl();

lib/AST/TypeWalker.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@ class Traversal : public TypeVisitor<Traversal, bool>
5050
return false;
5151

5252
}
53+
bool visitLocatableType(LocatableType *ty) { return false; }
5354
bool visitSILTokenType(SILTokenType *ty) { return false; }
5455

5556
bool visitPackType(PackType *ty) {

lib/IRGen/IRGenDebugInfo.cpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2213,6 +2213,12 @@ createSpecializedStructOrClassType(NominalOrBoundGenericNominalType *Type,
22132213
L.File, 0, Scope);
22142214
}
22152215

2216+
case TypeKind::Locatable: {
2217+
auto *Sugar = cast<LocatableType>(BaseTy);
2218+
auto *CanTy = Sugar->getSinglyDesugaredType();
2219+
return getOrCreateDesugaredType(CanTy, DbgTy);
2220+
}
2221+
22162222
// SyntaxSugarType derivations.
22172223
case TypeKind::Dictionary:
22182224
case TypeKind::ArraySlice:

0 commit comments

Comments
 (0)