Skip to content

Commit 9a52220

Browse files
committed
Sema: Check for invalid reference *before* checking for unsupported existential member access
1 parent 655a81c commit 9a52220

File tree

2 files changed

+62
-41
lines changed

2 files changed

+62
-41
lines changed

lib/Sema/CSSimplify.cpp

Lines changed: 49 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -7302,7 +7302,7 @@ performMemberLookup(ConstraintKind constraintKind, DeclNameRef memberName,
73027302
// Dig out the instance type and figure out what members of the instance type
73037303
// we are going to see.
73047304
auto baseTy = candidate.getBaseType();
7305-
auto baseObjTy = baseTy->getRValueType();
7305+
const auto baseObjTy = baseTy->getRValueType();
73067306

73077307
bool hasInstanceMembers = false;
73087308
bool hasInstanceMethods = false;
@@ -7349,18 +7349,6 @@ performMemberLookup(ConstraintKind constraintKind, DeclNameRef memberName,
73497349
hasInstanceMethods = true;
73507350
}
73517351

7352-
// If our base is an existential type, we can't make use of any
7353-
// member whose signature involves associated types.
7354-
if (instanceTy->isExistentialType()) {
7355-
if (auto *proto = decl->getDeclContext()->getSelfProtocolDecl()) {
7356-
if (!proto->isAvailableInExistential(decl)) {
7357-
result.addUnviable(candidate,
7358-
MemberLookupResult::UR_UnavailableInExistential);
7359-
return;
7360-
}
7361-
}
7362-
}
7363-
73647352
// If the invocation's argument expression has a favored type,
73657353
// use that information to determine whether a specific overload for
73667354
// the candidate should be favored.
@@ -7380,6 +7368,20 @@ performMemberLookup(ConstraintKind constraintKind, DeclNameRef memberName,
73807368
}
73817369
}
73827370

7371+
const auto isUnsupportedExistentialMemberAccess = [&] {
7372+
// If our base is an existential type, we can't make use of any
7373+
// member whose signature involves associated types.
7374+
if (instanceTy->isExistentialType()) {
7375+
if (auto *proto = decl->getDeclContext()->getSelfProtocolDecl()) {
7376+
if (!proto->isAvailableInExistential(decl)) {
7377+
return true;
7378+
}
7379+
}
7380+
}
7381+
7382+
return false;
7383+
};
7384+
73837385
// See if we have an instance method, instance member or static method,
73847386
// and check if it can be accessed on our base type.
73857387

@@ -7393,20 +7395,35 @@ performMemberLookup(ConstraintKind constraintKind, DeclNameRef memberName,
73937395
? candidate
73947396
: OverloadChoice(instanceTy, decl,
73957397
FunctionRefKind::SingleApply);
7396-
// If this is an instance member referenced from metatype
7397-
// let's add unviable result to the set because it could be
7398-
// either curried reference or an invalid call.
7399-
//
7400-
// New candidate shouldn't affect performance because such
7401-
// choice would only be attempted when solver is in diagnostic mode.
7402-
result.addUnviable(choice, MemberLookupResult::UR_InstanceMemberOnType);
7403-
7404-
bool invalidMethodRef = isa<FuncDecl>(decl) && !hasInstanceMethods;
7405-
bool invalidMemberRef = !isa<FuncDecl>(decl) && !hasInstanceMembers;
7406-
// If this is definitely an invalid way to reference a method or member
7407-
// on the metatype, let's stop here.
7408-
if (invalidMethodRef || invalidMemberRef)
7398+
7399+
const bool invalidMethodRef = isa<FuncDecl>(decl) && !hasInstanceMethods;
7400+
const bool invalidMemberRef = !isa<FuncDecl>(decl) && !hasInstanceMembers;
7401+
7402+
if (invalidMethodRef || invalidMemberRef) {
7403+
// If this is definitely an invalid way to reference a method or member
7404+
// on the metatype, let's stop here.
7405+
result.addUnviable(choice,
7406+
MemberLookupResult::UR_InstanceMemberOnType);
7407+
return;
7408+
} else if (isUnsupportedExistentialMemberAccess()) {
7409+
// If the member reference itself is legal, but it turns out to be an
7410+
// unsupported existential member access, do not make further
7411+
// assumptions about the correctness of a potential call -- let
7412+
// the unsupported member access error prevail.
7413+
result.addUnviable(candidate,
7414+
MemberLookupResult::UR_UnavailableInExistential);
74097415
return;
7416+
} else {
7417+
// Otherwise, still add an unviable result to the set, because it
7418+
// could be an invalid call that was supposed to be performed on an
7419+
// instance of the type.
7420+
//
7421+
// New candidate shouldn't affect performance because such
7422+
// choice would only be attempted when solver is in diagnostic mode.
7423+
result.addUnviable(choice,
7424+
MemberLookupResult::UR_InstanceMemberOnType);
7425+
7426+
}
74107427
}
74117428

74127429
// If the underlying type of a typealias is fully concrete, it is legal
@@ -7457,6 +7474,12 @@ performMemberLookup(ConstraintKind constraintKind, DeclNameRef memberName,
74577474
}
74587475
}
74597476

7477+
if (isUnsupportedExistentialMemberAccess()) {
7478+
result.addUnviable(candidate,
7479+
MemberLookupResult::UR_UnavailableInExistential);
7480+
return;
7481+
}
7482+
74607483
// If we have an rvalue base, make sure that the result isn't 'mutating'
74617484
// (only valid on lvalues).
74627485
if (!baseTy->is<AnyMetatypeType>() &&

test/decl/protocol/protocols_with_self_or_assoc_reqs.swift

Lines changed: 13 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -442,19 +442,19 @@ protocol P1_TypeMemberOnInstanceAndViceVersa {
442442
subscript(invariantSelfSubscript _: Void) -> G<Self> { get }
443443
}
444444
do {
445+
// Test that invalid reference errors prevail over unsupported existential
446+
// member accesses.
445447
func test(protoMeta: P1_TypeMemberOnInstanceAndViceVersa.Protocol,
446448
existMeta: P1_TypeMemberOnInstanceAndViceVersa.Type,
447449
instance: P1_TypeMemberOnInstanceAndViceVersa) {
448450
// P1_TypeMemberOnInstanceAndViceVersa.Protocol
449-
// FIXME: These should be diagnosed as invalid references.
450-
protoMeta.static_invariantSelfMethod() // expected-error {{member 'static_invariantSelfMethod' cannot be used on value of protocol type 'P1_TypeMemberOnInstanceAndViceVersa.Protocol'; use a generic constraint instead}}
451-
protoMeta.static_invariantSelfProp // expected-error {{member 'static_invariantSelfProp' cannot be used on value of protocol type 'P1_TypeMemberOnInstanceAndViceVersa.Protocol'; use a generic constraint instead}}
452-
protoMeta[static_invariantSelfSubscript: ()] // expected-error {{member 'subscript' cannot be used on value of protocol type 'P1_TypeMemberOnInstanceAndViceVersa.Protocol'; use a generic constraint instead}}
451+
protoMeta.static_invariantSelfMethod() // expected-error {{static member 'static_invariantSelfMethod' cannot be used on protocol metatype 'P1_TypeMemberOnInstanceAndViceVersa.Protocol'}}
452+
protoMeta.static_invariantSelfProp // expected-error {{static member 'static_invariantSelfProp' cannot be used on protocol metatype 'P1_TypeMemberOnInstanceAndViceVersa.Protocol'}}
453+
protoMeta[static_invariantSelfSubscript: ()] // expected-error {{static member 'subscript' cannot be used on protocol metatype 'P1_TypeMemberOnInstanceAndViceVersa.Protocol'}}
453454
_ = protoMeta.covariantSelfMethod // ok
454455
protoMeta.invariantSelfMethod // expected-error {{member 'invariantSelfMethod' cannot be used on value of protocol type 'P1_TypeMemberOnInstanceAndViceVersa.Protocol'; use a generic constraint instead}}
455-
// FIXME: These should be diagnosed as invalid references.
456-
protoMeta.invariantSelfProp // expected-error {{member 'invariantSelfProp' cannot be used on value of protocol type 'P1_TypeMemberOnInstanceAndViceVersa.Protocol'; use a generic constraint instead}}
457-
protoMeta[invariantSelfSubscript: ()] // expected-error {{member 'subscript' cannot be used on value of protocol type 'P1_TypeMemberOnInstanceAndViceVersa.Protocol'; use a generic constraint instead}}
456+
protoMeta.invariantSelfProp // expected-error {{instance member 'invariantSelfProp' cannot be used on type 'P1_TypeMemberOnInstanceAndViceVersa'}}
457+
protoMeta[invariantSelfSubscript: ()] // expected-error {{instance member 'subscript' cannot be used on type 'P1_TypeMemberOnInstanceAndViceVersa'}}
458458

459459
// P1_TypeMemberOnInstanceAndViceVersa.Type
460460
_ = existMeta.static_covariantSelfMethod // ok
@@ -463,16 +463,14 @@ do {
463463
existMeta.static_invariantSelfMethod // expected-error {{member 'static_invariantSelfMethod' cannot be used on value of protocol type 'P1_TypeMemberOnInstanceAndViceVersa.Type'; use a generic constraint instead}}
464464
existMeta.static_invariantSelfProp // expected-error {{member 'static_invariantSelfProp' cannot be used on value of protocol type 'P1_TypeMemberOnInstanceAndViceVersa.Type'; use a generic constraint instead}}
465465
existMeta[static_invariantSelfSubscript: ()] // expected-error {{member 'subscript' cannot be used on value of protocol type 'P1_TypeMemberOnInstanceAndViceVersa.Type'; use a generic constraint instead}}
466-
// FIXME: These should be diagnosed as invalid references.
467-
existMeta.invariantSelfMethod // expected-error {{member 'invariantSelfMethod' cannot be used on value of protocol type 'P1_TypeMemberOnInstanceAndViceVersa.Type'; use a generic constraint instead}}
468-
existMeta.invariantSelfProp // expected-error {{member 'invariantSelfProp' cannot be used on value of protocol type 'P1_TypeMemberOnInstanceAndViceVersa.Type'; use a generic constraint instead}}
469-
existMeta[invariantSelfSubscript: ()] // expected-error {{member 'subscript' cannot be used on value of protocol type 'P1_TypeMemberOnInstanceAndViceVersa.Type'; use a generic constraint instead}}
466+
existMeta.invariantSelfMethod // expected-error {{instance member 'invariantSelfMethod' cannot be used on type 'P1_TypeMemberOnInstanceAndViceVersa'}}
467+
existMeta.invariantSelfProp // expected-error {{instance member 'invariantSelfProp' cannot be used on type 'P1_TypeMemberOnInstanceAndViceVersa'}}
468+
existMeta[invariantSelfSubscript: ()] // expected-error {{instance member 'subscript' cannot be used on type 'P1_TypeMemberOnInstanceAndViceVersa'}}
470469

471470
// P1_TypeMemberOnInstanceAndViceVersa
472-
// FIXME: These should be diagnosed as invalid references.
473-
instance.static_invariantSelfMethod // expected-error {{member 'static_invariantSelfMethod' cannot be used on value of protocol type 'P1_TypeMemberOnInstanceAndViceVersa'; use a generic constraint instead}}
474-
instance.static_invariantSelfProp // expected-error {{member 'static_invariantSelfProp' cannot be used on value of protocol type 'P1_TypeMemberOnInstanceAndViceVersa'; use a generic constraint instead}}
475-
instance[static_invariantSelfSubscript: ()] // expected-error {{member 'subscript' cannot be used on value of protocol type 'P1_TypeMemberOnInstanceAndViceVersa'; use a generic constraint instead}}
471+
instance.static_invariantSelfMethod // expected-error {{static member 'static_invariantSelfMethod' cannot be used on instance of type 'P1_TypeMemberOnInstanceAndViceVersa'}}
472+
instance.static_invariantSelfProp // expected-error {{static member 'static_invariantSelfProp' cannot be used on instance of type 'P1_TypeMemberOnInstanceAndViceVersa'}}
473+
instance[static_invariantSelfSubscript: ()] // expected-error {{static member 'subscript' cannot be used on instance of type 'P1_TypeMemberOnInstanceAndViceVersa'}}
476474
}
477475
}
478476

0 commit comments

Comments
 (0)