Skip to content

Commit e49ca21

Browse files
committed
Sema: Check for invalid reference *before* checking for unsupported existential member access
1 parent 64b8f61 commit e49ca21

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
@@ -7322,7 +7322,7 @@ performMemberLookup(ConstraintKind constraintKind, DeclNameRef memberName,
73227322
// Dig out the instance type and figure out what members of the instance type
73237323
// we are going to see.
73247324
auto baseTy = candidate.getBaseType();
7325-
auto baseObjTy = baseTy->getRValueType();
7325+
const auto baseObjTy = baseTy->getRValueType();
73267326

73277327
bool hasInstanceMembers = false;
73287328
bool hasInstanceMethods = false;
@@ -7369,18 +7369,6 @@ performMemberLookup(ConstraintKind constraintKind, DeclNameRef memberName,
73697369
hasInstanceMethods = true;
73707370
}
73717371

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-
result.addUnviable(candidate,
7378-
MemberLookupResult::UR_UnavailableInExistential);
7379-
return;
7380-
}
7381-
}
7382-
}
7383-
73847372
// If the invocation's argument expression has a favored type,
73857373
// use that information to determine whether a specific overload for
73867374
// the candidate should be favored.
@@ -7400,6 +7388,20 @@ performMemberLookup(ConstraintKind constraintKind, DeclNameRef memberName,
74007388
}
74017389
}
74027390

7391+
const auto isUnsupportedExistentialMemberAccess = [&] {
7392+
// If our base is an existential type, we can't make use of any
7393+
// member whose signature involves associated types.
7394+
if (instanceTy->isExistentialType()) {
7395+
if (auto *proto = decl->getDeclContext()->getSelfProtocolDecl()) {
7396+
if (!proto->isAvailableInExistential(decl)) {
7397+
return true;
7398+
}
7399+
}
7400+
}
7401+
7402+
return false;
7403+
};
7404+
74037405
// See if we have an instance method, instance member or static method,
74047406
// and check if it can be accessed on our base type.
74057407

@@ -7413,20 +7415,35 @@ performMemberLookup(ConstraintKind constraintKind, DeclNameRef memberName,
74137415
? candidate
74147416
: OverloadChoice(instanceTy, decl,
74157417
FunctionRefKind::SingleApply);
7416-
// If this is an instance member referenced from metatype
7417-
// let's add unviable result to the set because it could be
7418-
// either curried reference or an invalid call.
7419-
//
7420-
// New candidate shouldn't affect performance because such
7421-
// choice would only be attempted when solver is in diagnostic mode.
7422-
result.addUnviable(choice, MemberLookupResult::UR_InstanceMemberOnType);
7423-
7424-
bool invalidMethodRef = isa<FuncDecl>(decl) && !hasInstanceMethods;
7425-
bool invalidMemberRef = !isa<FuncDecl>(decl) && !hasInstanceMembers;
7426-
// If this is definitely an invalid way to reference a method or member
7427-
// on the metatype, let's stop here.
7428-
if (invalidMethodRef || invalidMemberRef)
7418+
7419+
const bool invalidMethodRef = isa<FuncDecl>(decl) && !hasInstanceMethods;
7420+
const bool invalidMemberRef = !isa<FuncDecl>(decl) && !hasInstanceMembers;
7421+
7422+
if (invalidMethodRef || invalidMemberRef) {
7423+
// If this is definitely an invalid way to reference a method or member
7424+
// on the metatype, let's stop here.
7425+
result.addUnviable(choice,
7426+
MemberLookupResult::UR_InstanceMemberOnType);
7427+
return;
7428+
} else if (isUnsupportedExistentialMemberAccess()) {
7429+
// If the member reference itself is legal, but it turns out to be an
7430+
// unsupported existential member access, do not make further
7431+
// assumptions about the correctness of a potential call -- let
7432+
// the unsupported member access error prevail.
7433+
result.addUnviable(candidate,
7434+
MemberLookupResult::UR_UnavailableInExistential);
74297435
return;
7436+
} else {
7437+
// Otherwise, still add an unviable result to the set, because it
7438+
// could be an invalid call that was supposed to be performed on an
7439+
// instance of the type.
7440+
//
7441+
// New candidate shouldn't affect performance because such
7442+
// choice would only be attempted when solver is in diagnostic mode.
7443+
result.addUnviable(choice,
7444+
MemberLookupResult::UR_InstanceMemberOnType);
7445+
7446+
}
74307447
}
74317448

74327449
// If the underlying type of a typealias is fully concrete, it is legal
@@ -7477,6 +7494,12 @@ performMemberLookup(ConstraintKind constraintKind, DeclNameRef memberName,
74777494
}
74787495
}
74797496

7497+
if (isUnsupportedExistentialMemberAccess()) {
7498+
result.addUnviable(candidate,
7499+
MemberLookupResult::UR_UnavailableInExistential);
7500+
return;
7501+
}
7502+
74807503
// If we have an rvalue base, make sure that the result isn't 'mutating'
74817504
// (only valid on lvalues).
74827505
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)