|
32 | 32 | namespace swift {
|
33 | 33 | namespace constraints {
|
34 | 34 |
|
| 35 | +class FunctionArgApplyInfo; |
| 36 | + |
35 | 37 | /// Base class for all of the possible diagnostics,
|
36 | 38 | /// provides most basic information such as location of
|
37 | 39 | /// the problem, parent expression and some utility methods.
|
@@ -162,6 +164,13 @@ class FailureDiagnostic {
|
162 | 164 |
|
163 | 165 | Optional<SelectedOverload> getChoiceFor(Expr *) const;
|
164 | 166 |
|
| 167 | + /// For a given locator describing a function argument conversion, or a |
| 168 | + /// constraint within an argument conversion, returns information about the |
| 169 | + /// application of the argument to its parameter. If the locator is not |
| 170 | + /// for an argument conversion, returns \c None. |
| 171 | + Optional<FunctionArgApplyInfo> |
| 172 | + getFunctionArgApplyInfo(ConstraintLocator *locator) const; |
| 173 | + |
165 | 174 | private:
|
166 | 175 | /// Compute anchor expression associated with current diagnostic.
|
167 | 176 | std::pair<Expr *, bool> computeAnchor() const;
|
@@ -1336,6 +1345,97 @@ class SkipUnhandledConstructInFunctionBuilderFailure final
|
1336 | 1345 | bool diagnoseAsNote() override;
|
1337 | 1346 | };
|
1338 | 1347 |
|
| 1348 | +/// Provides information about the application of a function argument to a |
| 1349 | +/// parameter. |
| 1350 | +class FunctionArgApplyInfo { |
| 1351 | + Expr *ArgExpr; |
| 1352 | + unsigned ArgIdx; |
| 1353 | + Type ArgType; |
| 1354 | + |
| 1355 | + unsigned ParamIdx; |
| 1356 | + |
| 1357 | + Type FnInterfaceType; |
| 1358 | + FunctionType *FnType; |
| 1359 | + const ValueDecl *Callee; |
| 1360 | + |
| 1361 | +public: |
| 1362 | + FunctionArgApplyInfo(Expr *argExpr, unsigned argIdx, Type argType, |
| 1363 | + unsigned paramIdx, Type fnInterfaceType, |
| 1364 | + FunctionType *fnType, const ValueDecl *callee) |
| 1365 | + : ArgExpr(argExpr), ArgIdx(argIdx), ArgType(argType), ParamIdx(paramIdx), |
| 1366 | + FnInterfaceType(fnInterfaceType), FnType(fnType), Callee(callee) {} |
| 1367 | + |
| 1368 | + /// \returns The argument being applied. |
| 1369 | + Expr *getArgExpr() const { return ArgExpr; } |
| 1370 | + |
| 1371 | + /// \returns The position of the argument, starting at 1. |
| 1372 | + unsigned getArgPosition() const { return ArgIdx + 1; } |
| 1373 | + |
| 1374 | + /// \returns The position of the parameter, starting at 1. |
| 1375 | + unsigned getParamPosition() const { return ParamIdx + 1; } |
| 1376 | + |
| 1377 | + /// \returns The type of the argument being applied, including any generic |
| 1378 | + /// substitutions. |
| 1379 | + /// |
| 1380 | + /// \param withSpecifier Whether to keep the inout or @lvalue specifier of |
| 1381 | + /// the argument, if any. |
| 1382 | + Type getArgType(bool withSpecifier = false) const { |
| 1383 | + return withSpecifier ? ArgType : ArgType->getWithoutSpecifierType(); |
| 1384 | + } |
| 1385 | + |
| 1386 | + /// \returns The interface type for the function being applied. Note that this |
| 1387 | + /// may not a function type, for example it could be a generic parameter. |
| 1388 | + Type getFnInterfaceType() const { return FnInterfaceType; } |
| 1389 | + |
| 1390 | + /// \returns The function type being applied, including any generic |
| 1391 | + /// substitutions. |
| 1392 | + FunctionType *getFnType() const { return FnType; } |
| 1393 | + |
| 1394 | + /// \returns The callee for the application. |
| 1395 | + const ValueDecl *getCallee() const { return Callee; } |
| 1396 | + |
| 1397 | +private: |
| 1398 | + Type getParamTypeImpl(AnyFunctionType *fnTy, |
| 1399 | + bool lookThroughAutoclosure) const { |
| 1400 | + auto param = fnTy->getParams()[ParamIdx]; |
| 1401 | + auto paramTy = param.getPlainType(); |
| 1402 | + if (lookThroughAutoclosure && param.isAutoClosure()) |
| 1403 | + paramTy = paramTy->castTo<FunctionType>()->getResult(); |
| 1404 | + return paramTy; |
| 1405 | + } |
| 1406 | + |
| 1407 | +public: |
| 1408 | + /// \returns The type of the parameter which the argument is being applied to, |
| 1409 | + /// including any generic substitutions. |
| 1410 | + /// |
| 1411 | + /// \param lookThroughAutoclosure Whether an @autoclosure () -> T parameter |
| 1412 | + /// should be treated as being of type T. |
| 1413 | + Type getParamType(bool lookThroughAutoclosure = true) const { |
| 1414 | + return getParamTypeImpl(FnType, lookThroughAutoclosure); |
| 1415 | + } |
| 1416 | + |
| 1417 | + /// \returns The interface type of the parameter which the argument is being |
| 1418 | + /// applied to. |
| 1419 | + /// |
| 1420 | + /// \param lookThroughAutoclosure Whether an @autoclosure () -> T parameter |
| 1421 | + /// should be treated as being of type T. |
| 1422 | + Type getParamInterfaceType(bool lookThroughAutoclosure = true) const { |
| 1423 | + auto interfaceFnTy = FnInterfaceType->getAs<AnyFunctionType>(); |
| 1424 | + if (!interfaceFnTy) { |
| 1425 | + // If the interface type isn't a function, then just return the resolved |
| 1426 | + // parameter type. |
| 1427 | + return getParamType(lookThroughAutoclosure)->mapTypeOutOfContext(); |
| 1428 | + } |
| 1429 | + return getParamTypeImpl(interfaceFnTy, lookThroughAutoclosure); |
| 1430 | + } |
| 1431 | + |
| 1432 | + /// \returns The flags of the parameter which the argument is being applied |
| 1433 | + /// to. |
| 1434 | + ParameterTypeFlags getParameterFlags() const { |
| 1435 | + return FnType->getParams()[ParamIdx].getParameterFlags(); |
| 1436 | + } |
| 1437 | +}; |
| 1438 | + |
1339 | 1439 | } // end namespace constraints
|
1340 | 1440 | } // end namespace swift
|
1341 | 1441 |
|
|
0 commit comments