diff --git a/lib/Sema/CSDiagnostics.cpp b/lib/Sema/CSDiagnostics.cpp index 7081bb1126d..c6f3a6fbee7 100644 --- a/lib/Sema/CSDiagnostics.cpp +++ b/lib/Sema/CSDiagnostics.cpp @@ -530,42 +530,50 @@ bool MissingOptionalUnwrapFailure::diagnose() { } bool RValueTreatedAsLValueFailure::diagnose() { - if (auto callExpr = dyn_cast(getAnchor())) { - Expr *argExpr = callExpr->getArg(); + Diag subElementDiagID; + Diag rvalueDiagID; + Expr *diagExpr = getLocator()->getAnchor(); + SourceLoc loc; - Diag subElementDiagID; - Diag rvalueDiagID; - Expr *diagExpr = nullptr; + auto callExpr = dyn_cast(diagExpr); + if (!callExpr) + return false; // currently only creating these for args, so should be + // unreachable - if (isa(callExpr) || isa(callExpr)) { - subElementDiagID = diag::cannot_apply_lvalue_unop_to_subelement; - rvalueDiagID = diag::cannot_apply_lvalue_unop_to_rvalue; - diagExpr = argExpr; - } else if (isa(callExpr)) { - subElementDiagID = diag::cannot_apply_lvalue_binop_to_subelement; - rvalueDiagID = diag::cannot_apply_lvalue_binop_to_rvalue; - auto argTuple = dyn_cast(argExpr); - diagExpr = argTuple->getElement(0); - } else { - auto lastPathElement = getLocator()->getPath().back(); - assert(lastPathElement.getKind() == ConstraintLocator::PathElementKind::ApplyArgToParam); + Expr *argExpr = callExpr->getArg(); + loc = callExpr->getFn()->getLoc(); - subElementDiagID = diag::cannot_pass_rvalue_inout_subelement; - rvalueDiagID = diag::cannot_pass_rvalue_inout; - if (auto argTuple = dyn_cast(argExpr)) - diagExpr = argTuple->getElement(lastPathElement.getValue()); - else if (auto parens = dyn_cast(argExpr)) - diagExpr = parens->getSubExpr(); - } + if (isa(callExpr) || isa(callExpr)) { + subElementDiagID = diag::cannot_apply_lvalue_unop_to_subelement; + rvalueDiagID = diag::cannot_apply_lvalue_unop_to_rvalue; + diagExpr = argExpr; + } else if (isa(callExpr)) { + subElementDiagID = diag::cannot_apply_lvalue_binop_to_subelement; + rvalueDiagID = diag::cannot_apply_lvalue_binop_to_rvalue; + auto argTuple = dyn_cast(argExpr); + diagExpr = argTuple->getElement(0); + } else { + auto lastPathElement = getLocator()->getPath().back(); + assert(lastPathElement.getKind() == + ConstraintLocator::PathElementKind::ApplyArgToParam); - // FIXME: Would like for this to be unnecessary. - getConstraintSystem().TC.typeCheckExpression(diagExpr, getConstraintSystem().DC); - - diagnoseSubElementFailure(diagExpr, callExpr->getFn()->getLoc(), - getConstraintSystem(), - subElementDiagID, rvalueDiagID); - return true; + subElementDiagID = diag::cannot_pass_rvalue_inout_subelement; + rvalueDiagID = diag::cannot_pass_rvalue_inout; + if (auto argTuple = dyn_cast(argExpr)) + diagExpr = argTuple->getElement(lastPathElement.getValue()); + else if (auto parens = dyn_cast(argExpr)) + diagExpr = parens->getSubExpr(); } - // These fixes are only being created for matching arg types right now, so this is unreachable. - return false; + + // FIXME: Needed right now to apply correct overload choices to diagExpr for + // use by diagnoseSubElementFailure(). Once all callers are routed through + // here, that function can be rewritten to take the current Solution and use + // it for determining chosen decl bindings instead, making this extra + // typecheck unnecessary. + getConstraintSystem().TC.typeCheckExpression(diagExpr, + getConstraintSystem().DC); + + diagnoseSubElementFailure(diagExpr, loc, getConstraintSystem(), + subElementDiagID, rvalueDiagID); + return true; } diff --git a/lib/Sema/ConstraintLocator.h b/lib/Sema/ConstraintLocator.h index bd0c1930e10..52b0ff513c0 100644 --- a/lib/Sema/ConstraintLocator.h +++ b/lib/Sema/ConstraintLocator.h @@ -343,7 +343,7 @@ public: return PathElement(NamedTupleElement, position); } - /// Retrieve a patch element for an argument/parameter comparison in a + /// Retrieve a path element for an argument/parameter comparison in a /// function application. static PathElement getApplyArgToParam(unsigned argIdx, unsigned paramIdx) { return PathElement(ApplyArgToParam, argIdx, paramIdx);