[AST] Remove stored TypeLoc from TypedPattern (#19175)

* [AST] Remove stored TypeLoc from TypedPattern

TypedPattern was only using this TypeLoc as a means to a TypeRepr, which
caused it to store the pattern type twice (through the superclass and through
the TypeLoc itself.)

This also fixes a bug where deserializing a TypedPattern doesn't store
the type correctly and generally cleans up TypedPattern initialization.

Resolves rdar://44144435

* Address review comments
This commit is contained in:
Harlan
2018-09-07 21:14:04 -07:00
committed by GitHub
parent 0dd56dfda1
commit eb75ad80dc
11 changed files with 102 additions and 97 deletions

View File

@@ -383,14 +383,25 @@ public:
/// dynamic type match. /// dynamic type match.
class TypedPattern : public Pattern { class TypedPattern : public Pattern {
Pattern *SubPattern; Pattern *SubPattern;
mutable TypeLoc PatType; TypeRepr *PatTypeRepr;
public: public:
TypedPattern(Pattern *pattern, TypeLoc tl, Optional<bool> implicit = None) /// Creates a new TypedPattern which annotates the provided sub-pattern with
: Pattern(PatternKind::Typed), SubPattern(pattern), PatType(tl) { /// the provided TypeRepr. If 'implicit' is true, the pattern will be
if (implicit.hasValue() ? *implicit : !tl.hasLocation()) /// set to implicit. If false, it will not. If 'implicit' is not provided,
setImplicit(); /// then the pattern will be set to 'implicit' if there is a provided TypeRepr
Bits.TypedPattern.IsPropagatedType = false; /// which has a valid SourceRange.
TypedPattern(Pattern *pattern, TypeRepr *tr, Optional<bool> implicit = None);
/// Creates an implicit typed pattern annotating the provided sub-pattern
/// with a given type.
static TypedPattern *
createImplicit(ASTContext &ctx, Pattern *pattern, Type type) {
auto tp = new (ctx) TypedPattern(pattern, /*typeRepr*/nullptr,
/*implicit*/true);
if (!type.isNull())
tp->setType(type);
return tp;
} }
/// True if the type in this \c TypedPattern was propagated from a different /// True if the type in this \c TypedPattern was propagated from a different
@@ -412,27 +423,10 @@ public:
const Pattern *getSubPattern() const { return SubPattern; } const Pattern *getSubPattern() const { return SubPattern; }
void setSubPattern(Pattern *p) { SubPattern = p; } void setSubPattern(Pattern *p) { SubPattern = p; }
TypeLoc &getTypeLoc() { TypeRepr *getTypeRepr() const { return PatTypeRepr; }
// If we have a delayed interface type, set our type from that.
if (getDelayedInterfaceType())
PatType.setType(getType());
return PatType; TypeLoc getTypeLoc() const;
} SourceLoc getLoc() const;
TypeLoc getTypeLoc() const {
// If we have a delayed interface type, set our type from that.
if (getDelayedInterfaceType())
PatType.setType(getType());
return PatType;
}
SourceLoc getLoc() const {
if (SubPattern->isImplicit())
return PatType.getSourceRange().Start;
return SubPattern->getLoc();
}
SourceRange getSourceRange() const; SourceRange getSourceRange() const;
static bool classof(const Pattern *P) { static bool classof(const Pattern *P) {

View File

@@ -1571,7 +1571,8 @@ Pattern *Traversal::visitTypedPattern(TypedPattern *P) {
else else
return nullptr; return nullptr;
if (!P->isImplicit()) if (!P->isImplicit())
if (doIt(P->getTypeLoc())) if (auto *TR = P->getTypeRepr())
if (doIt(TR))
return nullptr; return nullptr;
return P; return P;
} }

View File

@@ -400,6 +400,30 @@ SourceRange TuplePattern::getSourceRange() const {
Fields.back().getPattern()->getEndLoc() }; Fields.back().getPattern()->getEndLoc() };
} }
TypedPattern::TypedPattern(Pattern *pattern, TypeRepr *tr,
Optional<bool> implicit)
: Pattern(PatternKind::Typed), SubPattern(pattern), PatTypeRepr(tr) {
if (implicit ? *implicit : tr && !tr->getSourceRange().isValid())
setImplicit();
Bits.TypedPattern.IsPropagatedType = false;
}
TypeLoc TypedPattern::getTypeLoc() const {
TypeLoc loc = TypeLoc(PatTypeRepr);
if (hasType())
loc.setType(getType());
return loc;
}
SourceLoc TypedPattern::getLoc() const {
if (SubPattern->isImplicit() && PatTypeRepr)
return PatTypeRepr->getSourceRange().Start;
return SubPattern->getLoc();
}
SourceRange TypedPattern::getSourceRange() const { SourceRange TypedPattern::getSourceRange() const {
if (isImplicit() || isPropagatedType()) { if (isImplicit() || isPropagatedType()) {
// If a TypedPattern is implicit, then its type is definitely implicit, so // If a TypedPattern is implicit, then its type is definitely implicit, so
@@ -408,10 +432,14 @@ SourceRange TypedPattern::getSourceRange() const {
return SubPattern->getSourceRange(); return SubPattern->getSourceRange();
} }
if (SubPattern->isImplicit()) if (!PatTypeRepr)
return PatType.getSourceRange(); return SourceRange();
return { SubPattern->getSourceRange().Start, PatType.getSourceRange().End }; if (SubPattern->isImplicit())
return PatTypeRepr->getSourceRange();
return { SubPattern->getSourceRange().Start,
PatTypeRepr->getSourceRange().End };
} }
/// Construct an ExprPattern. /// Construct an ExprPattern.

View File

@@ -117,10 +117,7 @@ static Pattern *createTypedNamedPattern(VarDecl *decl) {
Pattern *P = new (Ctx) NamedPattern(decl); Pattern *P = new (Ctx) NamedPattern(decl);
P->setType(ty); P->setType(ty);
P->setImplicit(); P->setImplicit();
P = new (Ctx) TypedPattern(P, TypeLoc::withoutLoc(ty)); return TypedPattern::createImplicit(Ctx, P, ty);
P->setType(ty);
P->setImplicit();
return P;
} }
/// Create a var member for this struct, along with its pattern binding, and add /// Create a var member for this struct, along with its pattern binding, and add

View File

@@ -4502,8 +4502,8 @@ VarDecl *Parser::parseDeclVarGetSet(Pattern *pattern,
storage->setInvalid(true); storage->setInvalid(true);
Pattern *pattern = Pattern *pattern =
new (Context) TypedPattern(new (Context) NamedPattern(storage), TypedPattern::createImplicit(Context, new (Context) NamedPattern(storage),
TypeLoc::withoutLoc(ErrorType::get(Context))); ErrorType::get(Context));
PatternBindingEntry entry(pattern, /*EqualLoc*/ SourceLoc(), PatternBindingEntry entry(pattern, /*EqualLoc*/ SourceLoc(),
/*Init*/ nullptr, /*InitContext*/ nullptr); /*Init*/ nullptr, /*InitContext*/ nullptr);
auto binding = PatternBindingDecl::create(Context, StaticLoc, auto binding = PatternBindingDecl::create(Context, StaticLoc,
@@ -5135,7 +5135,7 @@ Parser::parseDeclVar(ParseDeclOptions Flags,
} }
TypedPattern *NewTP = new (Context) TypedPattern(PrevPat, TypedPattern *NewTP = new (Context) TypedPattern(PrevPat,
TP->getTypeLoc()); TP->getTypeRepr());
NewTP->setPropagatedType(); NewTP->setPropagatedType();
PBDEntries[i-1].setPattern(NewTP); PBDEntries[i-1].setPattern(NewTP);
} }

View File

@@ -1271,6 +1271,7 @@ static void synthesizeLazyGetterBody(TypeChecker &TC, AccessorDecl *Get,
Ctx.getIdentifier("tmp2"), Ctx.getIdentifier("tmp2"),
Get); Get);
Tmp2VD->setType(VD->getType()); Tmp2VD->setType(VD->getType());
Tmp2VD->setInterfaceType(VD->getInterfaceType());
Tmp2VD->setImplicit(); Tmp2VD->setImplicit();
@@ -1297,9 +1298,8 @@ static void synthesizeLazyGetterBody(TypeChecker &TC, AccessorDecl *Get,
} }
Pattern *Tmp2PBDPattern = new (Ctx) NamedPattern(Tmp2VD, /*implicit*/true); Pattern *Tmp2PBDPattern = new (Ctx) NamedPattern(Tmp2VD, /*implicit*/true);
Tmp2PBDPattern = new (Ctx) TypedPattern(Tmp2PBDPattern, Tmp2PBDPattern =
TypeLoc::withoutLoc(VD->getType()), TypedPattern::createImplicit(Ctx, Tmp2PBDPattern, VD->getType());
/*implicit*/true);
auto *Tmp2PBD = PatternBindingDecl::createImplicit( auto *Tmp2PBD = PatternBindingDecl::createImplicit(
Ctx, StaticSpellingKind::None, Tmp2PBDPattern, InitValue, Get, Ctx, StaticSpellingKind::None, Tmp2PBDPattern, InitValue, Get,
@@ -1447,9 +1447,8 @@ void TypeChecker::completePropertyBehaviorStorage(VarDecl *VD,
// Create the pattern binding decl for the storage decl. This will get // Create the pattern binding decl for the storage decl. This will get
// default initialized using the protocol's initStorage() method. // default initialized using the protocol's initStorage() method.
Pattern *PBDPattern = new (Context) NamedPattern(Storage, /*implicit*/true); Pattern *PBDPattern = new (Context) NamedPattern(Storage, /*implicit*/true);
PBDPattern = new (Context) TypedPattern(PBDPattern, PBDPattern = TypedPattern::createImplicit(Context, PBDPattern,
TypeLoc::withoutLoc(SubstStorageContextTy), SubstStorageContextTy);
/*implicit*/true);
auto *PBD = PatternBindingDecl::createImplicit( auto *PBD = PatternBindingDecl::createImplicit(
Context, VD->getParentPatternBinding()->getStaticSpelling(), PBDPattern, Context, VD->getParentPatternBinding()->getStaticSpelling(), PBDPattern,
InitStorageExpr, VD->getDeclContext(), /*VarLoc*/ VD->getLoc()); InitStorageExpr, VD->getDeclContext(), /*VarLoc*/ VD->getLoc());
@@ -1740,9 +1739,7 @@ void TypeChecker::completeLazyVarImplementation(VarDecl *VD) {
// Create the pattern binding decl for the storage decl. This will get // Create the pattern binding decl for the storage decl. This will get
// default initialized to nil. // default initialized to nil.
Pattern *PBDPattern = new (Context) NamedPattern(Storage, /*implicit*/true); Pattern *PBDPattern = new (Context) NamedPattern(Storage, /*implicit*/true);
PBDPattern = new (Context) TypedPattern(PBDPattern, PBDPattern = TypedPattern::createImplicit(Context, PBDPattern, StorageTy);
TypeLoc::withoutLoc(StorageTy),
/*implicit*/true);
auto *PBD = PatternBindingDecl::createImplicit( auto *PBD = PatternBindingDecl::createImplicit(
Context, StaticSpellingKind::None, PBDPattern, /*init*/ nullptr, Context, StaticSpellingKind::None, PBDPattern, /*init*/ nullptr,
VD->getDeclContext(), /*VarLoc*/ VD->getLoc()); VD->getDeclContext(), /*VarLoc*/ VD->getLoc());

View File

@@ -221,7 +221,7 @@ static DeclRefExpr *convertEnumToIndex(SmallVectorImpl<ASTNode> &stmts,
// generate: var indexVar // generate: var indexVar
Pattern *indexPat = new (C) NamedPattern(indexVar, /*implicit*/ true); Pattern *indexPat = new (C) NamedPattern(indexVar, /*implicit*/ true);
indexPat->setType(intType); indexPat->setType(intType);
indexPat = new (C) TypedPattern(indexPat, TypeLoc::withoutLoc(intType)); indexPat = TypedPattern::createImplicit(C, indexPat, intType);
indexPat->setType(intType); indexPat->setType(intType);
auto *indexBind = PatternBindingDecl::createImplicit( auto *indexBind = PatternBindingDecl::createImplicit(
C, StaticSpellingKind::None, indexPat, /*InitExpr*/ nullptr, funcDecl); C, StaticSpellingKind::None, indexPat, /*InitExpr*/ nullptr, funcDecl);
@@ -1105,9 +1105,7 @@ static ValueDecl *deriveHashable_hashValue(DerivedConformance &derived) {
Pattern *hashValuePat = new (C) NamedPattern(hashValueDecl, /*implicit*/true); Pattern *hashValuePat = new (C) NamedPattern(hashValueDecl, /*implicit*/true);
hashValuePat->setType(intType); hashValuePat->setType(intType);
hashValuePat hashValuePat = TypedPattern::createImplicit(C, hashValuePat, intType);
= new (C) TypedPattern(hashValuePat, TypeLoc::withoutLoc(intType),
/*implicit*/ true);
hashValuePat->setType(intType); hashValuePat->setType(intType);
auto *patDecl = PatternBindingDecl::createImplicit( auto *patDecl = PatternBindingDecl::createImplicit(

View File

@@ -340,9 +340,7 @@ DerivedConformance::declareDerivedProperty(Identifier name,
Pattern *propPat = new (C) NamedPattern(propDecl, /*implicit*/ true); Pattern *propPat = new (C) NamedPattern(propDecl, /*implicit*/ true);
propPat->setType(propertyContextType); propPat->setType(propertyContextType);
propPat = new (C) TypedPattern(propPat, propPat = TypedPattern::createImplicit(C, propPat, propertyContextType);
TypeLoc::withoutLoc(propertyContextType),
/*implicit*/ true);
propPat->setType(propertyContextType); propPat->setType(propertyContextType);
auto *pbDecl = PatternBindingDecl::createImplicit( auto *pbDecl = PatternBindingDecl::createImplicit(

View File

@@ -699,7 +699,7 @@ static bool validateTypedPattern(TypeChecker &TC,
if (TP->hasType()) if (TP->hasType())
return TP->getType()->hasError(); return TP->getType()->hasError();
TypeLoc &TL = TP->getTypeLoc(); TypeLoc TL = TP->getTypeLoc();
bool hadError = TC.validateType(TL, resolution, options); bool hadError = TC.validateType(TL, resolution, options);
if (hadError) { if (hadError) {

View File

@@ -381,9 +381,11 @@ Expected<Pattern *> ModuleFile::readPattern(DeclContext *owningDC) {
return subPattern; return subPattern;
} }
auto result = new (getContext()) TypedPattern(subPattern.get(), TypeLoc(), auto type = getType(typeID);
auto result = new (getContext()) TypedPattern(subPattern.get(),
/*typeRepr*/nullptr,
isImplicit); isImplicit);
recordPatternType(result, getType(typeID)); recordPatternType(result, type);
restoreOffset.reset(); restoreOffset.reset();
return result; return result;
} }

View File

@@ -1,43 +1,40 @@
// RUN: %empty-directory(%t) // RUN: %empty-directory(%t)
// RUN: %target-swift-frontend -emit-interface-path %t.swiftinterface -emit-module -o /dev/null %s // RUN: %target-swift-frontend -emit-interface-path %t.swiftinterface -emit-module -o /dev/null %s
// RUN: %FileCheck %s < %t.swiftinterface // RUN: %FileCheck %s < %t.swiftinterface --check-prefix CHECK --check-prefix COMMON
// RUN: %target-swift-frontend -emit-interface-path %t-resilient.swiftinterface -enable-resilience -emit-module -o /dev/null %s // RUN: %target-swift-frontend -emit-interface-path %t-resilient.swiftinterface -enable-resilience -emit-module -o /dev/null %s
// RUN: %FileCheck %s --check-prefix RESILIENT < %t-resilient.swiftinterface // RUN: %FileCheck %s --check-prefix RESILIENT --check-prefix COMMON < %t-resilient.swiftinterface
// RUN: %target-swift-frontend -emit-module -o %t/Test.swiftmodule %t.swiftinterface -disable-objc-attr-requires-foundation-module // RUN: %target-swift-frontend -emit-module -o %t/Test.swiftmodule %t.swiftinterface -disable-objc-attr-requires-foundation-module
// FIXME(rdar44144435): %target-swift-frontend -emit-module -o /dev/null -merge-modules %t/Test.swiftmodule -emit-interface-path - | %FileCheck %s // RUN: %target-swift-frontend -emit-module -o /dev/null -merge-modules %t/Test.swiftmodule -module-name Test -emit-interface-path - | %FileCheck %s --check-prefix CHECK --check-prefix COMMON
// RUN: %target-swift-frontend -emit-module -o %t/TestResilient.swiftmodule -enable-resilience %t.swiftinterface -disable-objc-attr-requires-foundation-module // RUN: %target-swift-frontend -emit-module -o %t/TestResilient.swiftmodule -enable-resilience %t.swiftinterface -disable-objc-attr-requires-foundation-module
// FIXME(rdar44144435): %target-swift-frontend -emit-module -o /dev/null -merge-modules %t/Test.swiftmodule -enable-resilience -emit-interface-path - | %FileCheck %s // RUN: %target-swift-frontend -emit-module -o /dev/null -merge-modules %t/TestResilient.swiftmodule -module-name TestResilient -enable-resilience -emit-interface-path - | %FileCheck %s --check-prefix RESILIENT --check-prefix COMMON
// CHECK: struct MyStruct {{{$}} // COMMON: struct MyStruct {{{$}}
// RESILIENT: struct MyStruct {{{$}}
public struct MyStruct { public struct MyStruct {
// CHECK-NEXT: var publicVar: Int64{{$}} // COMMON-NEXT: var publicVar: [[INT64:(Swift\.)?Int64]]{{$}}
// RESILIENT-NEXT: var publicVar: Int64{{$}}
public var publicVar: Int64 public var publicVar: Int64
// CHECK-NEXT: let publicLet: Bool{{$}} // COMMON-NEXT: let publicLet: [[BOOL:(Swift\.)?Bool]]{{$}}
// RESILIENT-NEXT: let publicLet: Bool{{$}}
public let publicLet: Bool public let publicLet: Bool
// CHECK-NEXT: internal var _: Int64{{$}} // CHECK-NEXT: internal var _: [[INT64]]{{$}}
// RESILIENT-NOT: internal var _: Int64{{$}} // RESILIENT-NOT: internal var _: [[INT64]]{{$}}
var internalVar: Int64 var internalVar: Int64
// CHECK-NEXT: internal let _: Bool{{$}} // CHECK-NEXT: internal let _: [[BOOL]]{{$}}
// RESILIENT-NOT: internal let _: Bool{{$}} // RESILIENT-NOT: internal let _: [[BOOL]]{{$}}
let internalLet: Bool let internalLet: Bool
// CHECK-NEXT: private var _: Int64{{$}} // CHECK-NEXT: private var _: [[INT64]]{{$}}
// RESILIENT-NOT: private var _: Int64{{$}} // RESILIENT-NOT: private var _: [[INT64]]{{$}}
private var privateVar: Int64 private var privateVar: Int64
// CHECK-NEXT: private let _: Bool{{$}} // CHECK-NEXT: private let _: [[BOOL]]{{$}}
// RESILIENT-NOT: private let _: Bool{{$}} // RESILIENT-NOT: private let _: [[BOOL]]{{$}}
private let privateLet: Bool private let privateLet: Bool
// CHECK-NOT: private var // CHECK-NOT: private var
@@ -50,39 +47,34 @@ public struct MyStruct {
// RESILIENT-NOT: private static var // RESILIENT-NOT: private static var
private static var staticPrivateVar: Int64 = 0 private static var staticPrivateVar: Int64 = 0
// CHECK-NEXT: var publicEndVar: Int64{{$}} // COMMON: var publicEndVar: [[INT64]]{{$}}
// RESILIENT-NEXT: var publicEndVar: Int64{{$}}
public var publicEndVar: Int64 = 0 public var publicEndVar: Int64 = 0
// CHECK: }{{$}} // COMMON: }{{$}}
// RESILIENT: }{{$}}
} }
// CHECK: class MyClass {{{$}} // COMMON: class MyClass {{{$}}
// RESILIENT: class MyClass {{{$}}
public class MyClass { public class MyClass {
// CHECK-NEXT: var publicVar: Int64{{$}} // COMMON-NEXT: var publicVar: [[INT64]]{{$}}
// RESILIENT-NEXT: var publicVar: Int64{{$}}
public var publicVar: Int64 = 0 public var publicVar: Int64 = 0
// CHECK-NEXT: let publicLet: Bool{{$}} // COMMON-NEXT: let publicLet: [[BOOL]]{{$}}
// RESILIENT-NEXT: let publicLet: Bool{{$}}
public let publicLet: Bool = true public let publicLet: Bool = true
// CHECK-NEXT: internal var _: Int64{{$}} // CHECK-NEXT: internal var _: [[INT64]]{{$}}
// RESILIENT-NOT: internal var _: Int64{{$}} // RESILIENT-NOT: internal var _: [[INT64]]{{$}}
var internalVar: Int64 = 0 var internalVar: Int64 = 0
// CHECK-NEXT: internal let _: Bool{{$}} // CHECK-NEXT: internal let _: [[BOOL]]{{$}}
// RESILIENT-NOT: internal let _: Bool{{$}} // RESILIENT-NOT: internal let _: [[BOOL]]{{$}}
let internalLet: Bool = true let internalLet: Bool = true
// CHECK-NEXT: private var _: Int64{{$}} // CHECK-NEXT: private var _: [[INT64]]{{$}}
// RESILIENT-NOT: private var _: Int64{{$}} // RESILIENT-NOT: private var _: [[INT64]]{{$}}
private var privateVar: Int64 = 0 private var privateVar: Int64 = 0
// CHECK-NEXT: private let _: Bool{{$}} // CHECK-NEXT: private let _: [[BOOL]]{{$}}
// RESILIENT-NOT: private let _: Bool{{$}} // RESILIENT-NOT: private let _: [[BOOL]]{{$}}
private let privateLet: Bool = true private let privateLet: Bool = true
// CHECK-NOT: private var // CHECK-NOT: private var
@@ -95,12 +87,10 @@ public class MyClass {
// RESILIENT-NOT: private static var // RESILIENT-NOT: private static var
private static var staticPrivateVar: Int64 = 0 private static var staticPrivateVar: Int64 = 0
// CHECK-NEXT: var publicEndVar: Int64{{$}} // COMMON: var publicEndVar: [[INT64]]{{$}}
// RESILIENT-NEXT: var publicEndVar: Int64{{$}}
public var publicEndVar: Int64 = 0 public var publicEndVar: Int64 = 0
public init() {} public init() {}
// CHECK: }{{$}} // COMMON: }{{$}}
// RESILIENT: }{{$}}
} }