@@ -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);
@@ -3298,11 +3300,7 @@ namespace {
3298
3300
auto cond
3299
3301
= solution.convertBooleanTypeToBuiltinI1 (expr->getCondExpr (),
3300
3302
cs.getConstraintLocator (expr));
3301
- if (!cond) {
3302
- cs.setType (expr->getCondExpr (), ErrorType::get (resultTy));
3303
- } else {
3304
- expr->setCondExpr (cond);
3305
- }
3303
+ expr->setCondExpr (cond);
3306
3304
3307
3305
// Coerce the then/else branches to the common type.
3308
3306
expr->setThenExpr (coerceToType (expr->getThenExpr (), resultTy,
@@ -7013,45 +7011,38 @@ static Type adjustSelfTypeForMember(Type baseTy, ValueDecl *member,
7013
7011
AccessSemantics semantics,
7014
7012
DeclContext *UseDC) {
7015
7013
auto baseObjectTy = baseTy->getWithoutSpecifierType ();
7016
- if (auto func = dyn_cast<AbstractFunctionDecl>(member)) {
7014
+
7015
+ if (isa<ConstructorDecl>(member))
7016
+ return baseObjectTy;
7017
+
7018
+ if (auto func = dyn_cast<FuncDecl>(member)) {
7017
7019
// If 'self' is an inout type, turn the base type into an lvalue
7018
7020
// type with the same qualifiers.
7019
- auto selfParam = func->getInterfaceType ()->getAs <AnyFunctionType>()->getParams ();
7020
- assert (selfParam.size () == 1 && " found invalid arity of self param" );
7021
- if (selfParam[0 ].getParameterFlags ().isInOut ()) {
7022
- // Unless we're looking at a nonmutating existential member. In which
7023
- // case, the member will be modeled as an inout but ExistentialMemberRef
7024
- // and ArchetypeMemberRef want to take the base as an rvalue.
7025
- if (auto *fd = dyn_cast<FuncDecl>(func))
7026
- if (!fd->isMutating () && baseObjectTy->is <ArchetypeType>())
7027
- return baseObjectTy;
7028
-
7021
+ if (func->isMutating ())
7029
7022
return InOutType::get (baseObjectTy);
7030
- }
7031
7023
7032
7024
// Otherwise, return the rvalue type.
7033
7025
return baseObjectTy;
7034
7026
}
7035
7027
7036
7028
// If the base of the access is mutable, then we may be invoking a getter or
7037
7029
// setter that requires the base to be mutable.
7038
- if (auto *SD = dyn_cast<AbstractStorageDecl>(member)) {
7039
- bool isSettableFromHere = SD->isSettable (UseDC)
7040
- && (!UseDC->getASTContext ().LangOpts .EnableAccessControl
7041
- || SD->isSetterAccessibleFrom (UseDC));
7042
-
7043
- // If neither the property's getter nor its setter are mutating, the base
7044
- // can be an rvalue.
7045
- if (!SD->isGetterMutating ()
7046
- && (!isSettableFromHere || !SD->isSetterMutating ()))
7047
- return baseObjectTy;
7048
-
7049
- // If we're calling an accessor, keep the base as an inout type, because the
7050
- // getter may be mutating.
7051
- if (SD->hasAccessorFunctions () && baseTy->is <InOutType>() &&
7052
- semantics != AccessSemantics::DirectToStorage)
7053
- return InOutType::get (baseObjectTy);
7054
- }
7030
+ auto *SD = cast<AbstractStorageDecl>(member);
7031
+ bool isSettableFromHere = SD->isSettable (UseDC)
7032
+ && (!UseDC->getASTContext ().LangOpts .EnableAccessControl
7033
+ || SD->isSetterAccessibleFrom (UseDC));
7034
+
7035
+ // If neither the property's getter nor its setter are mutating, the base
7036
+ // can be an rvalue.
7037
+ if (!SD->isGetterMutating ()
7038
+ && (!isSettableFromHere || !SD->isSetterMutating ()))
7039
+ return baseObjectTy;
7040
+
7041
+ // If we're calling an accessor, keep the base as an inout type, because the
7042
+ // getter may be mutating.
7043
+ if (SD->hasAccessorFunctions () && baseTy->is <InOutType>() &&
7044
+ semantics != AccessSemantics::DirectToStorage)
7045
+ return InOutType::get (baseObjectTy);
7055
7046
7056
7047
// Accesses to non-function members in value types are done through an @lvalue
7057
7048
// type.
@@ -7287,11 +7278,11 @@ Expr *ExprRewriter::convertLiteralInPlace(Expr *literal,
7287
7278
7288
7279
// Find the witness that we'll use to initialize the type via a builtin
7289
7280
// literal.
7290
- auto witness = findNamedWitnessImpl<AbstractFunctionDecl> (
7281
+ auto witness = findNamedWitnessImpl (
7291
7282
tc, dc, type->getRValueType (), builtinProtocol,
7292
7283
builtinLiteralFuncName, brokenBuiltinProtocolDiag,
7293
7284
*builtinConformance);
7294
- if (!witness)
7285
+ if (!witness || !isa<AbstractFunctionDecl>(witness. getDecl ()) )
7295
7286
return nullptr ;
7296
7287
7297
7288
// Form a reference to the builtin conversion function.
@@ -7301,7 +7292,7 @@ Expr *ExprRewriter::convertLiteralInPlace(Expr *literal,
7301
7292
7302
7293
Expr *unresolvedDot = new (tc.Context ) UnresolvedDotExpr (
7303
7294
base, SourceLoc (),
7304
- witness->getFullName (),
7295
+ witness. getDecl () ->getFullName (),
7305
7296
DeclNameLoc (base->getEndLoc ()),
7306
7297
/* Implicit=*/ true );
7307
7298
(void )tc.typeCheckExpression (unresolvedDot, dc);
@@ -7352,11 +7343,11 @@ Expr *ExprRewriter::convertLiteralInPlace(Expr *literal,
7352
7343
}
7353
7344
7354
7345
// Find the witness that we'll use to initialize the literal value.
7355
- auto witness = findNamedWitnessImpl<AbstractFunctionDecl> (
7346
+ auto witness = findNamedWitnessImpl (
7356
7347
tc, dc, type->getRValueType (), protocol,
7357
7348
literalFuncName, brokenProtocolDiag,
7358
7349
conformance);
7359
- if (!witness)
7350
+ if (!witness || !isa<AbstractFunctionDecl>(witness. getDecl ()) )
7360
7351
return nullptr ;
7361
7352
7362
7353
// Form a reference to the conversion function.
@@ -7366,7 +7357,7 @@ Expr *ExprRewriter::convertLiteralInPlace(Expr *literal,
7366
7357
7367
7358
Expr *unresolvedDot = new (tc.Context ) UnresolvedDotExpr (
7368
7359
base, SourceLoc (),
7369
- witness->getFullName (),
7360
+ witness. getDecl () ->getFullName (),
7370
7361
DeclNameLoc (base->getEndLoc ()),
7371
7362
/* Implicit=*/ true );
7372
7363
(void )tc.typeCheckExpression (unresolvedDot, dc);
@@ -8367,18 +8358,20 @@ Expr *TypeChecker::callWitness(Expr *base, DeclContext *dc,
8367
8358
if (auto metaType = type->getAs <AnyMetatypeType>())
8368
8359
type = metaType->getInstanceType ();
8369
8360
8370
- auto witness = findNamedWitnessImpl<AbstractFunctionDecl> (
8361
+ auto witness = findNamedWitnessImpl (
8371
8362
*this , dc, type->getRValueType (), protocol,
8372
8363
name, brokenProtocolDiag);
8373
- if (!witness)
8364
+ if (!witness || !isa<AbstractFunctionDecl>(witness. getDecl ()) )
8374
8365
return nullptr ;
8375
8366
8367
+ auto *witnessFn = cast<AbstractFunctionDecl>(witness.getDecl ());
8368
+
8376
8369
// Form a syntactic expression that describes the reference to the
8377
8370
// witness.
8378
8371
// FIXME: Egregious hack.
8379
8372
auto unresolvedDot = new (Context) UnresolvedDotExpr (
8380
8373
base, SourceLoc (),
8381
- witness->getFullName (),
8374
+ witness. getDecl () ->getFullName (),
8382
8375
DeclNameLoc (base->getEndLoc ()),
8383
8376
/* Implicit=*/ true );
8384
8377
unresolvedDot->setFunctionRefKind (FunctionRefKind::SingleApply);
@@ -8387,7 +8380,7 @@ Expr *TypeChecker::callWitness(Expr *base, DeclContext *dc,
8387
8380
// Form a reference to the witness itself.
8388
8381
Type openedFullType, openedType;
8389
8382
std::tie (openedFullType, openedType)
8390
- = cs.getTypeOfMemberReference (base->getType (), witness, dc,
8383
+ = cs.getTypeOfMemberReference (base->getType (), witness. getDecl () , dc,
8391
8384
/* isDynamicResult=*/ false ,
8392
8385
FunctionRefKind::DoubleApply,
8393
8386
dotLocator);
@@ -8400,9 +8393,9 @@ Expr *TypeChecker::callWitness(Expr *base, DeclContext *dc,
8400
8393
// FIXME: Standardize all callers to always provide all argument names,
8401
8394
// rather than hack around this.
8402
8395
CallExpr *call;
8403
- auto argLabels = witness->getFullName ().getArgumentNames ();
8396
+ auto argLabels = witness. getDecl () ->getFullName ().getArgumentNames ();
8404
8397
if (arguments.size () == 1 &&
8405
- (isVariadicWitness (witness ) ||
8398
+ (isVariadicWitness (witnessFn ) ||
8406
8399
argumentNamesMatch (cs.getType (arguments[0 ]), argLabels))) {
8407
8400
call = CallExpr::create (Context, unresolvedDot, arguments[0 ], {}, {},
8408
8401
/* hasTrailingClosure=*/ false ,
@@ -8453,7 +8446,7 @@ Expr *TypeChecker::callWitness(Expr *base, DeclContext *dc,
8453
8446
/* suppressDiagnostics=*/ false );
8454
8447
8455
8448
auto choice =
8456
- OverloadChoice (openedFullType, witness , FunctionRefKind::SingleApply);
8449
+ OverloadChoice (openedFullType, witnessFn , FunctionRefKind::SingleApply);
8457
8450
auto memberRef = rewriter.buildMemberRef (
8458
8451
base, openedFullType, base->getStartLoc (), choice,
8459
8452
DeclNameLoc (base->getEndLoc ()), openedType, dotLocator, dotLocator,
@@ -8502,45 +8495,48 @@ Solution::convertBooleanTypeToBuiltinI1(Expr *expr,
8502
8495
// Find the builtin method.
8503
8496
if (members.size () != 1 ) {
8504
8497
tc.diagnose (expr->getLoc (), diag::broken_bool);
8505
- return nullptr ;
8498
+ return expr ;
8506
8499
}
8507
8500
auto *builtinMethod = dyn_cast<FuncDecl>(members[0 ].getValueDecl ());
8508
8501
if (!builtinMethod) {
8509
8502
tc.diagnose (expr->getLoc (), diag::broken_bool);
8510
- return nullptr ;
8503
+ return expr ;
8511
8504
}
8512
8505
8513
- // Form a reference to the builtin method.
8514
- Expr *memberRef = new (ctx) MemberRefExpr (expr, SourceLoc (),
8515
- builtinMethod,
8516
- DeclNameLoc (expr->getLoc ()),
8517
- /* Implicit=*/ true );
8518
- cs.cacheSubExprTypes (memberRef);
8519
- cs.setSubExprTypes (memberRef);
8520
- bool failed = tc.typeCheckExpressionShallow (memberRef, cs.DC );
8521
- cs.cacheExprTypes (memberRef);
8522
- assert (!failed && " Could not reference witness?" );
8523
- (void )failed;
8506
+ // The method is not generic, so there are no substitutions.
8507
+ auto builtinMethodType = builtinMethod->getInterfaceType ()
8508
+ ->castTo <FunctionType>();
8509
+
8510
+ // Form an unbound reference to the builtin method.
8511
+ auto *declRef = new (ctx) DeclRefExpr (builtinMethod,
8512
+ DeclNameLoc (expr->getLoc ()),
8513
+ /* Implicit=*/ true );
8514
+ declRef->setFunctionRefKind (FunctionRefKind::DoubleApply);
8515
+ cs.setType (declRef, builtinMethodType);
8524
8516
8525
- // Call the builtin method.
8526
8517
auto getType = [&](const Expr *E) -> Type {
8527
8518
return cs.getType (E);
8528
8519
};
8529
8520
8530
- expr = CallExpr::createImplicit (ctx, memberRef, { }, { }, getType);
8531
- cs.cacheSubExprTypes (expr);
8532
- cs.setSubExprTypes (expr);
8533
- failed = tc.typeCheckExpressionShallow (expr, cs.DC );
8534
- cs.cacheExprTypes (expr);
8535
- assert (!failed && " Could not call witness?" );
8536
- (void )failed;
8521
+ // Apply 'self' to get the method value.
8522
+ auto *methodRef = new (ctx) DotSyntaxCallExpr (declRef,
8523
+ SourceLoc (),
8524
+ expr);
8525
+ cs.setType (methodRef, builtinMethodType->getResult ());
8526
+
8527
+ // Apply the empty argument list to get the final result.
8528
+ auto *result = CallExpr::createImplicit (ctx, methodRef,
8529
+ { }, { }, getType);
8530
+ cs.setType (result, builtinMethodType->getResult ()
8531
+ ->castTo <FunctionType>()->getResult ());
8532
+ cs.setType (result->getArg (), ctx.TheEmptyTupleType );
8537
8533
8538
- if (expr && !cs.getType (expr )->isBuiltinIntegerType (1 )) {
8534
+ if (!cs.getType (result )->isBuiltinIntegerType (1 )) {
8539
8535
tc.diagnose (expr->getLoc (), diag::broken_bool);
8540
- return nullptr ;
8536
+ return result ;
8541
8537
}
8542
8538
8543
- return expr ;
8539
+ return result ;
8544
8540
}
8545
8541
8546
8542
Expr *Solution::convertOptionalToBool (Expr *expr,
0 commit comments