Skip to content

Commit 8a0a083

Browse files
authored
Merge pull request #77797 from xedin/locatable-types
[AST/Sema] Introduce a new type that has associated location in source
2 parents 36e33a8 + df6950a commit 8a0a083

File tree

19 files changed

+300
-21
lines changed

19 files changed

+300
-21
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

include/swift/Sema/ConstraintSystem.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3501,6 +3501,8 @@ class ConstraintSystem {
35013501
return !solverState || solverState->recordFixes;
35023502
}
35033503

3504+
bool inSalvageMode() const { return solverState && solverState->recordFixes; }
3505+
35043506
ArrayRef<ConstraintFix *> getFixes() const { return Fixes.getArrayRef(); }
35053507

35063508
bool shouldSuppressDiagnostics() const {

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;
@@ -3272,6 +3273,7 @@ void ASTContext::Implementation::Arena::dump(llvm::raw_ostream &os) const {
32723273

32733274
SIZE_AND_BYTES(ErrorTypesWithOriginal);
32743275
SIZE(TypeAliasTypes);
3276+
SIZE(LocatableTypes);
32753277
SIZE(TupleTypes);
32763278
SIZE(PackTypes);
32773279
SIZE(PackExpansionTypes);
@@ -3454,6 +3456,45 @@ void TypeAliasType::Profile(
34543456
id.AddPointer(underlying.getPointer());
34553457
}
34563458

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

lib/AST/ASTDumper.cpp

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4094,6 +4094,18 @@ namespace {
40944094
printFoot();
40954095
}
40964096

4097+
void visitLocatableType(LocatableType *T, StringRef label) {
4098+
printCommon("locatable_type", label);
4099+
printFieldQuotedRaw(
4100+
[&](raw_ostream &OS) {
4101+
auto &C = T->getASTContext();
4102+
T->getLoc().print(OS, C.SourceMgr);
4103+
},
4104+
"loc");
4105+
printRec(T->getSinglyDesugaredType(), "underlying");
4106+
printFoot();
4107+
}
4108+
40974109
void visitPackType(PackType *T, StringRef label) {
40984110
printCommon("pack_type", label);
40994111

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
@@ -6006,6 +6006,10 @@ class TypePrinter : public TypeVisitor<TypePrinter> {
60066006
}
60076007
}
60086008

6009+
void visitLocatableType(LocatableType *T) {
6010+
visit(T->getSinglyDesugaredType());
6011+
}
6012+
60096013
void visitPackType(PackType *T) {
60106014
if (Options.PrintExplicitPackTypes || Options.PrintTypesForDebugging)
60116015
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:

lib/Sema/CSDiagnostics.cpp

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -611,6 +611,13 @@ void RequirementFailure::maybeEmitRequirementNote(const Decl *anchor, Type lhs,
611611
req.getFirstType(), lhs, req.getSecondType(), rhs);
612612
}
613613

614+
SourceLoc MissingConformanceFailure::getLoc() const {
615+
if (auto *locatable = dyn_cast<LocatableType>(LHS.getPointer())) {
616+
return locatable->getLoc();
617+
}
618+
return RequirementFailure::getLoc();
619+
}
620+
614621
bool MissingConformanceFailure::diagnoseAsError() {
615622
auto anchor = getAnchor();
616623
auto nonConformingType = getLHS();

lib/Sema/CSDiagnostics.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -259,6 +259,10 @@ class RequirementFailure : public FailureDiagnostic {
259259
Apply = dyn_cast<ApplyExpr>(parentExpr);
260260
}
261261

262+
virtual SourceLoc getLoc() const override {
263+
return FailureDiagnostic::getLoc();
264+
}
265+
262266
unsigned getRequirementIndex() const {
263267
auto reqElt =
264268
getLocator()->castLastElementTo<LocatorPathElt::AnyRequirement>();
@@ -341,6 +345,8 @@ class MissingConformanceFailure final : public RequirementFailure {
341345
#endif
342346
}
343347

348+
virtual SourceLoc getLoc() const override;
349+
344350
bool diagnoseAsError() override;
345351

346352
protected:

lib/Sema/CSGen.cpp

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2687,6 +2687,21 @@ namespace {
26872687
varType = TypeChecker::getOptionalType(var->getLoc(), varType);
26882688
}
26892689

2690+
auto makeTypeLocatableIfPossible = [&var](Type type) -> Type {
2691+
if (auto loc = var->getLoc()) {
2692+
return LocatableType::get(loc, type);
2693+
}
2694+
return type;
2695+
};
2696+
2697+
auto useLocatableTypes = [&]() -> bool {
2698+
if (!CS.inSalvageMode())
2699+
return false;
2700+
2701+
return var->isImplicit() &&
2702+
var->getNameStr().starts_with("$__builder");
2703+
};
2704+
26902705
// When we are supposed to bind pattern variables, create a fresh
26912706
// type variable and a one-way constraint to assign it to either the
26922707
// deduced type or the externally-imposed type.
@@ -2711,6 +2726,9 @@ namespace {
27112726

27122727
CS.addConstraint(ConstraintKind::OneWayEqual, oneWayVarType,
27132728
varType, locator);
2729+
2730+
if (useLocatableTypes())
2731+
oneWayVarType = makeTypeLocatableIfPossible(oneWayVarType);
27142732
}
27152733

27162734
// Ascribe a type to the declaration so it's always available to
@@ -2772,6 +2790,9 @@ namespace {
27722790
CS.getConstraintLocator(locator));
27732791
}
27742792

2793+
if (useLocatableTypes())
2794+
declTy = makeTypeLocatableIfPossible(declTy);
2795+
27752796
CS.setType(var, declTy);
27762797
}
27772798

lib/Sema/CSSimplify.cpp

Lines changed: 24 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -8427,11 +8427,10 @@ ConstraintSystem::SolutionKind ConstraintSystem::simplifyConformsToConstraint(
84278427

84288428
// We sometimes get a pack expansion type here.
84298429
if (auto *expansionType = type->getAs<PackExpansionType>()) {
8430-
// FIXME: Locator
8431-
addConstraint(ConstraintKind::ConformsTo,
8432-
expansionType->getPatternType(),
8433-
protocol->getDeclaredInterfaceType(),
8434-
locator);
8430+
addConstraint(
8431+
ConstraintKind::ConformsTo, expansionType->getPatternType(),
8432+
protocol->getDeclaredInterfaceType(),
8433+
locator.withPathElement(LocatorPathElt::PackExpansionPattern()));
84358434

84368435
return SolutionKind::Solved;
84378436
}
@@ -8625,17 +8624,27 @@ ConstraintSystem::SolutionKind ConstraintSystem::simplifyConformsToConstraint(
86258624
return recordFix(fix) ? SolutionKind::Error : SolutionKind::Solved;
86268625
}
86278626

8628-
// If we have something like ... -> type req # -> pack element #, we're
8629-
// solving a requirement of the form T : P where T is a type parameter pack
8630-
if (path.back().is<LocatorPathElt::PackElement>())
8631-
path.pop_back();
8627+
// Conditional conformance requirements could produce chains of
8628+
// `path element -> pack expansion pattern -> pack element`.
8629+
while (!path.empty()) {
8630+
// If we have something like ... -> type req # -> pack element #, we're
8631+
// solving a requirement of the form T : P where T is a type parameter pack
8632+
if (path.back().is<LocatorPathElt::PackElement>()) {
8633+
path.pop_back();
8634+
continue;
8635+
}
86328636

8633-
// This is similar to `PackElement` but locator points to the requirement
8634-
// associted with pack expansion pattern (i.e. `repeat each T: P`) where
8635-
// the path is something like:
8636-
// `... -> type req # -> pack expansion pattern`.
8637-
if (path.back().is<LocatorPathElt::PackExpansionPattern>())
8638-
path.pop_back();
8637+
// This is similar to `PackElement` but locator points to the requirement
8638+
// associated with pack expansion pattern (i.e. `repeat each T: P`) where
8639+
// the path is something like:
8640+
// `... -> type req # -> pack expansion pattern`.
8641+
if (path.back().is<LocatorPathElt::PackExpansionPattern>()) {
8642+
path.pop_back();
8643+
continue;
8644+
}
8645+
8646+
break;
8647+
}
86398648

86408649
if (auto req = path.back().getAs<LocatorPathElt::AnyRequirement>()) {
86418650
// If this is a requirement associated with `Self` which is bound

lib/Serialization/Serialization.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5443,6 +5443,10 @@ class Serializer::TypeSerializer : public TypeVisitor<TypeSerializer> {
54435443
llvm_unreachable("error union types do not persist in the AST");
54445444
}
54455445

5446+
void visitLocatableType(const LocatableType *) {
5447+
llvm_unreachable("locatable types do not persist in the AST");
5448+
}
5449+
54465450
void visitBuiltinTypeImpl(Type ty) {
54475451
using namespace decls_block;
54485452
TypeAliasDecl *typeAlias =

test/Constraints/result_builder_diags.swift

Lines changed: 26 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -629,15 +629,37 @@ _ = wrapperifyInfer(true) { x in // Ok
629629

630630
struct DoesNotConform {}
631631

632+
struct List<C> {
633+
typealias T = C
634+
635+
init(@TupleBuilder _: () -> C) {}
636+
}
637+
638+
extension List: P where C: P {}
639+
632640
struct MyView {
633-
@TupleBuilder var value: some P { // expected-error {{return type of property 'value' requires that 'DoesNotConform' conform to 'P'}}
641+
struct Conforms : P {
642+
typealias T = Void
643+
}
644+
645+
@TupleBuilder var value: some P {
646+
// expected-note@-1 {{opaque return type declared here}}
647+
DoesNotConform() // expected-error {{return type of property 'value' requires that 'DoesNotConform' conform to 'P'}}
648+
}
649+
650+
@TupleBuilder var nestedFailures: some P {
634651
// expected-note@-1 {{opaque return type declared here}}
635-
DoesNotConform()
652+
List {
653+
List {
654+
DoesNotConform()
655+
// expected-error@-1 {{return type of property 'nestedFailures' requires that 'DoesNotConform' conform to 'P'}}
656+
}
657+
}
636658
}
637659

638-
@TupleBuilder func test() -> some P { // expected-error {{return type of instance method 'test()' requires that 'DoesNotConform' conform to 'P'}}
660+
@TupleBuilder func test() -> some P {
639661
// expected-note@-1 {{opaque return type declared here}}
640-
DoesNotConform()
662+
DoesNotConform() // expected-error {{return type of instance method 'test()' requires that 'DoesNotConform' conform to 'P'}}
641663
}
642664

643665
@TupleBuilder var emptySwitch: some P {

0 commit comments

Comments
 (0)