@@ -3980,6 +3980,191 @@ performMemberLookup(ConstraintKind constraintKind, DeclName memberName,
3980
3980
return result;
3981
3981
}
3982
3982
3983
+ // / Determine whether the given type refers to a non-final class (or
3984
+ // / dynamic self of one).
3985
+ static bool isNonFinalClass (Type type) {
3986
+ if (auto dynamicSelf = type->getAs <DynamicSelfType>())
3987
+ type = dynamicSelf->getSelfType ();
3988
+
3989
+ if (auto classDecl = type->getClassOrBoundGenericClass ())
3990
+ return !classDecl->isFinal ();
3991
+
3992
+ if (auto archetype = type->getAs <ArchetypeType>())
3993
+ if (auto super = archetype->getSuperclass ())
3994
+ return isNonFinalClass (super);
3995
+
3996
+ return type->isExistentialType ();
3997
+ }
3998
+
3999
+ // / Determine whether given constructor reference is valid or does it require
4000
+ // / any fixes e.g. when base is a protocol metatype.
4001
+ static ConstraintFix *validateInitializerRef (ConstraintSystem &cs,
4002
+ ConstructorDecl *init,
4003
+ ConstraintLocator *locator) {
4004
+ auto *anchor = locator->getAnchor ();
4005
+ if (!anchor)
4006
+ return nullptr ;
4007
+
4008
+ auto getType = [&cs](const Expr *expr) -> Type {
4009
+ return cs.simplifyType (cs.getType (expr))->getRValueType ();
4010
+ };
4011
+
4012
+ auto locatorEndsWith =
4013
+ [](ConstraintLocator *locator,
4014
+ ConstraintLocator::PathElementKind eltKind) -> bool {
4015
+ auto path = locator->getPath ();
4016
+ return !path.empty () && path.back ().getKind () == eltKind;
4017
+ };
4018
+
4019
+ Expr *baseExpr = nullptr ;
4020
+ Type baseType;
4021
+
4022
+ // Explicit initializer reference e.g. `T.init(...)` or `T.init`.
4023
+ if (auto *UDE = dyn_cast<UnresolvedDotExpr>(anchor)) {
4024
+ baseExpr = UDE->getBase ();
4025
+ baseType = getType (baseExpr);
4026
+ if (baseType->is <MetatypeType>()) {
4027
+ auto instanceType = baseType->getAs <MetatypeType>()
4028
+ ->getInstanceType ()
4029
+ ->getWithoutParens ();
4030
+ if (!cs.isTypeReference (baseExpr) && instanceType->isExistentialType ()) {
4031
+ return AllowInvalidInitRef::onProtocolMetatype (
4032
+ cs, baseType, init, /* isStaticallyDerived=*/ true ,
4033
+ baseExpr->getSourceRange (), locator);
4034
+ }
4035
+ }
4036
+ // Initializer call e.g. `T(...)`
4037
+ } else if (auto *CE = dyn_cast<CallExpr>(anchor)) {
4038
+ baseExpr = CE->getFn ();
4039
+ baseType = getType (baseExpr);
4040
+ // If this is an initializer call without explicit mention
4041
+ // of `.init` on metatype value.
4042
+ if (auto *AMT = baseType->getAs <AnyMetatypeType>()) {
4043
+ auto instanceType = AMT->getInstanceType ()->getWithoutParens ();
4044
+ if (!cs.isTypeReference (baseExpr)) {
4045
+ if (baseType->is <MetatypeType>() &&
4046
+ instanceType->isAnyExistentialType ()) {
4047
+ return AllowInvalidInitRef::onProtocolMetatype (
4048
+ cs, baseType, init, cs.isStaticallyDerivedMetatype (baseExpr),
4049
+ baseExpr->getSourceRange (), locator);
4050
+ }
4051
+
4052
+ if (!instanceType->isExistentialType () ||
4053
+ instanceType->isAnyExistentialType ()) {
4054
+ return AllowInvalidInitRef::onNonConstMetatype (cs, baseType, init,
4055
+ locator);
4056
+ }
4057
+ }
4058
+ }
4059
+ // Initializer reference which requires contextual base type e.g.
4060
+ // `.init(...)`.
4061
+ } else if (auto *UME = dyn_cast<UnresolvedMemberExpr>(anchor)) {
4062
+ // We need to find type variable which represents contextual base.
4063
+ auto *baseLocator = cs.getConstraintLocator (
4064
+ UME, locatorEndsWith (locator, ConstraintLocator::ConstructorMember)
4065
+ ? ConstraintLocator::UnresolvedMember
4066
+ : ConstraintLocator::MemberRefBase);
4067
+
4068
+ // FIXME: Type variables responsible for contextual base could be cached
4069
+ // in the constraint system to speed up lookup.
4070
+ auto result = llvm::find_if (
4071
+ cs.getTypeVariables (), [&baseLocator](const TypeVariableType *typeVar) {
4072
+ return typeVar->getImpl ().getLocator () == baseLocator;
4073
+ });
4074
+
4075
+ assert (result != cs.getTypeVariables ().end ());
4076
+ baseType = cs.simplifyType (*result)->getRValueType ();
4077
+ // Constraint for member base is formed as '$T.Type[.<member] = ...`
4078
+ // which means MetatypeType has to be added after finding a type variable.
4079
+ if (locatorEndsWith (baseLocator, ConstraintLocator::MemberRefBase))
4080
+ baseType = MetatypeType::get (baseType);
4081
+ }
4082
+
4083
+ if (!baseType)
4084
+ return nullptr ;
4085
+
4086
+ if (!baseType->is <AnyMetatypeType>()) {
4087
+ bool applicable = false ;
4088
+ // Special case -- in a protocol extension initializer with a class
4089
+ // constrainted Self type, 'self' has archetype type, and only
4090
+ // required initializers can be called.
4091
+ if (baseExpr && !baseExpr->isSuperExpr ()) {
4092
+ auto &ctx = cs.getASTContext ();
4093
+ if (auto *DRE =
4094
+ dyn_cast<DeclRefExpr>(baseExpr->getSemanticsProvidingExpr ())) {
4095
+ if (DRE->getDecl ()->getFullName () == ctx.Id_self ) {
4096
+ if (getType (DRE)->is <ArchetypeType>())
4097
+ applicable = true ;
4098
+ }
4099
+ }
4100
+ }
4101
+
4102
+ if (!applicable)
4103
+ return nullptr ;
4104
+ }
4105
+
4106
+ auto instanceType = baseType->getMetatypeInstanceType ();
4107
+ bool isStaticallyDerived = true ;
4108
+ // If this is expression like `.init(...)` where base type is
4109
+ // determined by a contextual type.
4110
+ if (!baseExpr) {
4111
+ isStaticallyDerived = !(instanceType->is <DynamicSelfType>() ||
4112
+ instanceType->is <ArchetypeType>());
4113
+ // Otherwise this is something like `T.init(...)`
4114
+ } else {
4115
+ isStaticallyDerived = cs.isStaticallyDerivedMetatype (baseExpr);
4116
+ }
4117
+
4118
+ auto baseRange = baseExpr ? baseExpr->getSourceRange () : SourceRange ();
4119
+ // FIXME: The "hasClangNode" check here is a complete hack.
4120
+ if (isNonFinalClass (instanceType) && !isStaticallyDerived &&
4121
+ !init->hasClangNode () &&
4122
+ !(init->isRequired () || init->getDeclContext ()->getSelfProtocolDecl ())) {
4123
+ return AllowInvalidInitRef::dynamicOnMetatype (cs, baseType, init, baseRange,
4124
+ locator);
4125
+ // Constructors cannot be called on a protocol metatype, because there is no
4126
+ // metatype to witness it.
4127
+ } else if (baseType->is <MetatypeType>() &&
4128
+ instanceType->isExistentialType ()) {
4129
+ return AllowInvalidInitRef::onProtocolMetatype (
4130
+ cs, baseType, init, isStaticallyDerived, baseRange, locator);
4131
+ }
4132
+
4133
+ return nullptr ;
4134
+ }
4135
+
4136
+ static ConstraintFix *
4137
+ fixMemberRef (ConstraintSystem &cs, Type baseTy,
4138
+ DeclName memberName, const OverloadChoice &choice,
4139
+ ConstraintLocator *locator,
4140
+ Optional<MemberLookupResult::UnviableReason> reason = None) {
4141
+ if (!choice.isDecl ())
4142
+ return nullptr ;
4143
+
4144
+ auto *decl = choice.getDecl ();
4145
+ if (auto *CD = dyn_cast<ConstructorDecl>(decl)) {
4146
+ if (auto *fix = validateInitializerRef (cs, CD, locator))
4147
+ return fix;
4148
+ }
4149
+
4150
+ if (reason) {
4151
+ switch (*reason) {
4152
+ case MemberLookupResult::UR_InstanceMemberOnType:
4153
+ case MemberLookupResult::UR_TypeMemberOnInstance:
4154
+ return AllowTypeOrInstanceMember::create (cs, baseTy, memberName, locator);
4155
+
4156
+ case MemberLookupResult::UR_MutatingMemberOnRValue:
4157
+ case MemberLookupResult::UR_MutatingGetterOnRValue:
4158
+ case MemberLookupResult::UR_LabelMismatch:
4159
+ case MemberLookupResult::UR_Inaccessible:
4160
+ case MemberLookupResult::UR_UnavailableInExistential:
4161
+ break ;
4162
+ }
4163
+ }
4164
+
4165
+ return nullptr ;
4166
+ }
4167
+
3983
4168
ConstraintSystem::SolutionKind ConstraintSystem::simplifyMemberConstraint (
3984
4169
ConstraintKind kind, Type baseTy, DeclName member, Type memberTy,
3985
4170
DeclContext *useDC, FunctionRefKind functionRefKind,
@@ -4021,8 +4206,12 @@ ConstraintSystem::SolutionKind ConstraintSystem::simplifyMemberConstraint(
4021
4206
// If we found viable candidates, then we're done!
4022
4207
if (!result.ViableCandidates .empty ()) {
4023
4208
llvm::SmallVector<Constraint *, 8 > candidates;
4024
- generateConstraints (candidates, memberTy, result.ViableCandidates ,
4025
- useDC, locator, result.getFavoredChoice ());
4209
+ generateConstraints (
4210
+ candidates, memberTy, result.ViableCandidates , useDC, locator,
4211
+ result.getFavoredIndex (), /* requiresFix=*/ false ,
4212
+ [&](unsigned , const OverloadChoice &choice) {
4213
+ return fixMemberRef (*this , baseTy, member, choice, locator);
4214
+ });
4026
4215
4027
4216
if (!outerAlternatives.empty ()) {
4028
4217
// If local scope has a single choice,
@@ -4049,46 +4238,26 @@ ConstraintSystem::SolutionKind ConstraintSystem::simplifyMemberConstraint(
4049
4238
if (!MissingMembers.insert (locator))
4050
4239
return SolutionKind::Error;
4051
4240
4052
- // FIXME(diagnostics): If there were no viable results, but there are
4053
- // unviable ones, we'd have to introduce fix for each specific problem.
4054
4241
if (!result.UnviableCandidates .empty ()) {
4055
- // Check if we have unviable candidates whose reason for rejection
4056
- // is either UR_InstanceMemberOnType or UR_TypeMemberOnInstance
4057
- SmallVector<OverloadChoice, 4 > filteredCandidates;
4058
-
4059
- llvm::for_each (
4060
- result.UnviableCandidates ,
4061
- [&](const std::pair<OverloadChoice,
4062
- MemberLookupResult::UnviableReason> &c) {
4063
- if (c.second == MemberLookupResult::UR_InstanceMemberOnType ||
4064
- c.second == MemberLookupResult::UR_TypeMemberOnInstance) {
4065
- filteredCandidates.push_back (std::move (c.first ));
4066
- }
4067
- });
4068
-
4069
- // If we do, then allow them
4070
- if (!filteredCandidates.empty ()) {
4071
-
4072
- auto meetsProtocolBaseMetatypeCriteria =
4073
- baseTy->is <AnyMetatypeType>() && baseTy->getMetatypeInstanceType ()
4074
- ->getWithoutParens ()
4075
- ->isAnyExistentialType ();
4076
-
4077
- auto requiresProtocolMetatypeFix =
4078
- llvm::any_of (filteredCandidates, [&](const OverloadChoice &c) {
4079
- return c.isDecl () && isa<ConstructorDecl>(c.getDecl ());
4080
- });
4081
-
4082
- if (!meetsProtocolBaseMetatypeCriteria ||
4083
- !requiresProtocolMetatypeFix) {
4084
- auto fix =
4085
- AllowTypeOrInstanceMember::create (*this , baseTy, member, locator);
4086
- if (recordFix (fix))
4087
- // The fix wasn't successful, so return an error
4088
- return SolutionKind::Error;
4089
- }
4090
-
4091
- addOverloadSet (memberTy, filteredCandidates, useDC, locator);
4242
+ SmallVector<OverloadChoice, 8 > choices;
4243
+ llvm::transform (
4244
+ result.UnviableCandidates , std::back_inserter (choices),
4245
+ [](const std::pair<OverloadChoice, MemberLookupResult::UnviableReason>
4246
+ &candidate) { return candidate.first ; });
4247
+
4248
+ SmallVector<Constraint *, 4 > candidates;
4249
+ generateConstraints (candidates, memberTy, choices, useDC, locator,
4250
+ /* favoredChoice=*/ None, /* requiresFix=*/ true ,
4251
+ [&](unsigned idx, const OverloadChoice &choice) {
4252
+ return fixMemberRef (
4253
+ *this , baseTy, member, choice, locator,
4254
+ result.UnviableCandidates [idx].second );
4255
+ });
4256
+
4257
+ // If there are any viable "fixed" candidates, let's schedule
4258
+ // them to be attempted.
4259
+ if (!candidates.empty ()) {
4260
+ addOverloadSet (candidates, locator);
4092
4261
return SolutionKind::Solved;
4093
4262
}
4094
4263
}
@@ -6379,6 +6548,11 @@ ConstraintSystem::simplifyConstraint(const Constraint &constraint) {
6379
6548
None, constraint.getLocator ());
6380
6549
6381
6550
case ConstraintKind::BindOverload:
6551
+ if (auto *fix = constraint.getFix ()) {
6552
+ if (recordFix (fix))
6553
+ return SolutionKind::Error;
6554
+ }
6555
+
6382
6556
resolveOverload (constraint.getLocator (), constraint.getFirstType (),
6383
6557
constraint.getOverloadChoice (),
6384
6558
constraint.getOverloadUseDC ());
0 commit comments