Skip to content

Commit d299925

Browse files
committed
[Diagnostics] Port the "extra address of agrument" diagnostic to the new
framework.
1 parent 746cad5 commit d299925

File tree

8 files changed

+70
-37
lines changed

8 files changed

+70
-37
lines changed

lib/Sema/CSDiag.cpp

Lines changed: 0 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -2199,19 +2199,6 @@ typeCheckArgumentChildIndependently(Expr *argExpr, Type argType,
21992199
if (!exprResult)
22002200
return nullptr;
22012201

2202-
// If the caller expected something inout, but we didn't have
2203-
// something of inout type, diagnose it.
2204-
if (auto IOE =
2205-
dyn_cast<InOutExpr>(exprResult->getSemanticsProvidingExpr())) {
2206-
if (!param.isInOut()) {
2207-
diagnose(exprResult->getLoc(), diag::extra_address_of,
2208-
CS.getType(exprResult)->getInOutObjectType())
2209-
.highlight(exprResult->getSourceRange())
2210-
.fixItRemove(IOE->getStartLoc());
2211-
return nullptr;
2212-
}
2213-
}
2214-
22152202
auto resultTy = CS.getType(exprResult);
22162203
resultElts[inArgNo] = exprResult;
22172204
resultEltTys[inArgNo] = {resultTy->getInOutObjectType(),
@@ -4592,13 +4579,6 @@ bool FailureDiagnosis::visitInOutExpr(InOutExpr *IOE) {
45924579
}
45934580
} else if (contextualType->is<InOutType>()) {
45944581
contextualType = contextualType->getInOutObjectType();
4595-
} else {
4596-
// If the caller expected something inout, but we didn't have
4597-
// something of inout type, diagnose it.
4598-
diagnose(IOE->getLoc(), diag::extra_address_of, contextualType)
4599-
.highlight(IOE->getSourceRange())
4600-
.fixItRemove(IOE->getStartLoc());
4601-
return true;
46024582
}
46034583
}
46044584

@@ -6015,19 +5995,6 @@ bool FailureDiagnosis::visitTupleExpr(TupleExpr *TE) {
60155995
CS.getContextualTypePurpose(), options);
60165996
// If there was an error type checking this argument, then we're done.
60175997
if (!exprResult) return true;
6018-
6019-
// If the caller expected something inout, but we didn't have
6020-
// something of inout type, diagnose it.
6021-
if (auto IOE =
6022-
dyn_cast<InOutExpr>(exprResult->getSemanticsProvidingExpr())) {
6023-
if (!contextualTT->getElement(i).isInOut()) {
6024-
diagnose(exprResult->getLoc(), diag::extra_address_of,
6025-
CS.getType(exprResult)->getInOutObjectType())
6026-
.highlight(exprResult->getSourceRange())
6027-
.fixItRemove(IOE->getStartLoc());
6028-
return true;
6029-
}
6030-
}
60315998
}
60325999

60336000
return false;

lib/Sema/CSDiagnostics.cpp

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -908,6 +908,17 @@ bool MissingAddressOfFailure::diagnoseAsError() {
908908
return true;
909909
}
910910

911+
bool ExtraAddressOfFailure::diagnoseAsError() {
912+
if (hasComplexLocator())
913+
return false;
914+
915+
auto anchor = getAnchor();
916+
emitDiagnostic(getAnchor()->getLoc(), diag::extra_address_of, getToType())
917+
.highlight(anchor->getSourceRange())
918+
.fixItRemove(anchor->getStartLoc());
919+
return true;
920+
}
921+
911922
bool MissingExplicitConversionFailure::diagnoseAsError() {
912923
if (hasComplexLocator())
913924
return false;

lib/Sema/CSDiagnostics.h

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -843,6 +843,16 @@ class MissingAddressOfFailure final : public ContextualFailure {
843843
bool diagnoseAsError() override;
844844
};
845845

846+
/// Diagnose failures when passing an inout argument to a non-inout parameter.
847+
class ExtraAddressOfFailure final : public ContextualFailure {
848+
public:
849+
ExtraAddressOfFailure(Expr *expr, ConstraintSystem &cs, Type argTy,
850+
Type paramTy, ConstraintLocator *locator)
851+
: ContextualFailure(expr, cs, argTy, paramTy, locator) {}
852+
853+
bool diagnoseAsError() override;
854+
};
855+
846856
/// Diagnose mismatches relating to tuple destructuring.
847857
class TupleContextualFailure final : public ContextualFailure {
848858
public:

lib/Sema/CSFix.cpp

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -114,6 +114,19 @@ AddAddressOf *AddAddressOf::create(ConstraintSystem &cs, Type argTy,
114114
return new (cs.getAllocator()) AddAddressOf(cs, argTy, paramTy, locator);
115115
}
116116

117+
bool RemoveAddressOfArg::diagnose(Expr *root, bool asNote) const {
118+
auto &cs = getConstraintSystem();
119+
ExtraAddressOfFailure failure(root, cs, getFromType(), getToType(),
120+
getLocator());
121+
return failure.diagnose(asNote);
122+
}
123+
124+
RemoveAddressOfArg *
125+
RemoveAddressOfArg::create(ConstraintSystem &cs, Type argTy, Type paramTy,
126+
ConstraintLocator *locator) {
127+
return new (cs.getAllocator()) RemoveAddressOfArg(cs, argTy, paramTy, locator);
128+
}
129+
117130
bool TreatRValueAsLValue::diagnose(Expr *root, bool asNote) const {
118131
RValueTreatedAsLValueFailure failure(getConstraintSystem(), getLocator());
119132
return failure.diagnose(asNote);

lib/Sema/CSFix.h

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -545,6 +545,21 @@ class AddAddressOf final : public ContextualMismatch {
545545
ConstraintLocator *locator);
546546
};
547547

548+
/// Remove the \c & of an argument for a non-inout parameter.
549+
class RemoveAddressOfArg final : public ContextualMismatch {
550+
RemoveAddressOfArg(ConstraintSystem &cs, Type argTy, Type paramTy,
551+
ConstraintLocator *locator)
552+
: ContextualMismatch(cs, argTy, paramTy, locator) {}
553+
554+
public:
555+
std::string getName() const override { return "remove address of argument"; }
556+
557+
bool diagnose(Expr *root, bool asNote = false) const override;
558+
559+
static RemoveAddressOfArg *create(ConstraintSystem &cs, Type argTy,
560+
Type paramTy, ConstraintLocator *locator);
561+
};
562+
548563
/// Detect situations where two type's generic arguments must
549564
/// match but are not convertible e.g.
550565
///

lib/Sema/CSSimplify.cpp

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2430,6 +2430,23 @@ bool ConstraintSystem::repairFailures(
24302430
conversionsOrFixes.push_back(AddAddressOf::create(
24312431
*this, lhs, rhs, getConstraintLocator(locator)));
24322432
}
2433+
2434+
// If the argument is inout and the parameter is not inout or a pointer,
2435+
// suggest removing the &.
2436+
if (lhs->is<InOutType>() && !rhs->is<InOutType>()) {
2437+
auto objectType = rhs->lookThroughAllOptionalTypes();
2438+
if (objectType->getAnyPointerElementType())
2439+
break;
2440+
2441+
auto result = matchTypes(lhs->getInOutObjectType(), rhs,
2442+
ConstraintKind::ArgumentConversion,
2443+
TypeMatchFlags::TMF_ApplyingFix, locator);
2444+
2445+
if (result.isSuccess())
2446+
conversionsOrFixes.push_back(RemoveAddressOfArg::create(*this, lhs,
2447+
rhs, getConstraintLocator(locator)));
2448+
}
2449+
24332450
break;
24342451
}
24352452

test/Constraints/diagnostics.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -570,8 +570,8 @@ func r22255907_2<T>(_ x : Int, a : T, b: Int) {}
570570

571571
func reachabilityForInternetConnection() {
572572
var variable: Int = 42
573-
r22255907_1(&variable, b: 2.1) // expected-error {{'&' used with non-inout argument of type 'Int'}} {{15-16=}}
574-
r22255907_2(1, a: &variable, b: 2.1)// expected-error {{'&' used with non-inout argument of type 'Int'}} {{21-22=}}
573+
r22255907_1(&variable, b: 2) // expected-error {{'&' used with non-inout argument of type 'Int'}} {{15-16=}}
574+
r22255907_2(1, a: &variable, b: 2)// expected-error {{'&' used with non-inout argument of type 'Int'}} {{21-22=}}
575575
}
576576

577577
// <rdar://problem/21601687> QoI: Using "=" instead of "==" in if statement leads to incorrect error message

test/Generics/materializable_restrictions.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,8 @@
22

33
func test15921520() {
44
var x: Int = 0
5-
func f<T>(_ x: T) {} // expected-note{{in call to function 'f'}}
6-
f(&x) // expected-error{{generic parameter 'T' could not be inferred}}
5+
func f<T>(_ x: T) {}
6+
f(&x) // expected-error{{'&' used with non-inout argument of type 'Int'}} {{7-8=}}
77
}
88

99
func test20807269() {

0 commit comments

Comments
 (0)