Skip to content

Reword the missing nullary call error message #30705

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 8 additions & 2 deletions include/swift/AST/DiagnosticsSema.def
Original file line number Diff line number Diff line change
Expand Up @@ -1038,8 +1038,14 @@ NOTE(note_init_parameter,none,


ERROR(missing_nullary_call,none,
"function produces expected type %0; did you mean to call it with '()'?",
(Type))
"cannot convert value of type %0 to expected type %1; did you mean to call"
" it with '()'%select{| using its default arguments}2?",
(Type, Type, bool))
ERROR(missing_nullary_call_decl,none,
"cannot convert value of type %0 (reference to %1 %2) to expected type %3;"
" did you mean to call it with '()'"
"%select{| using its default arguments}4?",
(Type, DescriptiveDeclKind, DeclName, Type, bool))
ERROR(optional_not_unwrapped,none,
"value of optional type %0 must be unwrapped to a value of type %1",
(Type, Type))
Expand Down
25 changes: 19 additions & 6 deletions lib/Sema/CSDiagnostics.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2278,6 +2278,22 @@ void ContextualFailure::tryFixIts(InFlightDiagnostic &diagnostic) const {
return;
}

static InFlightDiagnostic emitMissingNullaryCallDiagnostic(ConstraintSystem &cs,
FunctionType *srcFT,
Expr *anchor) {
auto &diags = cs.getASTContext().Diags;
if (auto declRefExpr = dyn_cast<DeclRefExpr>(anchor)) {
if (auto decl = declRefExpr->getDecl())
return diags.diagnose(anchor->getLoc(), diag::missing_nullary_call_decl,
srcFT, decl->getDescriptiveKind(),
decl->getBaseName(), srcFT->getResult(),
!srcFT->getParams().empty());
}

return diags.diagnose(anchor->getLoc(), diag::missing_nullary_call, srcFT,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could you please make it a method on ContextualFailure and use emitDiagnostic instead of DiagnosticEngine directly? I'm trying to change the way diagnostics are emitted in the future - #30967

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we'll need to duplicate it in MissingCallFailure too since this error can be emitted from both. It's fairly short though, so probably worth it to take advantage of the upcoming changes

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could we maybe inherit MissingCallFailure from ContextualFailure?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe, I'll look into doing that

srcFT->getResult(), !srcFT->getParams().empty());
}

bool ContextualFailure::diagnoseMissingFunctionCall() const {
if (getLocator()->isLastElement<LocatorPathElt::RValueAdjustment>())
return false;
Expand Down Expand Up @@ -2310,8 +2326,7 @@ bool ContextualFailure::diagnoseMissingFunctionCall() const {
}

auto *anchor = getAnchor();
emitDiagnostic(anchor->getLoc(), diag::missing_nullary_call,
srcFT->getResult())
emitMissingNullaryCallDiagnostic(getConstraintSystem(), srcFT, anchor)
.highlight(anchor->getSourceRange())
.fixItInsertAfter(anchor->getEndLoc(), "()");

Expand Down Expand Up @@ -3049,8 +3064,7 @@ bool MissingCallFailure::diagnoseAsError() {
case ConstraintLocator::ContextualType:
case ConstraintLocator::ApplyArgToParam: {
auto fnType = getType(baseExpr)->castTo<FunctionType>();
emitDiagnostic(baseExpr->getLoc(), diag::missing_nullary_call,
fnType->getResult())
emitMissingNullaryCallDiagnostic(getConstraintSystem(), fnType, baseExpr)
.fixItInsertAfter(baseExpr->getEndLoc(), "()");
return true;
}
Expand Down Expand Up @@ -3099,8 +3113,7 @@ bool MissingCallFailure::diagnoseAsError() {
if (auto *AE = dyn_cast<AssignExpr>(baseExpr)) {
auto *srcExpr = AE->getSrc();
if (auto *fnType = getType(srcExpr)->getAs<FunctionType>()) {
emitDiagnostic(srcExpr->getLoc(), diag::missing_nullary_call,
fnType->getResult())
emitMissingNullaryCallDiagnostic(getConstraintSystem(), fnType, srcExpr)
.highlight(srcExpr->getSourceRange())
.fixItInsertAfter(srcExpr->getEndLoc(), "()");
return true;
Expand Down
22 changes: 11 additions & 11 deletions test/Constraints/fixes.swift
Original file line number Diff line number Diff line change
Expand Up @@ -24,27 +24,27 @@ func f7(_ a: A, _: Int) -> Int { }
func forgotCall() {
// Simple cases
var x: Int
x = f1 // expected-error{{function produces expected type 'Int'; did you mean to call it with '()'?}}{{9-9=()}}
x = f1 // expected-error{{cannot convert value of type '() -> Int' (reference to global function 'f1') to expected type 'Int'; did you mean to call it with '()'?}}{{9-9=()}}
x = f2 // expected-error{{cannot assign value of type '(Int) -> Int' to type 'Int'}}
x = f3 // expected-error{{cannot assign value of type '(Int...) -> Int' to type 'Int'}}

// With a supertype conversion
var a = A()
a = f4 // expected-error{{function produces expected type 'B'; did you mean to call it with '()'?}}{{9-9=()}}
a = f4 // expected-error{{cannot convert value of type '() -> B' (reference to global function 'f4') to expected type 'B'; did you mean to call it with '()'?}}{{9-9=()}}

// As a call
f5(f4) // expected-error{{function produces expected type 'B'; did you mean to call it with '()'?}}{{8-8=()}}
f6(f4, f2) // expected-error{{function produces expected type 'B'; did you mean to call it with '()'?}}{{8-8=()}}
// expected-error@-1 {{function produces expected type 'Int'; did you mean to call it with '()'?}} {{12-12=()}}
f5(f4) // expected-error{{cannot convert value of type '() -> B' (reference to global function 'f4') to expected type 'B'; did you mean to call it with '()'?}}{{8-8=()}}
f6(f4, f2) // expected-error{{cannot convert value of type '(Int) -> Int' (reference to global function 'f2') to expected type 'Int'; did you mean to call it with '()' using its default arguments?}}{{12-12=()}}
// expected-error@-1 {{cannot convert value of type '() -> B' (reference to global function 'f4') to expected type 'B'; did you mean to call it with '()'?}} {{8-8=()}}

// With overloading: only one succeeds.
a = createB // expected-error{{function produces expected type 'B'; did you mean to call it with '()'?}}
a = createB // expected-error{{cannot convert value of type '() -> B' to expected type 'B'; did you mean to call it with '()'?}}

let _: A = createB // expected-error{{function produces expected type 'B'; did you mean to call it with '()'?}} {{21-21=()}}
let _: B = createB // expected-error{{function produces expected type 'B'; did you mean to call it with '()'?}} {{21-21=()}}
let _: A = createB // expected-error{{cannot convert value of type '() -> B' to expected type 'B'; did you mean to call it with '()'?}} {{21-21=()}}
let _: B = createB // expected-error{{cannot convert value of type '() -> B' to expected type 'B'; did you mean to call it with '()'?}} {{21-21=()}}

// With overloading, pick the fewest number of fixes.
var b = f7(f4, f1) // expected-error{{function produces expected type 'B'; did you mean to call it with '()'?}}
var b = f7(f4, f1) // expected-error{{cannot convert value of type '() -> B' (reference to global function 'f4') to expected type 'B'; did you mean to call it with '()'?}}
b.iAmAB()
}

Expand Down Expand Up @@ -339,7 +339,7 @@ func test_explicit_call_with_overloads() {
}

foo(S().foo)
// expected-error@-1 {{function produces expected type 'Int'; did you mean to call it with '()'?}} {{14-14=()}}
// expected-error@-1 {{cannot convert value of type '(Int, String) -> Int' to expected type 'Int'; did you mean to call it with '()' using its default arguments?}} {{14-14=()}}
}

// SR-11476
Expand All @@ -354,7 +354,7 @@ func testKeyPathSubscriptArgFixes(_ fn: @escaping () -> Int) {
// expected-note@-2{{force-unwrap using '!' to abort execution if the optional value contains 'nil'}}{{12-12=!}}

_ = \S.[nil] // expected-error {{'nil' is not compatible with expected argument type 'Int'}}
_ = \S.[fn] // expected-error {{function produces expected type 'Int'; did you mean to call it with '()'?}} {{13-13=()}}
_ = \S.[fn] // expected-error {{cannot convert value of type '() -> Int' (reference to parameter 'fn') to expected type 'Int'; did you mean to call it with '()'?}} {{13-13=()}}
}

func sr12426(a: Any, _ str: String?) {
Expand Down
12 changes: 6 additions & 6 deletions test/decl/var/properties.swift
Original file line number Diff line number Diff line change
Expand Up @@ -1305,32 +1305,32 @@ class SR_10995 {

class SR_9267 {}
extension SR_9267 {
var foo: String = { // expected-error {{extensions must not contain stored properties}} // expected-error {{function produces expected type 'String'; did you mean to call it with '()'?}} // expected-note {{Remove '=' to make 'foo' a computed property}}{{19-21=}}
var foo: String = { // expected-error {{extensions must not contain stored properties}} // expected-error {{cannot convert value of type '() -> String' to expected type 'String'; did you mean to call it with '()'?}} // expected-note {{Remove '=' to make 'foo' a computed property}}{{19-21=}}
return "Hello"
}
}

enum SR_9267_E {
var SR_9267_prop: String = { // expected-error {{enums must not contain stored properties}} // expected-error {{function produces expected type 'String'; did you mean to call it with '()'?}} // expected-note {{Remove '=' to make 'SR_9267_prop' a computed property}}{{28-30=}}
var SR_9267_prop: String = { // expected-error {{enums must not contain stored properties}} // expected-error {{cannot convert value of type '() -> String' to expected type 'String'; did you mean to call it with '()'?}} // expected-note {{Remove '=' to make 'SR_9267_prop' a computed property}}{{28-30=}}
return "Hello"
}
}

var SR_9267_prop_1: Int = { // expected-error {{function produces expected type 'Int'; did you mean to call it with '()'?}} // expected-note {{Remove '=' to make 'SR_9267_prop_1' a computed property}}{{25-27=}}
var SR_9267_prop_1: Int = { // expected-error {{cannot convert value of type '() -> Int' to expected type 'Int'; did you mean to call it with '()'?}} // expected-note {{Remove '=' to make 'SR_9267_prop_1' a computed property}}{{25-27=}}
return 0
}

class SR_9267_C {
var SR_9267_prop_2: String = { // expected-error {{function produces expected type 'String'; did you mean to call it with '()'?}} // expected-note {{Remove '=' to make 'SR_9267_prop_2' a computed property}}{{30-32=}}
var SR_9267_prop_2: String = { // expected-error {{cannot convert value of type '() -> String' to expected type 'String'; did you mean to call it with '()'?}} // expected-note {{Remove '=' to make 'SR_9267_prop_2' a computed property}}{{30-32=}}
return "Hello"
}
}

class SR_9267_C2 {
let SR_9267_prop_3: Int = { return 0 } // expected-error {{function produces expected type 'Int'; did you mean to call it with '()'?}} // expected-note {{Remove '=' to make 'SR_9267_prop_3' a computed property}}{{3-6=var}}{{27-29=}}
let SR_9267_prop_3: Int = { return 0 } // expected-error {{cannot convert value of type '() -> Int' to expected type 'Int'; did you mean to call it with '()'?}} // expected-note {{Remove '=' to make 'SR_9267_prop_3' a computed property}}{{3-6=var}}{{27-29=}}
}

class LazyPropInClass {
lazy var foo: Int = { return 0 } // expected-error {{function produces expected type 'Int'; did you mean to call it with '()'?}}
lazy var foo: Int = { return 0 } // expected-error {{cannot convert value of type '() -> Int' to expected type 'Int'; did you mean to call it with '()'?}}
// expected-note@-1 {{Remove '=' to make 'foo' a computed property}}{{21-23=}}{{3-8=}}
}
2 changes: 1 addition & 1 deletion test/diagnostics/pretty-printed-diagnostics.swift
Original file line number Diff line number Diff line change
Expand Up @@ -120,7 +120,7 @@ foo(b:
// CHECK: [[#LINE-1]] | extension A {
// CHECK: [[#LINE]] | let x: Int = { 42 }()
// CHECK: | ~~~~~~++
// CHECK: | ^ error: function produces expected type 'Int'; did you mean to call it with '()'?
// CHECK: | ^ error: cannot convert value of type '() -> Int' to expected type 'Int'; did you mean to call it with '()'? [insert '()']
// CHECK: | ^ note: Remove '=' to make 'x' a computed property [remove '= ' and replace 'let' with 'var']
// CHECK: [[#LINE+1]] | }

Expand Down
2 changes: 1 addition & 1 deletion test/expr/closure/closures.swift
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ var closure5 : (Double) -> Int = {

var closure6 = $0 // expected-error {{anonymous closure argument not contained in a closure}}

var closure7 : Int = { 4 } // expected-error {{function produces expected type 'Int'; did you mean to call it with '()'?}} {{27-27=()}} // expected-note {{Remove '=' to make 'closure7' a computed property}}{{20-22=}}
var closure7 : Int = { 4 } // expected-error {{cannot convert value of type '() -> Int' to expected type 'Int'; did you mean to call it with '()'?}} {{27-27=()}} // expected-note {{Remove '=' to make 'closure7' a computed property}}{{20-22=}}

var capturedVariable = 1
var closure8 = { [capturedVariable] in
Expand Down
2 changes: 1 addition & 1 deletion test/type/types.swift
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ var d2 : () -> Int = { 4 }

var d3 : () -> Float = { 4 }

var d4 : () -> Int = { d2 } // expected-error{{function produces expected type 'Int'; did you mean to call it with '()'?}} {{26-26=()}}
var d4 : () -> Int = { d2 } // expected-error{{cannot convert value of type '() -> Int' (reference to var 'd2') to expected type 'Int'; did you mean to call it with '()'?}} {{26-26=()}}

if #available(macOS 9999, iOS 9999, tvOS 9999, watchOS 9999, *) {
var e0 : [Int]
Expand Down