|
41 | 41 | using namespace swift;
|
42 | 42 | using namespace constraints;
|
43 | 43 |
|
| 44 | +static bool hasFixFor(const Solution &solution, ConstraintLocator *locator) { |
| 45 | + return llvm::any_of(solution.Fixes, [&locator](const ConstraintFix *fix) { |
| 46 | + return fix->getLocator() == locator; |
| 47 | + }); |
| 48 | +} |
| 49 | + |
44 | 50 | FailureDiagnostic::~FailureDiagnostic() {}
|
45 | 51 |
|
46 | 52 | bool FailureDiagnostic::diagnose(bool asNote) {
|
@@ -6127,6 +6133,74 @@ bool MissingContextualBaseInMemberRefFailure::diagnoseAsError() {
|
6127 | 6133 | return true;
|
6128 | 6134 | }
|
6129 | 6135 |
|
| 6136 | +bool UnableToInferClosureParameterType::diagnoseAsError() { |
| 6137 | + auto *closure = castToExpr<ClosureExpr>(getRawAnchor()); |
| 6138 | + |
| 6139 | + // Let's check whether this closure is an argument to |
| 6140 | + // a call which couldn't be properly resolved e.g. |
| 6141 | + // missing member or invalid contextual reference and |
| 6142 | + // if so let's not diagnose this problem because main |
| 6143 | + // issue here is inability to establish context for |
| 6144 | + // closure inference. |
| 6145 | + // |
| 6146 | + // TODO(diagnostics): Once we gain an ability to determine |
| 6147 | + // originating source of type holes this check could be |
| 6148 | + // significantly simplified. |
| 6149 | + { |
| 6150 | + auto &solution = getSolution(); |
| 6151 | + |
| 6152 | + // If there is a contextual mismatch associated with this |
| 6153 | + // closure, let's not diagnose any parameter type issues. |
| 6154 | + if (hasFixFor(solution, getConstraintLocator( |
| 6155 | + closure, LocatorPathElt::ContextualType()))) |
| 6156 | + return false; |
| 6157 | + |
| 6158 | + if (auto *parentExpr = findParentExpr(closure)) { |
| 6159 | + while (parentExpr && |
| 6160 | + (isa<TupleExpr>(parentExpr) || isa<ParenExpr>(parentExpr))) { |
| 6161 | + parentExpr = findParentExpr(parentExpr); |
| 6162 | + } |
| 6163 | + |
| 6164 | + if (parentExpr) { |
| 6165 | + // Missing or invalid member reference in call. |
| 6166 | + if (auto *AE = dyn_cast<ApplyExpr>(parentExpr)) { |
| 6167 | + if (getType(AE->getFn())->isHole()) |
| 6168 | + return false; |
| 6169 | + } |
| 6170 | + |
| 6171 | + // Any fix anchored on parent expression makes it unnecessary |
| 6172 | + // to diagnose unability to infer parameter type because it's |
| 6173 | + // an indication that proper context couldn't be established to |
| 6174 | + // resolve the closure. |
| 6175 | + if (llvm::any_of(solution.Fixes, |
| 6176 | + [&parentExpr](const ConstraintFix *fix) -> bool { |
| 6177 | + return fix->getAnchor() == parentExpr; |
| 6178 | + })) |
| 6179 | + return false; |
| 6180 | + } |
| 6181 | + } |
| 6182 | + } |
| 6183 | + |
| 6184 | + auto paramIdx = getLocator() |
| 6185 | + ->castLastElementTo<LocatorPathElt::TupleElement>() |
| 6186 | + .getIndex(); |
| 6187 | + |
| 6188 | + auto *PD = closure->getParameters()->get(paramIdx); |
| 6189 | + |
| 6190 | + llvm::SmallString<16> id; |
| 6191 | + llvm::raw_svector_ostream OS(id); |
| 6192 | + |
| 6193 | + if (PD->isAnonClosureParam()) { |
| 6194 | + OS << "$" << paramIdx; |
| 6195 | + } else { |
| 6196 | + OS << "'" << PD->getParameterName() << "'"; |
| 6197 | + } |
| 6198 | + |
| 6199 | + auto loc = PD->isAnonClosureParam() ? getLoc() : PD->getLoc(); |
| 6200 | + emitDiagnosticAt(loc, diag::cannot_infer_closure_parameter_type, OS.str()); |
| 6201 | + return true; |
| 6202 | +} |
| 6203 | + |
6130 | 6204 | bool UnableToInferClosureReturnType::diagnoseAsError() {
|
6131 | 6205 | auto *closure = castToExpr<ClosureExpr>(getRawAnchor());
|
6132 | 6206 |
|
|
0 commit comments