@@ -934,11 +934,18 @@ matchWitness(TypeChecker &tc,
934
934
// the required type and the witness type.
935
935
cs.emplace (tc, dc, ConstraintSystemOptions ());
936
936
937
- Type model;
938
- if (conformance)
939
- model = conformance->getType ();
940
- else
941
- model = dc->getDeclaredTypeInContext ();
937
+ Type selfIfaceTy = proto->getProtocolSelf ()->getDeclaredType ();
938
+ Type selfTy;
939
+
940
+ // For a concrete conformance, use the conforming type as the
941
+ // base type of the requirement and witness lookup.
942
+ if (conformance) {
943
+ selfTy = conformance->getType ();
944
+
945
+ // For a default witness, use the requirement's context archetype.
946
+ } else {
947
+ selfTy = ArchetypeBuilder::mapTypeIntoContext (dc, selfIfaceTy);
948
+ }
942
949
943
950
// Open up the witness type.
944
951
witnessType = witness->getInterfaceType ();
@@ -950,7 +957,7 @@ matchWitness(TypeChecker &tc,
950
957
LocatorPathElt (ConstraintLocator::Witness, witness));
951
958
if (witness->getDeclContext ()->isTypeContext ()) {
952
959
std::tie (openedFullWitnessType, openWitnessType)
953
- = cs->getTypeOfMemberReference (model , witness,
960
+ = cs->getTypeOfMemberReference (selfTy , witness,
954
961
/* isTypeReference=*/ false ,
955
962
/* isDynamicResult=*/ false ,
956
963
witnessLocator,
@@ -972,7 +979,7 @@ matchWitness(TypeChecker &tc,
972
979
DeclContext *reqDC = req->getInnermostDeclContext ();
973
980
llvm::DenseMap<CanType, TypeVariableType *> replacements;
974
981
std::tie (openedFullReqType, reqType)
975
- = cs->getTypeOfMemberReference (model , req,
982
+ = cs->getTypeOfMemberReference (selfTy , req,
976
983
/* isTypeReference=*/ false ,
977
984
/* isDynamicResult=*/ false ,
978
985
locator,
@@ -981,31 +988,45 @@ matchWitness(TypeChecker &tc,
981
988
982
989
// Bind the associated types.
983
990
for (const auto &replacement : replacements) {
984
- if ( auto gpType = replacement. first -> getAs <GenericTypeParamType>()) {
985
- // Record the type variable for ' Self'.
986
- if (gpType-> getDepth () == 0 && gpType-> getIndex () == 0 ) {
987
- cs-> SelfTypeVar = replacement. second ;
988
- continue ;
989
- }
990
-
991
- // Replace any other type variable with the archetype within
992
- // the requirement's context.
993
- cs->addConstraint (ConstraintKind::Bind,
994
- replacement. second ,
995
- ArchetypeBuilder::mapTypeIntoContext (reqDC, gpType),
996
- locator);
997
-
998
- // Associated type of 'Self'.
999
- } else if (auto assocType = getReferencedAssocTypeOfProtocol (
991
+
992
+ // If we have a concrete conformance, handle Self-derived type parameters
993
+ // differently.
994
+ if (conformance) {
995
+ if (replacement. first -> is <GenericTypeParamType>()) {
996
+ // For a concrete conformance, we record the type variable for 'Self'
997
+ // without doing anything else. See the comment for SelfTypeVar in
998
+ // ConstraintSystem.h.
999
+ if (selfIfaceTy-> isEqual (replacement. first )) {
1000
+ cs->SelfTypeVar = replacement. second ;
1001
+ continue ;
1002
+ }
1003
+
1004
+ // Inner generic parameter of the requirement -- fall through below.
1005
+
1006
+ } else if (auto assocType = getReferencedAssocTypeOfProtocol (
1000
1007
replacement.first , proto)) {
1001
- if (conformance) {
1008
+
1009
+ // Look up the associated type witness.
1002
1010
cs->addConstraint (ConstraintKind::Bind,
1003
1011
replacement.second ,
1004
1012
conformance->getTypeWitness (assocType, nullptr )
1005
1013
.getReplacement (),
1006
1014
locator);
1015
+ continue ;
1016
+ } else {
1017
+ continue ;
1007
1018
}
1008
1019
}
1020
+
1021
+ // Replace any other type variable with the archetype within the
1022
+ // requirement's context.
1023
+ auto contextTy = ArchetypeBuilder::mapTypeIntoContext (
1024
+ reqDC, replacement.first );
1025
+
1026
+ cs->addConstraint (ConstraintKind::Bind,
1027
+ replacement.second ,
1028
+ contextTy,
1029
+ locator);
1009
1030
}
1010
1031
reqType = reqType->getRValueType ();
1011
1032
@@ -1042,7 +1063,7 @@ matchWitness(TypeChecker &tc,
1042
1063
if (openedFullWitnessType->hasTypeVariable ()) {
1043
1064
// Figure out the context we're substituting into.
1044
1065
auto witnessDC = witness->getInnermostDeclContext ();
1045
-
1066
+
1046
1067
// Compute the set of substitutions we'll need for the witness.
1047
1068
solution->computeSubstitutions (witness->getInterfaceType (),
1048
1069
witnessDC, openedFullWitnessType,
@@ -2311,7 +2332,8 @@ ConformanceChecker::resolveWitnessViaLookup(ValueDecl *requirement) {
2311
2332
2312
2333
// If the requirement is optional, it's okay. We'll satisfy this via
2313
2334
// our handling of default definitions.
2314
- // FIXME: also check for a default definition here.
2335
+ //
2336
+ // FIXME: revisit this once we get default definitions in protocol bodies.
2315
2337
//
2316
2338
// Treat 'unavailable' implicitly as if it were 'optional'.
2317
2339
// The compiler will reject actual uses.
@@ -2400,7 +2422,7 @@ ResolveWitnessResult ConformanceChecker::resolveWitnessViaDerivation(
2400
2422
return ResolveWitnessResult::ExplicitFailed;
2401
2423
}
2402
2424
2403
- // FIXME: use default definitions??
2425
+ // FIXME: revisit this once we get default implementations in protocol bodies.
2404
2426
ResolveWitnessResult ConformanceChecker::resolveWitnessViaDefault (
2405
2427
ValueDecl *requirement) {
2406
2428
assert (!isa<AssociatedTypeDecl>(requirement) && " Use resolveTypeWitnessVia*" );
@@ -2413,8 +2435,6 @@ ResolveWitnessResult ConformanceChecker::resolveWitnessViaDefault(
2413
2435
return ResolveWitnessResult::Success;
2414
2436
}
2415
2437
2416
- // FIXME: Default definition.
2417
-
2418
2438
diagnoseOrDefer (requirement, true ,
2419
2439
[requirement](TypeChecker &tc, NormalProtocolConformance *conformance) {
2420
2440
auto dc = conformance->getDeclContext ();
0 commit comments