Skip to content

SR-13976: Improve compiler error message: "partial application of ‘mutating’ method is not allowed" #35466

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

Merged
merged 1 commit into from
Oct 7, 2021
Merged
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
8 changes: 4 additions & 4 deletions include/swift/AST/DiagnosticsSema.def
Original file line number Diff line number Diff line change
Expand Up @@ -3700,20 +3700,20 @@ NOTE(ambiguous_because_of_trailing_closure,none,
// Cannot capture inout-ness of a parameter
// Partial application of foreign functions not supported
ERROR(partial_application_of_function_invalid,none,
"partial application of %select{"
"cannot reference %select{"
"'mutating' method|"
"'super.init' initializer chain|"
"'self.init' initializer delegation|"
"'super' instance method with metatype base"
"}0 is not allowed",
"}0 as function value",
(unsigned))
WARNING(partial_application_of_function_invalid_swift4,none,
"partial application of %select{"
"cannot reference %select{"
"'mutating' method|"
"'super.init' initializer chain|"
"'self.init' initializer delegation|"
"'super' instance method with metatype base"
"}0 is not allowed; calling the function has undefined behavior and will "
"}0 as function value; calling the function has undefined behavior and will "
Copy link
Author

@abdulajet abdulajet Oct 6, 2021

Choose a reason for hiding this comment

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

I cannot build swift locally at the moment, while I fix that so I can run the test suite locally. Does the second clause here make sense? "cannot reference x as function value calling the function has undefined..."

I think so since is error/warning will be in the context of a function I believe

Copy link
Contributor

Choose a reason for hiding this comment

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

Yes, I think it makes sense, second part is a clarification on why it can't be used as a function value - because calling it is UB.

"be an error in future Swift versions",
(unsigned))

Expand Down
3 changes: 3 additions & 0 deletions lib/Sema/CSDiagnostics.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4189,6 +4189,9 @@ bool PartialApplicationFailure::diagnoseAsError() {
kind = RefKind::SuperMethod;
}

/* TODO(diagnostics): SR-15250,
Add a "did you mean to call it?" note with a fix-it for inserting '()'
if function type has no params or all have a default value. */
auto diagnostic = CompatibilityWarning
? diag::partial_application_of_function_invalid_swift4
: diag::partial_application_of_function_invalid;
Expand Down
4 changes: 2 additions & 2 deletions test/Constraints/construction.swift
Original file line number Diff line number Diff line change
Expand Up @@ -241,15 +241,15 @@ func sr_10837() {
convenience init(foo: Int = 42) {
self.init(value:)(foo) // Ok
self.init(value:)
// expected-error@-1 {{partial application of 'self.init' initializer delegation is not allowed}}
// expected-error@-1 {{cannot reference 'self.init' initializer delegation as function value}}
}
}

class C : A {
override init(bar: Int) {
super.init(bar:)(bar) // Ok
super.init(bar:)
// expected-error@-1 {{partial application of 'super.init' initializer chain is not allowed}}
// expected-error@-1 {{cannot reference 'super.init' initializer chain as function value}}
}
}
}
Expand Down
4 changes: 2 additions & 2 deletions test/Constraints/members.swift
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ func g0(_: (inout X) -> (Float) -> ()) {}
_ = x.f0(i)
x.f0(i).f1(i)

g0(X.f1) // expected-error{{partial application of 'mutating' method}}
g0(X.f1) // expected-error{{cannot reference 'mutating' method as function value}}

_ = x.f0(x.f2(1))
_ = x.f0(1).f2(i)
Expand Down Expand Up @@ -74,7 +74,7 @@ struct GZ<T> {

var z = Z(i: 0)
var getI = z.getI
var incI = z.incI // expected-error{{partial application of 'mutating'}}
var incI = z.incI // expected-error{{cannot reference 'mutating' method as function value}}
var zi = z.getI()
var zcurried1 = z.curried
var zcurried2 = z.curried(0)
Expand Down
24 changes: 12 additions & 12 deletions test/Constraints/mutating_members.swift
Original file line number Diff line number Diff line change
Expand Up @@ -6,31 +6,31 @@ struct Foo {
mutating func boom() {}
}

let x = Foo.boom // expected-error{{partial application of 'mutating' method}}
let x = Foo.boom // expected-error{{cannot reference 'mutating' method as function value}}
var y = Foo()
let z0 = y.boom // expected-error{{partial application of 'mutating' method}}
let z1 = Foo.boom(&y) // expected-error{{partial application of 'mutating' method}}
let z0 = y.boom // expected-error{{cannot reference 'mutating' method as function value}}
let z1 = Foo.boom(&y) // expected-error{{cannot reference 'mutating' method as function value}}

func fromLocalContext() -> (inout Foo) -> () -> () {
return Foo.boom // expected-error{{partial application of 'mutating' method}}
return Foo.boom // expected-error{{cannot reference 'mutating' method as function value}}
}
func fromLocalContext2(x: inout Foo, y: Bool) -> () -> () {
if y {
return x.boom // expected-error{{partial application of 'mutating' method}}
return x.boom // expected-error{{cannot reference 'mutating' method as function value}}
} else {
return Foo.boom(&x) // expected-error{{partial application of 'mutating' method}}
return Foo.boom(&x) // expected-error{{cannot reference 'mutating' method as function value}}
}
}

func bar() -> P.Type { fatalError() }
func bar() -> Foo.Type { fatalError() }

_ = bar().boom // expected-error{{partial application of 'mutating' method}}
_ = bar().boom(&y) // expected-error{{partial application of 'mutating' method}}
_ = bar().boom(&y)() // expected-error{{partial application of 'mutating' method}}
_ = bar().boom // expected-error{{cannot reference 'mutating' method as function value}}
_ = bar().boom(&y) // expected-error{{cannot reference 'mutating' method as function value}}
_ = bar().boom(&y)() // expected-error{{cannot reference 'mutating' method as function value}}

func foo(_ foo: Foo.Type) {
_ = foo.boom // expected-error{{partial application of 'mutating' method}}
_ = foo.boom(&y) // expected-error{{partial application of 'mutating' method}}
_ = foo.boom(&y)() // expected-error{{partial application of 'mutating' method}}
_ = foo.boom // expected-error{{cannot reference 'mutating' method as function value}}
_ = foo.boom(&y) // expected-error{{cannot reference 'mutating' method as function value}}
_ = foo.boom(&y)() // expected-error{{cannot reference 'mutating' method as function value}}
}
24 changes: 12 additions & 12 deletions test/Constraints/mutating_members_compat.swift
Original file line number Diff line number Diff line change
Expand Up @@ -6,31 +6,31 @@ struct Foo {
mutating func boom() {}
}

let x = Foo.boom // expected-warning{{partial application of 'mutating' method}}
let x = Foo.boom // expected-warning{{cannot reference 'mutating' method as function value; calling the function has undefined behavior and will be an error in future Swift versions}}
Copy link
Author

Choose a reason for hiding this comment

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

I am not sure why this test was working on main before? the warnings for swift 4 should have always had the second clause.

But alas, run the tests locally and fixed the CI issues

var y = Foo()
let z0 = y.boom // expected-error{{partial application of 'mutating' method}}
let z1 = Foo.boom(&y) // expected-error{{partial application of 'mutating' method}}
let z0 = y.boom // expected-error{{cannot reference 'mutating' method as function value}}
let z1 = Foo.boom(&y) // expected-error{{cannot reference 'mutating' method as function value}}

func fromLocalContext() -> (inout Foo) -> () -> () {
return Foo.boom // expected-warning{{partial application of 'mutating' method}}
return Foo.boom // expected-warning{{cannot reference 'mutating' method as function value; calling the function has undefined behavior and will be an error in future Swift versions}}
}
func fromLocalContext2(x: inout Foo, y: Bool) -> () -> () {
if y {
return x.boom // expected-error{{partial application of 'mutating' method}}
return x.boom // expected-error{{cannot reference 'mutating' method as function value}}
} else {
return Foo.boom(&x) // expected-error{{partial application of 'mutating' method}}
return Foo.boom(&x) // expected-error{{cannot reference 'mutating' method as function value}}
}
}

func bar() -> P.Type { fatalError() }
func bar() -> Foo.Type { fatalError() }

_ = bar().boom // expected-warning{{partial application of 'mutating' method}}
_ = bar().boom(&y) // expected-error{{partial application of 'mutating' method}}
_ = bar().boom(&y)() // expected-error{{partial application of 'mutating' method}}
_ = bar().boom // expected-warning{{cannot reference 'mutating' method as function value; calling the function has undefined behavior and will be an error in future Swift versions}}
_ = bar().boom(&y) // expected-error{{cannot reference 'mutating' method as function value}}
_ = bar().boom(&y)() // expected-error{{cannot reference 'mutating' method as function value}}

func foo(_ foo: Foo.Type) {
_ = foo.boom // expected-warning{{partial application of 'mutating' method}}
_ = foo.boom(&y) // expected-error{{partial application of 'mutating' method}}
_ = foo.boom(&y)() // expected-error{{partial application of 'mutating' method}}
_ = foo.boom // expected-warning{{cannot reference 'mutating' method as function value; calling the function has undefined behavior and will be an error in future Swift versions}}
_ = foo.boom(&y) // expected-error{{cannot reference 'mutating' method as function value}}
_ = foo.boom(&y)() // expected-error{{cannot reference 'mutating' method as function value}}
}
6 changes: 3 additions & 3 deletions test/Constraints/protocols.swift
Original file line number Diff line number Diff line change
Expand Up @@ -136,7 +136,7 @@ func generic<T: P>(_ t: T) {
let _: (T) -> (Int) -> () = id(T.bar)
let _: (Int) -> () = id(T.bar(t))

_ = t.mut // expected-error{{partial application of 'mutating' method is not allowed}}
_ = t.mut // expected-error{{cannot reference 'mutating' method as function value}}
_ = t.tum // expected-error{{static member 'tum' cannot be used on instance of type 'T'}}
}

Expand Down Expand Up @@ -167,7 +167,7 @@ func existential(_ p: P) {
var p = p
// Fully applied mutating method
p.mut(1)
_ = p.mut // expected-error{{partial application of 'mutating' method is not allowed}}
_ = p.mut // expected-error{{cannot reference 'mutating' method as function value}}

// Instance member of existential)
let _: (Int) -> () = id(p.bar)
Expand Down Expand Up @@ -212,7 +212,7 @@ func staticExistential(_ p: P.Type, pp: P.Protocol) {
// Instance member of existential metatype -- not allowed
_ = p.bar // expected-error{{instance member 'bar' cannot be used on type 'P'}}
_ = p.mut // expected-error{{instance member 'mut' cannot be used on type 'P'}}
// expected-error@-1 {{partial application of 'mutating' method is not allowed}}
// expected-error@-1 {{cannot reference 'mutating' method as function value}}

// Static member of metatype -- not allowed
_ = pp.tum // expected-error{{static member 'tum' cannot be used on protocol metatype 'P.Protocol'}}
Expand Down
11 changes: 6 additions & 5 deletions test/NameLookup/name_lookup.swift
Original file line number Diff line number Diff line change
Expand Up @@ -288,23 +288,24 @@ class ThisDerived1 : ThisBase1 {
self.Type // expected-error {{type 'ThisDerived1' has no member 'Type'}}
}

// FIXME(SR-15250): Partial application diagnostic is applied incorrectly for some test cases.
class func staticTestSuper1() {
super.baseInstanceVar = 42 // expected-error {{member 'baseInstanceVar' cannot be used on type 'ThisBase1'}}
super.baseProp = 42 // expected-error {{member 'baseProp' cannot be used on type 'ThisBase1'}}
super.baseFunc0() // expected-error {{instance member 'baseFunc0' cannot be used on type 'ThisBase1'}}
// expected-error@-1 {{partial application of 'super' instance method with metatype base is not allowed}}
super.baseFunc0(ThisBase1())() // expected-error {{partial application of 'super' instance method with metatype base is not allowed}}
// expected-error@-1 {{cannot reference 'super' instance method with metatype base as function value}}
super.baseFunc0(ThisBase1())() // expected-error {{cannot reference 'super' instance method with metatype base as function value}}
super.baseFunc1(42) // expected-error {{instance member 'baseFunc1' cannot be used on type 'ThisBase1'}}
// expected-error@-1 {{partial application of 'super' instance method with metatype base is not allowed}}
super.baseFunc1(ThisBase1())(42) // expected-error {{partial application of 'super' instance method with metatype base is not allowed}}
// expected-error@-1 {{cannot reference 'super' instance method with metatype base as function value}}
super.baseFunc1(ThisBase1())(42) // expected-error {{cannot reference 'super' instance method with metatype base as function value}}
super[0] = 42.0 // expected-error {{instance member 'subscript' cannot be used on type 'ThisBase1'}}
super.baseStaticVar = 42
super.baseStaticProp = 42
super.baseStaticFunc0()

super.baseExtProp = 42 // expected-error {{member 'baseExtProp' cannot be used on type 'ThisBase1'}}
super.baseExtFunc0() // expected-error {{instance member 'baseExtFunc0' cannot be used on type 'ThisBase1'}}
// expected-error@-1 {{partial application of 'super' instance method with metatype base is not allowed}}
// expected-error@-1 {{cannot reference 'super' instance method with metatype base as function value}}
super.baseExtStaticVar = 42 // expected-error {{instance member 'baseExtStaticVar' cannot be used on type 'ThisBase1'}}
super.baseExtStaticProp = 42 // expected-error {{member 'baseExtStaticProp' cannot be used on type 'ThisBase1'}}
super.baseExtStaticFunc0()
Expand Down
4 changes: 2 additions & 2 deletions test/Parse/super.swift
Original file line number Diff line number Diff line change
Expand Up @@ -21,11 +21,11 @@ class D : B {
}

override init(x:Int) {
let _: () -> B = super.init // expected-error {{partial application of 'super.init' initializer chain is not allowed}}
let _: () -> B = super.init // expected-error {{cannot reference 'super.init' initializer chain as function value}}
}

convenience init(y:Int) {
let _: () -> D = self.init // expected-error {{partial application of 'self.init' initializer delegation is not allowed}}
let _: () -> D = self.init // expected-error {{cannot reference 'self.init' initializer delegation as function value}}
}

init(z: Int) {
Expand Down
2 changes: 1 addition & 1 deletion test/expr/capture/inout.swift
Original file line number Diff line number Diff line change
Expand Up @@ -13,4 +13,4 @@ struct C {
}

var c = C()
let x = c.f // expected-error{{partial application of 'mutating' method is not allowed}}
let x = c.f // expected-error{{cannot reference 'mutating' method as function value}}
8 changes: 4 additions & 4 deletions test/expr/postfix/dot/init_ref_delegation.swift
Original file line number Diff line number Diff line change
Expand Up @@ -125,7 +125,7 @@ class Z5 : Z4 {
// Ill-formed initialization: failure to call initializer.
class Z6 {
convenience init() {
var _ : () -> Z6 = self.init // expected-error{{partial application of 'self.init' initializer delegation is not allowed}}
var _ : () -> Z6 = self.init // expected-error{{cannot reference 'self.init' initializer delegation as function value}}
}

init(other: Z6) { }
Expand Down Expand Up @@ -171,15 +171,15 @@ struct S {
init() {
let _ = S.init()
self.init()
let _ = self.init // expected-error{{partial application of 'self.init' initializer delegation is not allowed}}
let _ = self.init // expected-error{{cannot reference 'self.init' initializer delegation as function value}}
}
}

class C {
convenience init() { // expected-note 11 {{selected non-required initializer 'init()'}}
self.init()
let _: C = self.init() // expected-error{{cannot convert value of type '()' to specified type 'C'}}
let _: () -> C = self.init // expected-error{{partial application of 'self.init' initializer delegation is not allowed}}
let _: () -> C = self.init // expected-error{{cannot reference 'self.init' initializer delegation as function value}}
}

init(x: Int) {} // expected-note 11 {{selected non-required initializer 'init(x:)'}}
Expand All @@ -191,7 +191,7 @@ class D: C {
override init(x: Int) {
super.init(x: x)
let _: C = super.init() // expected-error{{cannot convert value of type '()' to specified type 'C'}}
let _: () -> C = super.init // expected-error{{partial application of 'super.init' initializer chain is not allowed}}
let _: () -> C = super.init // expected-error{{cannot reference 'super.init' initializer chain as function value}}
}

func foo() {
Expand Down
2 changes: 1 addition & 1 deletion test/type/self.swift
Original file line number Diff line number Diff line change
Expand Up @@ -355,7 +355,7 @@ do {
let _: Self = super.property // expected-error {{cannot convert value of type 'D' to specified type 'Self'}}
let _: Self = super[] // expected-error {{cannot convert value of type 'D' to specified type 'Self'}}
let _: () -> Self = super.method
// expected-error@-1 {{partial application of 'super' instance method with metatype base is not allowed}}
// expected-error@-1 {{cannot reference 'super' instance method with metatype base as function value}}
// expected-error@-2 {{cannot convert value of type '(C) -> () -> D' to specified type '() -> Self'}}
}
}
Expand Down