Skip to content

Commit 464761e

Browse files
authored
Merge pull request #24924 from xedin/rdar-50679161
[Diagnostics] Fix incorrect metatype check which leads to crashes
2 parents fe9b48c + ce61dfe commit 464761e

File tree

3 files changed

+83
-50
lines changed

3 files changed

+83
-50
lines changed

lib/Sema/CSDiagnostics.cpp

Lines changed: 45 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -2016,7 +2016,7 @@ bool AllowTypeOrInstanceMemberFailure::diagnoseAsError() {
20162016
// comes up and is otherwise non-obvious what is going on.
20172017

20182018
if (Name.isSimpleName(DeclBaseName::createConstructor()) &&
2019-
!BaseType->getRValueType()->is<AnyMetatypeType>()) {
2019+
!BaseType->is<AnyMetatypeType>()) {
20202020
if (auto ctorRef = dyn_cast<UnresolvedDotExpr>(getRawAnchor())) {
20212021
if (isa<SuperRefExpr>(ctorRef->getBase())) {
20222022
emitDiagnostic(loc, diag::super_initializer_not_in_initializer);
@@ -2063,8 +2063,8 @@ bool AllowTypeOrInstanceMemberFailure::diagnoseAsError() {
20632063
}
20642064

20652065
if (BaseType->is<AnyMetatypeType>() && !member->isStatic()) {
2066-
auto instanceTy = BaseType->getRValueType();
2067-
2066+
auto instanceTy = BaseType;
2067+
20682068
if (auto *AMT = instanceTy->getAs<AnyMetatypeType>()) {
20692069
instanceTy = AMT->getInstanceType();
20702070
}
@@ -2147,60 +2147,60 @@ bool AllowTypeOrInstanceMemberFailure::diagnoseAsError() {
21472147
// to replace the metatype with 'Self'
21482148
// error saying the lookup cannot be on a protocol metatype
21492149
Optional<InFlightDiagnostic> Diag;
2150-
auto baseObjTy = BaseType->getRValueType();
2151-
2152-
if (auto metatypeTy = baseObjTy->getAs<MetatypeType>()) {
2150+
auto baseTy = BaseType;
2151+
2152+
if (auto metatypeTy = baseTy->getAs<AnyMetatypeType>()) {
21532153
auto instanceTy = metatypeTy->getInstanceType();
2154-
2154+
21552155
// This will only happen if we have an unresolved dot expression
21562156
// (.foo) where foo is a protocol member and the contextual type is
21572157
// an optional protocol metatype.
21582158
if (auto objectTy = instanceTy->getOptionalObjectType()) {
21592159
instanceTy = objectTy;
2160-
baseObjTy = MetatypeType::get(objectTy);
2160+
baseTy = MetatypeType::get(objectTy);
21612161
}
2162-
assert(instanceTy->isExistentialType());
2163-
2164-
// Give a customized message if we're accessing a member type
2165-
// of a protocol -- otherwise a diagnostic talking about
2166-
// static members doesn't make a whole lot of sense
2167-
if (auto TAD = dyn_cast<TypeAliasDecl>(member)) {
2168-
Diag.emplace(emitDiagnostic(loc, diag::typealias_outside_of_protocol,
2169-
TAD->getName()));
2170-
} else if (auto ATD = dyn_cast<AssociatedTypeDecl>(member)) {
2171-
Diag.emplace(emitDiagnostic(loc, diag::assoc_type_outside_of_protocol,
2172-
ATD->getName()));
2173-
} else if (isa<ConstructorDecl>(member)) {
2174-
Diag.emplace(emitDiagnostic(loc, diag::construct_protocol_by_name,
2175-
instanceTy));
2176-
} else {
2177-
Diag.emplace(emitDiagnostic(loc,
2178-
diag::could_not_use_type_member_on_protocol_metatype,
2179-
baseObjTy, Name));
2180-
}
2181-
2182-
Diag->highlight(baseRange).highlight(getAnchor()->getSourceRange());
2183-
2184-
// See through function decl context
2185-
if (auto parent = cs.DC->getInnermostTypeContext()) {
2186-
// If we are in a protocol extension of 'Proto' and we see
2187-
// 'Proto.static', suggest 'Self.static'
2188-
if (auto extensionContext = parent->getExtendedProtocolDecl()) {
2189-
if (extensionContext->getDeclaredType()->isEqual(instanceTy)) {
2190-
Diag->fixItReplace(getAnchor()->getSourceRange(), "Self");
2162+
2163+
if (instanceTy->isExistentialType()) {
2164+
// Give a customized message if we're accessing a member type
2165+
// of a protocol -- otherwise a diagnostic talking about
2166+
// static members doesn't make a whole lot of sense
2167+
if (auto TAD = dyn_cast<TypeAliasDecl>(member)) {
2168+
Diag.emplace(emitDiagnostic(loc, diag::typealias_outside_of_protocol,
2169+
TAD->getName()));
2170+
} else if (auto ATD = dyn_cast<AssociatedTypeDecl>(member)) {
2171+
Diag.emplace(emitDiagnostic(loc, diag::assoc_type_outside_of_protocol,
2172+
ATD->getName()));
2173+
} else if (isa<ConstructorDecl>(member)) {
2174+
Diag.emplace(emitDiagnostic(loc, diag::construct_protocol_by_name,
2175+
instanceTy));
2176+
} else {
2177+
Diag.emplace(emitDiagnostic(
2178+
loc, diag::could_not_use_type_member_on_protocol_metatype, baseTy,
2179+
Name));
2180+
}
2181+
2182+
Diag->highlight(baseRange).highlight(getAnchor()->getSourceRange());
2183+
2184+
// See through function decl context
2185+
if (auto parent = cs.DC->getInnermostTypeContext()) {
2186+
// If we are in a protocol extension of 'Proto' and we see
2187+
// 'Proto.static', suggest 'Self.static'
2188+
if (auto extensionContext = parent->getExtendedProtocolDecl()) {
2189+
if (extensionContext->getDeclaredType()->isEqual(instanceTy)) {
2190+
Diag->fixItReplace(getAnchor()->getSourceRange(), "Self");
2191+
}
21912192
}
21922193
}
2194+
2195+
return true;
21932196
}
2194-
2195-
return true;
21962197
}
21972198

21982199
// If this is a reference to a static member by one of the key path
21992200
// components, let's provide a tailored diagnostic and return because
22002201
// that is unsupported so there is no fix-it.
22012202
if (locator->isForKeyPathComponent()) {
2202-
InvalidStaticMemberRefInKeyPath failure(expr, getConstraintSystem(),
2203-
member, locator);
2203+
InvalidStaticMemberRefInKeyPath failure(expr, cs, member, locator);
22042204
return failure.diagnoseAsError();
22052205
}
22062206

@@ -2209,13 +2209,13 @@ bool AllowTypeOrInstanceMemberFailure::diagnoseAsError() {
22092209
loc, diag::could_not_use_enum_element_on_instance, Name));
22102210
} else {
22112211
Diag.emplace(emitDiagnostic(
2212-
loc, diag::could_not_use_type_member_on_instance, baseObjTy, Name));
2212+
loc, diag::could_not_use_type_member_on_instance, baseTy, Name));
22132213
}
22142214

22152215
Diag->highlight(getAnchor()->getSourceRange());
22162216

22172217
if (Name.isSimpleName(DeclBaseName::createConstructor()) &&
2218-
!baseObjTy->is<AnyMetatypeType>()) {
2218+
!baseTy->is<AnyMetatypeType>()) {
22192219
if (auto ctorRef = dyn_cast<UnresolvedDotExpr>(getRawAnchor())) {
22202220
SourceRange fixItRng = ctorRef->getNameLoc().getSourceRange();
22212221
Diag->fixItInsert(fixItRng.Start, "type(of: ");
@@ -2233,7 +2233,7 @@ bool AllowTypeOrInstanceMemberFailure::diagnoseAsError() {
22332233

22342234
// Try to provide a fix-it that only contains a '.'
22352235
if (contextualType) {
2236-
if (baseObjTy->isEqual(contextualType)) {
2236+
if (baseTy->isEqual(contextualType)) {
22372237
Diag->fixItInsert(loc, ".");
22382238
return true;
22392239
}
@@ -2263,7 +2263,7 @@ bool AllowTypeOrInstanceMemberFailure::diagnoseAsError() {
22632263
// since the type can be inferred
22642264
Type secondArgType =
22652265
lastCS->getType(binaryExpr->getArg()->getElement(1));
2266-
if (secondArgType->isEqual(baseObjTy)) {
2266+
if (secondArgType->isEqual(baseTy)) {
22672267
Diag->fixItInsert(loc, ".");
22682268
return true;
22692269
}

lib/Sema/CSDiagnostics.h

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -810,11 +810,12 @@ class AllowTypeOrInstanceMemberFailure final : public FailureDiagnostic {
810810
DeclName Name;
811811

812812
public:
813-
AllowTypeOrInstanceMemberFailure(Expr *root, ConstraintSystem &cs, Type baseType,
814-
DeclName memberName, ConstraintLocator *locator)
815-
: FailureDiagnostic(root, cs, locator), BaseType(baseType),
816-
Name(memberName) {}
817-
813+
AllowTypeOrInstanceMemberFailure(Expr *root, ConstraintSystem &cs,
814+
Type baseType, DeclName memberName,
815+
ConstraintLocator *locator)
816+
: FailureDiagnostic(root, cs, locator),
817+
BaseType(baseType->getRValueType()), Name(memberName) {}
818+
818819
bool diagnoseAsError() override;
819820
};
820821
class PartialApplicationFailure final : public FailureDiagnostic {

test/Constraints/members.swift

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -577,3 +577,35 @@ extension S_Min : CustomStringConvertible {
577577
return "\(min)" // Ok
578578
}
579579
}
580+
581+
// rdar://problem/50679161
582+
583+
func rdar50679161() {
584+
struct Point {}
585+
586+
struct S {
587+
var w, h: Point
588+
}
589+
590+
struct Q {
591+
init(a: Int, b: Int) {}
592+
init(a: Point, b: Point) {}
593+
}
594+
595+
func foo() {
596+
_ = { () -> Void in
597+
var foo = S
598+
// expected-error@-1 {{expected member name or constructor call after type name}}
599+
// expected-note@-2 {{add arguments after the type to construct a value of the type}}
600+
// expected-note@-3 {{use '.self' to reference the type object}}
601+
if let v = Int?(1) {
602+
var _ = Q(
603+
a: v + foo.w,
604+
// expected-error@-1 {{instance member 'w' cannot be used on type 'S'}}
605+
b: v + foo.h
606+
// expected-error@-1 {{instance member 'h' cannot be used on type 'S'}}
607+
)
608+
}
609+
}
610+
}
611+
}

0 commit comments

Comments
 (0)