@@ -588,66 +588,6 @@ namespace {
588588 }
589589 }
590590
591- // Returns None if the AST does not contain enough information to recover
592- // substitutions; this is different from an Optional(SubstitutionMap()),
593- // indicating a valid call to a non-generic operator.
594- std::optional<SubstitutionMap> getOperatorSubstitutions (ValueDecl *witness,
595- Type refType) {
596- // We have to recover substitutions in this hacky way because
597- // the AST does not retain enough information to devirtualize
598- // calls like this.
599- auto witnessType = witness->getInterfaceType ();
600-
601- // Compute the substitutions.
602- auto *gft = witnessType->getAs <GenericFunctionType>();
603- if (gft == nullptr ) {
604- if (refType->isEqual (witnessType))
605- return SubstitutionMap ();
606- return std::nullopt ;
607- }
608-
609- auto sig = gft->getGenericSignature ();
610- auto *env = sig.getGenericEnvironment ();
611-
612- witnessType = FunctionType::get (gft->getParams (),
613- gft->getResult (),
614- gft->getExtInfo ());
615- witnessType = env->mapTypeIntoContext (witnessType);
616-
617- TypeSubstitutionMap subs;
618- auto substType = witnessType->substituteBindingsTo (
619- refType,
620- [&](ArchetypeType *origType, CanType substType) -> CanType {
621- if (auto gpType = dyn_cast<GenericTypeParamType>(
622- origType->getInterfaceType ()->getCanonicalType ()))
623- subs[gpType] = substType;
624-
625- return substType;
626- });
627-
628- // If substitution failed, it means that the protocol requirement type
629- // and the witness type did not match up. The only time that this
630- // should happen is when the witness is defined in a base class and
631- // the actual call uses a derived class. For example,
632- //
633- // protocol P { func +(lhs: Self, rhs: Self) }
634- // class Base : P { func +(lhs: Base, rhs: Base) {} }
635- // class Derived : Base {}
636- //
637- // If we enter this code path with two operands of type Derived,
638- // we know we're calling the protocol requirement P.+, with a
639- // substituted type of (Derived, Derived) -> (). But the type of
640- // the witness is (Base, Base) -> (). Just bail out and make a
641- // witness method call in this rare case; SIL mandatory optimizations
642- // will likely devirtualize it anyway.
643- if (!substType)
644- return std::nullopt ;
645-
646- return SubstitutionMap::get (sig,
647- QueryTypeSubstitutionMap{subs},
648- LookUpConformanceInModule ());
649- }
650-
651591 // / Determine whether the given reference is to a method on
652592 // / a remote distributed actor in the given context.
653593 bool isDistributedThunk (ConcreteDeclRef ref, Expr *context);
@@ -674,65 +614,6 @@ namespace {
674614
675615 auto baseTy = getBaseType (adjustedFullType->castTo <FunctionType>());
676616
677- // Handle operator requirements found in protocols.
678- if (auto proto = dyn_cast<ProtocolDecl>(decl->getDeclContext ())) {
679- bool isCurried = shouldBuildCurryThunk (choice, /* baseIsInstance=*/ false );
680-
681- // If we have a concrete conformance, build a call to the witness.
682- //
683- // FIXME: This is awful. We should be able to handle this as a call to
684- // the protocol requirement with Self == the concrete type, and SILGen
685- // (or later) can devirtualize as appropriate.
686- auto conformance = checkConformance (baseTy, proto);
687- if (conformance.isConcrete ()) {
688- if (auto witness = conformance.getConcrete ()->getWitnessDecl (decl)) {
689- bool isMemberOperator = witness->getDeclContext ()->isTypeContext ();
690-
691- if (!isMemberOperator || !isCurried) {
692- // The fullType was computed by substituting the protocol
693- // requirement so it always has a (Self) -> ... curried
694- // application. Strip it off if the witness was a top-level
695- // function.
696- Type refType;
697- if (isMemberOperator)
698- refType = adjustedFullType;
699- else
700- refType = adjustedFullType->castTo <AnyFunctionType>()->getResult ();
701-
702- // Build the AST for the call to the witness.
703- auto subMap = getOperatorSubstitutions (witness, refType);
704- if (subMap) {
705- ConcreteDeclRef witnessRef (witness, *subMap);
706- auto declRefExpr = new (ctx) DeclRefExpr (witnessRef, loc,
707- /* Implicit=*/ false );
708- declRefExpr->setFunctionRefInfo (choice.getFunctionRefInfo ());
709- cs.setType (declRefExpr, refType);
710-
711- Expr *refExpr;
712- if (isMemberOperator) {
713- // If the operator is a type member, add the implicit
714- // (Self) -> ... call.
715- Expr *base =
716- TypeExpr::createImplicitHack (loc.getBaseNameLoc (), baseTy,
717- ctx);
718- cs.setType (base, MetatypeType::get (baseTy));
719-
720- refExpr =
721- DotSyntaxCallExpr::create (ctx, declRefExpr, SourceLoc (),
722- Argument::unlabeled (base));
723- auto refType = adjustedFullType->castTo <FunctionType>()->getResult ();
724- cs.setType (refExpr, refType);
725- } else {
726- refExpr = declRefExpr;
727- }
728-
729- return forceUnwrapIfExpected (refExpr, locator);
730- }
731- }
732- }
733- }
734- }
735-
736617 // Build a reference to the member.
737618 Expr *base =
738619 TypeExpr::createImplicitHack (loc.getBaseNameLoc (), baseTy, ctx);
0 commit comments