@@ -3980,6 +3980,191 @@ performMemberLookup(ConstraintKind constraintKind, DeclName memberName,
39803980 return result;
39813981}
39823982
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+
39834168ConstraintSystem::SolutionKind ConstraintSystem::simplifyMemberConstraint (
39844169 ConstraintKind kind, Type baseTy, DeclName member, Type memberTy,
39854170 DeclContext *useDC, FunctionRefKind functionRefKind,
@@ -4021,8 +4206,12 @@ ConstraintSystem::SolutionKind ConstraintSystem::simplifyMemberConstraint(
40214206 // If we found viable candidates, then we're done!
40224207 if (!result.ViableCandidates .empty ()) {
40234208 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+ });
40264215
40274216 if (!outerAlternatives.empty ()) {
40284217 // If local scope has a single choice,
@@ -4049,46 +4238,26 @@ ConstraintSystem::SolutionKind ConstraintSystem::simplifyMemberConstraint(
40494238 if (!MissingMembers.insert (locator))
40504239 return SolutionKind::Error;
40514240
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.
40544241 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);
40924261 return SolutionKind::Solved;
40934262 }
40944263 }
@@ -6379,6 +6548,11 @@ ConstraintSystem::simplifyConstraint(const Constraint &constraint) {
63796548 None, constraint.getLocator ());
63806549
63816550 case ConstraintKind::BindOverload:
6551+ if (auto *fix = constraint.getFix ()) {
6552+ if (recordFix (fix))
6553+ return SolutionKind::Error;
6554+ }
6555+
63826556 resolveOverload (constraint.getLocator (), constraint.getFirstType (),
63836557 constraint.getOverloadChoice (),
63846558 constraint.getOverloadUseDC ());
0 commit comments