@lvalue exposure fixes & prevention

This commit is contained in:
Anthony Latsis
2019-10-07 21:02:29 +03:00
parent 022c6accf2
commit d64d45d3d6
5 changed files with 33 additions and 24 deletions

View File

@@ -75,12 +75,14 @@ std::pair<Expr *, bool> FailureDiagnostic::computeAnchor() const {
return {anchor, !resolved->getPath().empty()};
}
Type FailureDiagnostic::getType(Expr *expr) const {
return resolveType(CS.getType(expr));
Type FailureDiagnostic::getType(Expr *expr, bool wantRValue) const {
return resolveType(CS.getType(expr), /*reconstituteSugar=*/false,
wantRValue);
}
Type FailureDiagnostic::getType(const TypeLoc &loc) const {
return resolveType(CS.getType(loc));
Type FailureDiagnostic::getType(const TypeLoc &loc, bool wantRValue) const {
return resolveType(CS.getType(loc), /*reconstituteSugar=*/false,
wantRValue);
}
template <typename... ArgTypes>
@@ -248,7 +250,6 @@ FailureDiagnostic::getFunctionArgApplyInfo(ConstraintLocator *locator) const {
// Try to resolve the function type by loading lvalues and looking through
// optional types, which can occur for expressions like `fn?(5)`.
auto *fnType = resolveType(rawFnType)
->getRValueType()
->lookThroughAllOptionalTypes()
->getAs<FunctionType>();
if (!fnType)
@@ -1077,7 +1078,7 @@ bool MemberAccessOnOptionalBaseFailure::diagnoseAsError() {
return false;
auto *anchor = getAnchor();
auto baseType = getType(anchor)->getRValueType();
auto baseType = getType(anchor);
bool resultIsOptional = ResultTypeIsOptional;
// If we've resolved the member overload to one that returns an optional
@@ -1229,7 +1230,7 @@ bool MissingOptionalUnwrapFailure::diagnoseAsError() {
}
emitDiagnostic(tryExpr->getTryLoc(), diag::missing_unwrap_optional_try,
getType(anchor)->getRValueType())
getType(anchor))
.fixItReplace({tryExpr->getTryLoc(), tryExpr->getQuestionLoc()},
"try!");
return true;
@@ -1399,7 +1400,7 @@ bool RValueTreatedAsLValueFailure::diagnoseAsError() {
if (resolvedOverload->Choice.getKind() ==
OverloadChoiceKind::KeyPathDynamicMemberLookup) {
if (!getType(member->getBase())->hasLValueType())
if (!getType(member->getBase(), /*wantRValue=*/false)->hasLValueType())
subElementDiagID =
diag::assignment_dynamic_property_has_immutable_base;
}
@@ -2299,7 +2300,7 @@ bool ContextualFailure::diagnoseYieldByReferenceMismatch() const {
return false;
auto *anchor = getAnchor();
auto exprType = getType(anchor);
auto exprType = getType(anchor, /*wantRValue=*/false);
auto contextualType = getToType();
if (auto exprLV = exprType->getAs<LValueType>()) {
@@ -5163,7 +5164,7 @@ bool ArgumentMismatchFailure::diagnoseAsError() {
// let's match up its element type to the argument to see whether
// it would be appropriate to suggest adding `&`.
auto *argExpr = getAnchor();
if (getType(argExpr)->is<LValueType>()) {
if (getType(argExpr, /*wantRValue=*/false)->is<LValueType>()) {
auto elementTy = paramType->getAnyPointerElementType();
if (elementTy && argType->isEqual(elementTy)) {
diag.fixItInsert(argExpr->getStartLoc(), "&");
@@ -5199,8 +5200,8 @@ bool ArgumentMismatchFailure::diagnoseUseOfReferenceEqualityOperator() const {
auto name = *getOperatorName(binaryOp->getFn());
auto lhsType = getType(lhs)->getRValueType();
auto rhsType = getType(rhs)->getRValueType();
auto lhsType = getType(lhs);
auto rhsType = getType(rhs);
// If both arguments where incorrect e.g. both are function types,
// let's avoid producing a diagnostic second time, because first
@@ -5261,8 +5262,8 @@ bool ArgumentMismatchFailure::diagnosePatternMatchingMismatch() const {
auto *lhsExpr = op->getArg()->getElement(0);
auto *rhsExpr = op->getArg()->getElement(1);
auto lhsType = getType(lhsExpr)->getRValueType();
auto rhsType = getType(rhsExpr)->getRValueType();
auto lhsType = getType(lhsExpr);
auto rhsType = getType(rhsExpr);
auto diagnostic =
lhsType->is<UnresolvedType>()