@@ -131,17 +131,17 @@ void Solution::computeSubstitutions(
131
131
// / \param diag The diagnostic to emit if the protocol definition doesn't
132
132
// / have a requirement with the given name.
133
133
// /
134
- // / \returns The named witness, or nullptr if no witness could be found.
135
- template < typename DeclTy>
136
- static DeclTy * findNamedWitnessImpl (
134
+ // / \returns The named witness, or an empty ConcreteDeclRef if no witness
135
+ // / could be found.
136
+ ConcreteDeclRef findNamedWitnessImpl (
137
137
TypeChecker &tc, DeclContext *dc, Type type,
138
138
ProtocolDecl *proto, DeclName name,
139
139
Diag<> diag,
140
140
Optional<ProtocolConformanceRef> conformance = None) {
141
141
// Find the named requirement.
142
- DeclTy *requirement = nullptr ;
142
+ ValueDecl *requirement = nullptr ;
143
143
for (auto member : proto->getMembers ()) {
144
- auto d = dyn_cast<DeclTy >(member);
144
+ auto d = dyn_cast<ValueDecl >(member);
145
145
if (!d || !d->hasName ())
146
146
continue ;
147
147
@@ -159,7 +159,7 @@ static DeclTy *findNamedWitnessImpl(
159
159
// Find the member used to satisfy the named requirement.
160
160
if (!conformance) {
161
161
conformance = tc.conformsToProtocol (type, proto, dc,
162
- ConformanceCheckFlags::InExpression);
162
+ ConformanceCheckFlags::InExpression);
163
163
if (!conformance)
164
164
return nullptr ;
165
165
}
@@ -169,8 +169,7 @@ static DeclTy *findNamedWitnessImpl(
169
169
if (!conformance->isConcrete ())
170
170
return requirement;
171
171
auto concrete = conformance->getConcrete ();
172
- // FIXME: Dropping substitutions here.
173
- return cast_or_null<DeclTy>(concrete->getWitnessDecl (requirement, &tc));
172
+ return concrete->getWitnessDeclRef (requirement, &tc);
174
173
}
175
174
176
175
static bool shouldAccessStorageDirectly (Expr *base, VarDecl *member,
@@ -2377,18 +2376,21 @@ namespace {
2377
2376
DeclName name (tc.Context , DeclBaseName::createConstructor (),
2378
2377
{ tc.Context .Id_stringInterpolation });
2379
2378
auto member
2380
- = findNamedWitnessImpl<ConstructorDecl> (
2379
+ = findNamedWitnessImpl (
2381
2380
tc, dc, type,
2382
2381
interpolationProto, name,
2383
2382
diag::interpolation_broken_proto);
2384
2383
2385
2384
DeclName segmentName (tc.Context , DeclBaseName::createConstructor (),
2386
2385
{ tc.Context .Id_stringInterpolationSegment });
2387
2386
auto segmentMember
2388
- = findNamedWitnessImpl<ConstructorDecl> (
2387
+ = findNamedWitnessImpl (
2389
2388
tc, dc, type, interpolationProto, segmentName,
2390
2389
diag::interpolation_broken_proto);
2391
- if (!member || !segmentMember)
2390
+ if (!member ||
2391
+ !segmentMember ||
2392
+ !isa<ConstructorDecl>(member.getDecl ()) ||
2393
+ !isa<ConstructorDecl>(segmentMember.getDecl ()))
2392
2394
return nullptr ;
2393
2395
2394
2396
// Build a reference to the init(stringInterpolation:) initializer.
@@ -2399,7 +2401,7 @@ namespace {
2399
2401
Expr *memberRef =
2400
2402
new (tc.Context ) MemberRefExpr (typeRef,
2401
2403
expr->getStartLoc (),
2402
- member,
2404
+ member. getDecl () ,
2403
2405
DeclNameLoc (expr->getStartLoc ()),
2404
2406
/* Implicit=*/ true );
2405
2407
cs.cacheSubExprTypes (memberRef);
@@ -7283,11 +7285,11 @@ Expr *ExprRewriter::convertLiteralInPlace(Expr *literal,
7283
7285
7284
7286
// Find the witness that we'll use to initialize the type via a builtin
7285
7287
// literal.
7286
- auto witness = findNamedWitnessImpl<AbstractFunctionDecl> (
7288
+ auto witness = findNamedWitnessImpl (
7287
7289
tc, dc, type->getRValueType (), builtinProtocol,
7288
7290
builtinLiteralFuncName, brokenBuiltinProtocolDiag,
7289
7291
*builtinConformance);
7290
- if (!witness)
7292
+ if (!witness || !isa<AbstractFunctionDecl>(witness. getDecl ()) )
7291
7293
return nullptr ;
7292
7294
7293
7295
// Form a reference to the builtin conversion function.
@@ -7297,7 +7299,7 @@ Expr *ExprRewriter::convertLiteralInPlace(Expr *literal,
7297
7299
7298
7300
Expr *unresolvedDot = new (tc.Context ) UnresolvedDotExpr (
7299
7301
base, SourceLoc (),
7300
- witness->getFullName (),
7302
+ witness. getDecl () ->getFullName (),
7301
7303
DeclNameLoc (base->getEndLoc ()),
7302
7304
/* Implicit=*/ true );
7303
7305
(void )tc.typeCheckExpression (unresolvedDot, dc);
@@ -7348,11 +7350,11 @@ Expr *ExprRewriter::convertLiteralInPlace(Expr *literal,
7348
7350
}
7349
7351
7350
7352
// Find the witness that we'll use to initialize the literal value.
7351
- auto witness = findNamedWitnessImpl<AbstractFunctionDecl> (
7353
+ auto witness = findNamedWitnessImpl (
7352
7354
tc, dc, type->getRValueType (), protocol,
7353
7355
literalFuncName, brokenProtocolDiag,
7354
7356
conformance);
7355
- if (!witness)
7357
+ if (!witness || !isa<AbstractFunctionDecl>(witness. getDecl ()) )
7356
7358
return nullptr ;
7357
7359
7358
7360
// Form a reference to the conversion function.
@@ -7362,7 +7364,7 @@ Expr *ExprRewriter::convertLiteralInPlace(Expr *literal,
7362
7364
7363
7365
Expr *unresolvedDot = new (tc.Context ) UnresolvedDotExpr (
7364
7366
base, SourceLoc (),
7365
- witness->getFullName (),
7367
+ witness. getDecl () ->getFullName (),
7366
7368
DeclNameLoc (base->getEndLoc ()),
7367
7369
/* Implicit=*/ true );
7368
7370
(void )tc.typeCheckExpression (unresolvedDot, dc);
@@ -8363,18 +8365,20 @@ Expr *TypeChecker::callWitness(Expr *base, DeclContext *dc,
8363
8365
if (auto metaType = type->getAs <AnyMetatypeType>())
8364
8366
type = metaType->getInstanceType ();
8365
8367
8366
- auto witness = findNamedWitnessImpl<AbstractFunctionDecl> (
8368
+ auto witness = findNamedWitnessImpl (
8367
8369
*this , dc, type->getRValueType (), protocol,
8368
8370
name, brokenProtocolDiag);
8369
- if (!witness)
8371
+ if (!witness || !isa<AbstractFunctionDecl>(witness. getDecl ()) )
8370
8372
return nullptr ;
8371
8373
8374
+ auto *witnessFn = cast<AbstractFunctionDecl>(witness.getDecl ());
8375
+
8372
8376
// Form a syntactic expression that describes the reference to the
8373
8377
// witness.
8374
8378
// FIXME: Egregious hack.
8375
8379
auto unresolvedDot = new (Context) UnresolvedDotExpr (
8376
8380
base, SourceLoc (),
8377
- witness->getFullName (),
8381
+ witness. getDecl () ->getFullName (),
8378
8382
DeclNameLoc (base->getEndLoc ()),
8379
8383
/* Implicit=*/ true );
8380
8384
unresolvedDot->setFunctionRefKind (FunctionRefKind::SingleApply);
@@ -8383,7 +8387,7 @@ Expr *TypeChecker::callWitness(Expr *base, DeclContext *dc,
8383
8387
// Form a reference to the witness itself.
8384
8388
Type openedFullType, openedType;
8385
8389
std::tie (openedFullType, openedType)
8386
- = cs.getTypeOfMemberReference (base->getType (), witness, dc,
8390
+ = cs.getTypeOfMemberReference (base->getType (), witness. getDecl () , dc,
8387
8391
/* isDynamicResult=*/ false ,
8388
8392
FunctionRefKind::DoubleApply,
8389
8393
dotLocator);
@@ -8396,9 +8400,9 @@ Expr *TypeChecker::callWitness(Expr *base, DeclContext *dc,
8396
8400
// FIXME: Standardize all callers to always provide all argument names,
8397
8401
// rather than hack around this.
8398
8402
CallExpr *call;
8399
- auto argLabels = witness->getFullName ().getArgumentNames ();
8403
+ auto argLabels = witness. getDecl () ->getFullName ().getArgumentNames ();
8400
8404
if (arguments.size () == 1 &&
8401
- (isVariadicWitness (witness ) ||
8405
+ (isVariadicWitness (witnessFn ) ||
8402
8406
argumentNamesMatch (cs.getType (arguments[0 ]), argLabels))) {
8403
8407
call = CallExpr::create (Context, unresolvedDot, arguments[0 ], {}, {},
8404
8408
/* hasTrailingClosure=*/ false ,
@@ -8449,7 +8453,7 @@ Expr *TypeChecker::callWitness(Expr *base, DeclContext *dc,
8449
8453
/* suppressDiagnostics=*/ false );
8450
8454
8451
8455
auto choice =
8452
- OverloadChoice (openedFullType, witness , FunctionRefKind::SingleApply);
8456
+ OverloadChoice (openedFullType, witnessFn , FunctionRefKind::SingleApply);
8453
8457
auto memberRef = rewriter.buildMemberRef (
8454
8458
base, openedFullType, base->getStartLoc (), choice,
8455
8459
DeclNameLoc (base->getEndLoc ()), openedType, dotLocator, dotLocator,
0 commit comments