mirror of
https://github.com/apple/swift.git
synced 2025-12-21 12:14:44 +01:00
Strip TypeLoc from EnumElementPattern
This commit is contained in:
@@ -24,7 +24,6 @@
|
||||
#include "swift/Basic/LLVM.h"
|
||||
#include "swift/AST/Type.h"
|
||||
#include "swift/AST/Types.h"
|
||||
#include "swift/AST/TypeLoc.h"
|
||||
#include "swift/AST/TypeAlignments.h"
|
||||
#include "swift/Basic/InlineBitfield.h"
|
||||
#include "swift/Basic/OptionSet.h"
|
||||
@@ -35,6 +34,7 @@ namespace swift {
|
||||
class Expr;
|
||||
enum class CheckedCastKind : unsigned;
|
||||
class TypeExpr;
|
||||
class TypeLoc;
|
||||
|
||||
/// PatternKind - The classification of different kinds of
|
||||
/// value-matching pattern.
|
||||
@@ -503,7 +503,7 @@ public:
|
||||
/// case, then the value is extracted. If there is a subpattern, it is then
|
||||
/// matched against the associated value for the case.
|
||||
class EnumElementPattern : public Pattern {
|
||||
TypeLoc ParentType;
|
||||
TypeExpr *ParentType;
|
||||
SourceLoc DotLoc;
|
||||
DeclNameLoc NameLoc;
|
||||
DeclNameRef Name;
|
||||
@@ -511,27 +511,23 @@ class EnumElementPattern : public Pattern {
|
||||
Pattern /*nullable*/ *SubPattern;
|
||||
|
||||
public:
|
||||
EnumElementPattern(TypeLoc ParentType, SourceLoc DotLoc, DeclNameLoc NameLoc,
|
||||
DeclNameRef Name, EnumElementDecl *Element,
|
||||
Pattern *SubPattern)
|
||||
: Pattern(PatternKind::EnumElement),
|
||||
ParentType(ParentType), DotLoc(DotLoc), NameLoc(NameLoc), Name(Name),
|
||||
ElementDeclOrUnresolvedOriginalExpr(Element),
|
||||
SubPattern(SubPattern) { }
|
||||
EnumElementPattern(TypeExpr *ParentType, SourceLoc DotLoc,
|
||||
DeclNameLoc NameLoc, DeclNameRef Name,
|
||||
EnumElementDecl *Element, Pattern *SubPattern)
|
||||
: Pattern(PatternKind::EnumElement), ParentType(ParentType),
|
||||
DotLoc(DotLoc), NameLoc(NameLoc), Name(Name),
|
||||
ElementDeclOrUnresolvedOriginalExpr(Element), SubPattern(SubPattern) {
|
||||
assert(ParentType && "Missing parent type?");
|
||||
}
|
||||
|
||||
/// Create an unresolved EnumElementPattern for a `.foo` pattern relying on
|
||||
/// contextual type.
|
||||
EnumElementPattern(SourceLoc DotLoc,
|
||||
DeclNameLoc NameLoc,
|
||||
DeclNameRef Name,
|
||||
Pattern *SubPattern,
|
||||
Expr *UnresolvedOriginalExpr)
|
||||
: Pattern(PatternKind::EnumElement),
|
||||
ParentType(), DotLoc(DotLoc), NameLoc(NameLoc), Name(Name),
|
||||
EnumElementPattern(SourceLoc DotLoc, DeclNameLoc NameLoc, DeclNameRef Name,
|
||||
Pattern *SubPattern, Expr *UnresolvedOriginalExpr)
|
||||
: Pattern(PatternKind::EnumElement), ParentType(nullptr), DotLoc(DotLoc),
|
||||
NameLoc(NameLoc), Name(Name),
|
||||
ElementDeclOrUnresolvedOriginalExpr(UnresolvedOriginalExpr),
|
||||
SubPattern(SubPattern) {
|
||||
|
||||
}
|
||||
SubPattern(SubPattern) {}
|
||||
|
||||
bool hasSubPattern() const { return SubPattern; }
|
||||
|
||||
@@ -543,10 +539,6 @@ public:
|
||||
return SubPattern;
|
||||
}
|
||||
|
||||
bool isParentTypeImplicit() {
|
||||
return !ParentType.hasLocation();
|
||||
}
|
||||
|
||||
void setSubPattern(Pattern *p) { SubPattern = p; }
|
||||
|
||||
DeclNameRef getName() const { return Name; }
|
||||
@@ -567,21 +559,14 @@ public:
|
||||
|
||||
DeclNameLoc getNameLoc() const { return NameLoc; }
|
||||
SourceLoc getLoc() const { return NameLoc.getBaseNameLoc(); }
|
||||
SourceLoc getStartLoc() const {
|
||||
return ParentType.hasLocation() ? ParentType.getSourceRange().Start :
|
||||
DotLoc.isValid() ? DotLoc
|
||||
: NameLoc.getBaseNameLoc();
|
||||
}
|
||||
SourceLoc getEndLoc() const {
|
||||
if (SubPattern && SubPattern->getSourceRange().isValid()) {
|
||||
return SubPattern->getSourceRange().End;
|
||||
}
|
||||
return NameLoc.getEndLoc();
|
||||
}
|
||||
SourceLoc getStartLoc() const;
|
||||
SourceLoc getEndLoc() const;
|
||||
SourceRange getSourceRange() const { return {getStartLoc(), getEndLoc()}; }
|
||||
|
||||
TypeLoc &getParentType() { return ParentType; }
|
||||
TypeLoc getParentType() const { return ParentType; }
|
||||
TypeRepr *getParentTypeRepr() const;
|
||||
|
||||
void setParentType(Type ty);
|
||||
Type getParentType() const;
|
||||
|
||||
static bool classof(const Pattern *P) {
|
||||
return P->getKind() == PatternKind::EnumElement;
|
||||
|
||||
@@ -514,8 +514,7 @@ namespace {
|
||||
void visitEnumElementPattern(EnumElementPattern *P) {
|
||||
printCommon(P, "pattern_enum_element");
|
||||
OS << ' ';
|
||||
P->getParentType().getType().print(
|
||||
PrintWithColorRAII(OS, TypeColor).getOS());
|
||||
P->getParentType().print(PrintWithColorRAII(OS, TypeColor).getOS());
|
||||
PrintWithColorRAII(OS, IdentifierColor) << '.' << P->getName();
|
||||
if (P->hasSubPattern()) {
|
||||
OS << '\n';
|
||||
|
||||
@@ -1698,8 +1698,8 @@ Pattern *Traversal::visitIsPattern(IsPattern *P) {
|
||||
}
|
||||
|
||||
Pattern *Traversal::visitEnumElementPattern(EnumElementPattern *P) {
|
||||
if (!P->isParentTypeImplicit())
|
||||
if (doIt(P->getParentType()))
|
||||
if (auto *TR = P->getParentTypeRepr())
|
||||
if (doIt(TR))
|
||||
return nullptr;
|
||||
|
||||
if (!P->hasSubPattern())
|
||||
|
||||
@@ -466,6 +466,7 @@ SourceRange IsPattern::getSourceRange() const {
|
||||
|
||||
Type IsPattern::getCastType() const { return CastType->getInstanceType(); }
|
||||
void IsPattern::setCastType(Type type) {
|
||||
assert(type);
|
||||
CastType->setType(MetatypeType::get(type));
|
||||
}
|
||||
|
||||
@@ -479,6 +480,40 @@ ExprPattern::ExprPattern(Expr *e, bool isResolved, Expr *matchExpr,
|
||||
assert(!matchExpr || e->isImplicit() == matchExpr->isImplicit());
|
||||
}
|
||||
|
||||
SourceLoc EnumElementPattern::getStartLoc() const {
|
||||
return (ParentType && !ParentType->isImplicit())
|
||||
? ParentType->getSourceRange().Start
|
||||
: DotLoc.isValid() ? DotLoc : NameLoc.getBaseNameLoc();
|
||||
}
|
||||
|
||||
SourceLoc EnumElementPattern::getEndLoc() const {
|
||||
if (SubPattern && SubPattern->getSourceRange().isValid()) {
|
||||
return SubPattern->getSourceRange().End;
|
||||
}
|
||||
return NameLoc.getEndLoc();
|
||||
}
|
||||
|
||||
TypeRepr *EnumElementPattern::getParentTypeRepr() const {
|
||||
if (!ParentType)
|
||||
return nullptr;
|
||||
return ParentType->getTypeRepr();
|
||||
}
|
||||
|
||||
Type EnumElementPattern::getParentType() const {
|
||||
if (!ParentType)
|
||||
return Type();
|
||||
return ParentType->getInstanceType();
|
||||
}
|
||||
|
||||
void EnumElementPattern::setParentType(Type type) {
|
||||
assert(type);
|
||||
if (ParentType) {
|
||||
ParentType->setType(MetatypeType::get(type));
|
||||
} else {
|
||||
ParentType = TypeExpr::createImplicit(type, type->getASTContext());
|
||||
}
|
||||
}
|
||||
|
||||
SourceLoc ExprPattern::getLoc() const {
|
||||
return getSubExpr()->getLoc();
|
||||
}
|
||||
|
||||
@@ -1481,11 +1481,6 @@ namespace {
|
||||
Type resolveTypeReferenceInExpression(TypeRepr *repr,
|
||||
TypeResolverContext resCtx) {
|
||||
TypeLoc loc(repr);
|
||||
return resolveTypeReferenceInExpression(loc, resCtx);
|
||||
}
|
||||
|
||||
Type resolveTypeReferenceInExpression(TypeLoc &loc,
|
||||
TypeResolverContext resCtx) {
|
||||
TypeResolutionOptions options(resCtx);
|
||||
options |= TypeResolutionFlags::AllowUnboundGenerics;
|
||||
bool hadError = TypeChecker::validateType(
|
||||
@@ -2581,10 +2576,16 @@ namespace {
|
||||
CS.getConstraintLocator(locator),
|
||||
TVO_CanBindToLValue | TVO_CanBindToNoEscape);
|
||||
FunctionRefKind functionRefKind = FunctionRefKind::Compound;
|
||||
if (!enumPattern->getParentType().isNull()) {
|
||||
if (enumPattern->getParentType() || enumPattern->getParentTypeRepr()) {
|
||||
// Resolve the parent type.
|
||||
Type parentType = resolveTypeReferenceInExpression(
|
||||
enumPattern->getParentType(), TypeResolverContext::InExpression);
|
||||
Type parentType = [&]() -> Type {
|
||||
if (auto preTy = enumPattern->getParentType()) {
|
||||
return preTy;
|
||||
}
|
||||
return resolveTypeReferenceInExpression(
|
||||
enumPattern->getParentTypeRepr(),
|
||||
TypeResolverContext::InExpression);
|
||||
}();
|
||||
|
||||
if (!parentType)
|
||||
return Type();
|
||||
|
||||
@@ -212,8 +212,8 @@ deriveBodyCodingKey_enum_stringValue(AbstractFunctionDecl *strValDecl, void *) {
|
||||
} else {
|
||||
SmallVector<ASTNode, 4> cases;
|
||||
for (auto *elt : elements) {
|
||||
auto *pat = new (C) EnumElementPattern(TypeLoc::withoutLoc(enumType),
|
||||
SourceLoc(), DeclNameLoc(),
|
||||
auto *baseTE = TypeExpr::createImplicit(enumType, C);
|
||||
auto *pat = new (C) EnumElementPattern(baseTE, SourceLoc(), DeclNameLoc(),
|
||||
DeclNameRef(), elt, nullptr);
|
||||
pat->setImplicit();
|
||||
|
||||
|
||||
@@ -137,20 +137,20 @@ deriveBodyComparable_enum_hasAssociatedValues_lt(AbstractFunctionDecl *ltDecl, v
|
||||
SmallVector<VarDecl*, 4> lhsPayloadVars;
|
||||
auto lhsSubpattern = DerivedConformance::enumElementPayloadSubpattern(elt, 'l', ltDecl,
|
||||
lhsPayloadVars);
|
||||
auto lhsElemPat = new (C) EnumElementPattern(TypeLoc::withoutLoc(enumType),
|
||||
SourceLoc(), DeclNameLoc(),
|
||||
DeclNameRef(), elt,
|
||||
lhsSubpattern);
|
||||
auto *lhsBaseTE = TypeExpr::createImplicit(enumType, C);
|
||||
auto lhsElemPat =
|
||||
new (C) EnumElementPattern(lhsBaseTE, SourceLoc(), DeclNameLoc(),
|
||||
DeclNameRef(), elt, lhsSubpattern);
|
||||
lhsElemPat->setImplicit();
|
||||
|
||||
// .<elt>(let r0, let r1, ...)
|
||||
SmallVector<VarDecl*, 4> rhsPayloadVars;
|
||||
auto rhsSubpattern = DerivedConformance::enumElementPayloadSubpattern(elt, 'r', ltDecl,
|
||||
rhsPayloadVars);
|
||||
auto rhsElemPat = new (C) EnumElementPattern(TypeLoc::withoutLoc(enumType),
|
||||
SourceLoc(), DeclNameLoc(),
|
||||
DeclNameRef(), elt,
|
||||
rhsSubpattern);
|
||||
auto *rhsBaseTE = TypeExpr::createImplicit(enumType, C);
|
||||
auto rhsElemPat =
|
||||
new (C) EnumElementPattern(rhsBaseTE, SourceLoc(), DeclNameLoc(),
|
||||
DeclNameRef(), elt, rhsSubpattern);
|
||||
rhsElemPat->setImplicit();
|
||||
|
||||
auto hasBoundDecls = !lhsPayloadVars.empty();
|
||||
|
||||
@@ -259,20 +259,20 @@ deriveBodyEquatable_enum_hasAssociatedValues_eq(AbstractFunctionDecl *eqDecl,
|
||||
SmallVector<VarDecl*, 3> lhsPayloadVars;
|
||||
auto lhsSubpattern = DerivedConformance::enumElementPayloadSubpattern(elt, 'l', eqDecl,
|
||||
lhsPayloadVars);
|
||||
auto lhsElemPat = new (C) EnumElementPattern(TypeLoc::withoutLoc(enumType),
|
||||
SourceLoc(), DeclNameLoc(),
|
||||
DeclNameRef(), elt,
|
||||
lhsSubpattern);
|
||||
auto *lhsBaseTE = TypeExpr::createImplicit(enumType, C);
|
||||
auto lhsElemPat =
|
||||
new (C) EnumElementPattern(lhsBaseTE, SourceLoc(), DeclNameLoc(),
|
||||
DeclNameRef(), elt, lhsSubpattern);
|
||||
lhsElemPat->setImplicit();
|
||||
|
||||
// .<elt>(let r0, let r1, ...)
|
||||
SmallVector<VarDecl*, 3> rhsPayloadVars;
|
||||
auto rhsSubpattern = DerivedConformance::enumElementPayloadSubpattern(elt, 'r', eqDecl,
|
||||
rhsPayloadVars);
|
||||
auto rhsElemPat = new (C) EnumElementPattern(TypeLoc::withoutLoc(enumType),
|
||||
SourceLoc(), DeclNameLoc(),
|
||||
DeclNameRef(), elt,
|
||||
rhsSubpattern);
|
||||
auto *rhsBaseTE = TypeExpr::createImplicit(enumType, C);
|
||||
auto rhsElemPat =
|
||||
new (C) EnumElementPattern(rhsBaseTE, SourceLoc(), DeclNameLoc(),
|
||||
DeclNameRef(), elt, rhsSubpattern);
|
||||
rhsElemPat->setImplicit();
|
||||
|
||||
auto hasBoundDecls = !lhsPayloadVars.empty();
|
||||
@@ -748,12 +748,12 @@ deriveBodyHashable_enum_hasAssociatedValues_hashInto(
|
||||
// case A, B(Int), C(String, Int)
|
||||
// @derived func hash(into hasher: inout Hasher) {
|
||||
// switch self {
|
||||
// case A:
|
||||
// case .A:
|
||||
// hasher.combine(0)
|
||||
// case B(let a0):
|
||||
// case .B(let a0):
|
||||
// hasher.combine(1)
|
||||
// hasher.combine(a0)
|
||||
// case C(let a0, let a1):
|
||||
// case .C(let a0, let a1):
|
||||
// hasher.combine(2)
|
||||
// hasher.combine(a0)
|
||||
// hasher.combine(a1)
|
||||
@@ -783,10 +783,9 @@ deriveBodyHashable_enum_hasAssociatedValues_hashInto(
|
||||
|
||||
auto payloadPattern = DerivedConformance::enumElementPayloadSubpattern(elt, 'a', hashIntoDecl,
|
||||
payloadVars);
|
||||
auto pat = new (C) EnumElementPattern(TypeLoc::withoutLoc(enumType),
|
||||
SourceLoc(), DeclNameLoc(),
|
||||
DeclNameRef(elt->getBaseIdentifier()),
|
||||
elt, payloadPattern);
|
||||
auto pat = new (C) EnumElementPattern(
|
||||
TypeExpr::createImplicit(enumType, C), SourceLoc(), DeclNameLoc(),
|
||||
DeclNameRef(elt->getBaseIdentifier()), elt, payloadPattern);
|
||||
pat->setImplicit();
|
||||
|
||||
auto labelItem = CaseLabelItem(pat);
|
||||
|
||||
@@ -108,9 +108,9 @@ deriveBodyRawRepresentable_raw(AbstractFunctionDecl *toRawDecl, void *) {
|
||||
|
||||
SmallVector<ASTNode, 4> cases;
|
||||
for (auto elt : enumDecl->getAllElements()) {
|
||||
auto pat = new (C) EnumElementPattern(TypeLoc::withoutLoc(enumType),
|
||||
SourceLoc(), DeclNameLoc(),
|
||||
DeclNameRef(), elt, nullptr);
|
||||
auto pat = new (C)
|
||||
EnumElementPattern(TypeExpr::createImplicit(enumType, C), SourceLoc(),
|
||||
DeclNameLoc(), DeclNameRef(), elt, nullptr);
|
||||
pat->setImplicit();
|
||||
|
||||
auto labelItem = CaseLabelItem(pat);
|
||||
|
||||
@@ -548,9 +548,9 @@ DeclRefExpr *DerivedConformance::convertEnumToIndex(SmallVectorImpl<ASTNode> &st
|
||||
SmallVector<ASTNode, 4> cases;
|
||||
for (auto elt : enumDecl->getAllElements()) {
|
||||
// generate: case .<Case>:
|
||||
auto pat = new (C) EnumElementPattern(TypeLoc::withoutLoc(enumType),
|
||||
SourceLoc(), DeclNameLoc(),
|
||||
DeclNameRef(), elt, nullptr);
|
||||
auto pat = new (C)
|
||||
EnumElementPattern(TypeExpr::createImplicit(enumType, C), SourceLoc(),
|
||||
DeclNameLoc(), DeclNameRef(), elt, nullptr);
|
||||
pat->setImplicit();
|
||||
pat->setType(enumType);
|
||||
|
||||
|
||||
@@ -484,12 +484,12 @@ public:
|
||||
if (!referencedElement)
|
||||
return nullptr;
|
||||
|
||||
// Build a TypeRepr from the head of the full path.
|
||||
TypeLoc loc(repr);
|
||||
loc.setType(ty);
|
||||
return new (Context) EnumElementPattern(
|
||||
loc, ude->getDotLoc(), ude->getNameLoc(), ude->getName(),
|
||||
referencedElement, nullptr);
|
||||
auto *base =
|
||||
TypeExpr::createForMemberDecl(repr, ude->getNameLoc(), enumDecl);
|
||||
base->setType(MetatypeType::get(ty));
|
||||
return new (Context)
|
||||
EnumElementPattern(base, ude->getDotLoc(), ude->getNameLoc(),
|
||||
ude->getName(), referencedElement, nullptr);
|
||||
}
|
||||
|
||||
// A DeclRef 'E' that refers to an enum element forms an EnumElementPattern.
|
||||
@@ -499,9 +499,10 @@ public:
|
||||
return nullptr;
|
||||
|
||||
// Use the type of the enum from context.
|
||||
TypeLoc loc = TypeLoc::withoutLoc(
|
||||
elt->getParentEnum()->getDeclaredTypeInContext());
|
||||
return new (Context) EnumElementPattern(loc, SourceLoc(), de->getNameLoc(),
|
||||
auto enumTy = elt->getParentEnum()->getDeclaredTypeInContext();
|
||||
auto *base = TypeExpr::createImplicit(enumTy, Context);
|
||||
|
||||
return new (Context) EnumElementPattern(base, SourceLoc(), de->getNameLoc(),
|
||||
elt->createNameRef(), elt, nullptr);
|
||||
}
|
||||
Pattern *visitUnresolvedDeclRefExpr(UnresolvedDeclRefExpr *ude) {
|
||||
@@ -515,11 +516,11 @@ public:
|
||||
ude->getLoc())) {
|
||||
auto *enumDecl = referencedElement->getParentEnum();
|
||||
auto enumTy = enumDecl->getDeclaredTypeInContext();
|
||||
TypeLoc loc = TypeLoc::withoutLoc(enumTy);
|
||||
auto *base = TypeExpr::createImplicit(enumTy, Context);
|
||||
|
||||
return new (Context) EnumElementPattern(
|
||||
loc, SourceLoc(), ude->getNameLoc(), ude->getName(),
|
||||
referencedElement, nullptr);
|
||||
return new (Context)
|
||||
EnumElementPattern(base, SourceLoc(), ude->getNameLoc(),
|
||||
ude->getName(), referencedElement, nullptr);
|
||||
}
|
||||
|
||||
|
||||
@@ -549,7 +550,7 @@ public:
|
||||
|
||||
auto tailComponent = components.pop_back_val();
|
||||
EnumElementDecl *referencedElement = nullptr;
|
||||
TypeLoc loc;
|
||||
TypeExpr *baseTE = nullptr;
|
||||
|
||||
if (components.empty()) {
|
||||
// Only one component. Try looking up an enum element in context.
|
||||
@@ -560,7 +561,8 @@ public:
|
||||
return nullptr;
|
||||
|
||||
auto *enumDecl = referencedElement->getParentEnum();
|
||||
loc = TypeLoc::withoutLoc(enumDecl->getDeclaredTypeInContext());
|
||||
baseTE = TypeExpr::createImplicit(enumDecl->getDeclaredTypeInContext(),
|
||||
Context);
|
||||
} else {
|
||||
TypeResolutionOptions options = None;
|
||||
options |= TypeResolutionFlags::AllowUnboundGenerics;
|
||||
@@ -573,7 +575,8 @@ public:
|
||||
// See first if the entire repr resolves to a type.
|
||||
Type enumTy = TypeResolution::forContextual(DC, options)
|
||||
.resolveType(prefixRepr);
|
||||
if (!dyn_cast_or_null<EnumDecl>(enumTy->getAnyNominal()))
|
||||
auto *enumDecl = dyn_cast_or_null<EnumDecl>(enumTy->getAnyNominal());
|
||||
if (!enumDecl)
|
||||
return nullptr;
|
||||
|
||||
referencedElement
|
||||
@@ -583,18 +586,19 @@ public:
|
||||
if (!referencedElement)
|
||||
return nullptr;
|
||||
|
||||
loc = TypeLoc(prefixRepr);
|
||||
loc.setType(enumTy);
|
||||
baseTE = TypeExpr::createForMemberDecl(
|
||||
prefixRepr, tailComponent->getNameLoc(), enumDecl);
|
||||
baseTE->setType(MetatypeType::get(enumTy));
|
||||
}
|
||||
|
||||
assert(baseTE && baseTE->getType() && "Didn't initialize base expression?");
|
||||
assert(!isa<GenericIdentTypeRepr>(tailComponent) &&
|
||||
"should be handled above");
|
||||
|
||||
auto *subPattern = getSubExprPattern(ce->getArg());
|
||||
return new (Context) EnumElementPattern(
|
||||
loc, SourceLoc(), tailComponent->getNameLoc(),
|
||||
tailComponent->getNameRef(), referencedElement,
|
||||
subPattern);
|
||||
baseTE, SourceLoc(), tailComponent->getNameLoc(),
|
||||
tailComponent->getNameRef(), referencedElement, subPattern);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -1204,11 +1208,10 @@ Pattern *TypeChecker::coercePatternToType(ContextualPattern pattern,
|
||||
auto EP = cast<ExprPattern>(P);
|
||||
if (auto *NLE = dyn_cast<NilLiteralExpr>(EP->getSubExpr())) {
|
||||
auto *NoneEnumElement = Context.getOptionalNoneDecl();
|
||||
P = new (Context) EnumElementPattern(TypeLoc::withoutLoc(type),
|
||||
NLE->getLoc(),
|
||||
DeclNameLoc(NLE->getLoc()),
|
||||
NoneEnumElement->createNameRef(),
|
||||
NoneEnumElement, nullptr);
|
||||
auto *BaseTE = TypeExpr::createImplicit(type, Context);
|
||||
P = new (Context) EnumElementPattern(
|
||||
BaseTE, NLE->getLoc(), DeclNameLoc(NLE->getLoc()),
|
||||
NoneEnumElement->createNameRef(), NoneEnumElement, nullptr);
|
||||
return TypeChecker::coercePatternToType(
|
||||
pattern.forSubPattern(P, /*retainTopLevel=*/true), type, options);
|
||||
}
|
||||
@@ -1238,24 +1241,25 @@ Pattern *TypeChecker::coercePatternToType(ContextualPattern pattern,
|
||||
SmallVector<Type, 2> castTypeOptionals;
|
||||
castType->lookThroughAllOptionalTypes(castTypeOptionals);
|
||||
|
||||
// If we have extra optionals on the input type. Create ".Some" patterns
|
||||
// wrapping the isa pattern to balance out the optionals.
|
||||
// If we have extra optionals on the input type. Create ".some" patterns
|
||||
// wrapping the is pattern to balance out the optionals.
|
||||
int numExtraOptionals = inputTypeOptionals.size()-castTypeOptionals.size();
|
||||
if (numExtraOptionals > 0) {
|
||||
Pattern *sub = IP;
|
||||
for (int i = 0; i < numExtraOptionals; ++i) {
|
||||
auto extraOpts =
|
||||
llvm::drop_begin(inputTypeOptionals, castTypeOptionals.size());
|
||||
for (auto extraOptTy : llvm::reverse(extraOpts)) {
|
||||
auto some = Context.getOptionalDecl()->getUniqueElement(/*hasVal*/true);
|
||||
sub = new (Context) EnumElementPattern(TypeLoc(),
|
||||
IP->getStartLoc(),
|
||||
DeclNameLoc(IP->getEndLoc()),
|
||||
some->createNameRef(),
|
||||
nullptr, sub);
|
||||
auto *base = TypeExpr::createImplicit(extraOptTy, Context);
|
||||
sub = new (Context) EnumElementPattern(
|
||||
base, IP->getStartLoc(), DeclNameLoc(IP->getEndLoc()),
|
||||
some->createNameRef(), nullptr, sub);
|
||||
sub->setImplicit();
|
||||
}
|
||||
|
||||
P = sub;
|
||||
return coercePatternToType(
|
||||
pattern.forSubPattern(P, /*retainTopLevle=*/true), type, options);
|
||||
pattern.forSubPattern(P, /*retainTopLevel=*/true), type, options);
|
||||
}
|
||||
|
||||
CheckedCastKind castKind = TypeChecker::typeCheckCheckedCast(
|
||||
@@ -1405,7 +1409,7 @@ Pattern *TypeChecker::coercePatternToType(ContextualPattern pattern,
|
||||
// coercing to.
|
||||
assert(!EEP->getParentType().isNull()
|
||||
&& "enum with resolved element doesn't specify parent type?!");
|
||||
auto parentTy = EEP->getParentType().getType();
|
||||
auto parentTy = EEP->getParentType();
|
||||
// If the type matches exactly, use it.
|
||||
if (parentTy->isEqual(type)) {
|
||||
enumTy = type;
|
||||
@@ -1519,11 +1523,7 @@ Pattern *TypeChecker::coercePatternToType(ContextualPattern pattern,
|
||||
|
||||
EEP->setElementDecl(elt);
|
||||
EEP->setType(enumTy);
|
||||
|
||||
// Ensure that the type of our TypeLoc is fully resolved. If an unbound
|
||||
// generic type was spelled in the source (e.g. `case Optional.None:`) this
|
||||
// will fill in the generic parameters.
|
||||
EEP->getParentType().setType(enumTy);
|
||||
EEP->setParentType(enumTy);
|
||||
|
||||
// If we needed a cast, wrap the pattern in a cast pattern.
|
||||
if (castKind) {
|
||||
|
||||
@@ -486,12 +486,26 @@ func rdar63510989() {
|
||||
}
|
||||
|
||||
enum E {
|
||||
case foo(P?)
|
||||
case single(P?)
|
||||
case double(P??)
|
||||
case triple(P???)
|
||||
}
|
||||
|
||||
func test(e: E) {
|
||||
if case .foo(_ as Value) = e {} // Ok
|
||||
if case .foo(let v as Value) = e {} // Ok
|
||||
if case .single(_ as Value) = e {} // Ok
|
||||
if case .single(let v as Value) = e {} // Ok
|
||||
// expected-warning@-1 {{immutable value 'v' was never used; consider replacing with '_' or removing it}}
|
||||
if case .double(_ as Value) = e {} // Ok
|
||||
if case .double(let v as Value) = e {} // Ok
|
||||
// expected-warning@-1 {{immutable value 'v' was never used; consider replacing with '_' or removing it}}
|
||||
if case .double(let v as Value?) = e {} // Ok
|
||||
// expected-warning@-1 {{immutable value 'v' was never used; consider replacing with '_' or removing it}}
|
||||
if case .triple(_ as Value) = e {} // Ok
|
||||
if case .triple(let v as Value) = e {} // Ok
|
||||
// expected-warning@-1 {{immutable value 'v' was never used; consider replacing with '_' or removing it}}
|
||||
if case .triple(let v as Value?) = e {} // Ok
|
||||
// expected-warning@-1 {{immutable value 'v' was never used; consider replacing with '_' or removing it}}
|
||||
if case .triple(let v as Value??) = e {} // Ok
|
||||
// expected-warning@-1 {{immutable value 'v' was never used; consider replacing with '_' or removing it}}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user