-
Notifications
You must be signed in to change notification settings - Fork 10.5k
Sema: Do not diagnose set accessor availability for InOutExpr
s inside of LoadExpr
s
#72369
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
tshortli
merged 4 commits into
swiftlang:main
from
tshortli:spurious-unavailable-setter-diagnostic
Mar 19, 2024
Merged
Changes from all commits
Commits
Show all changes
4 commits
Select commit
Hold shift + click to select a range
bab6518
Sema: Add a test for accessor availability diagnostics.
tshortli 5a23239
Sema: Do not diagnose set accessor availability for `InOutExpr`s insi…
tshortli 86200b1
Parse: Resolve an unused variable warning.
tshortli ca925ab
stdlib: Resolve an un-mutated var warning.
tshortli File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,253 @@ | ||
// RUN: %target-typecheck-verify-swift -parse-as-library -module-name MyModule | ||
|
||
struct Value { | ||
static let defaultValue = Value(a: Nested(b: 1)) | ||
|
||
struct Nested { | ||
var b: Int | ||
|
||
@discardableResult | ||
mutating func setToZero() -> Int { | ||
let prev = b | ||
b = 0 | ||
return prev | ||
} | ||
} | ||
|
||
var a: Nested | ||
|
||
subscript(_ i: Int) -> Nested { | ||
get { a } | ||
set { a = newValue } | ||
} | ||
|
||
@discardableResult | ||
mutating func setToZero() -> Int { | ||
let prev = a.b | ||
a.setToZero() | ||
return prev | ||
} | ||
} | ||
|
||
struct BaseStruct { | ||
var available: Value = .defaultValue | ||
|
||
var unavailableGetter: Value { | ||
@available(*, unavailable) | ||
get { fatalError() } // expected-note 24 {{getter for 'unavailableGetter' has been explicitly marked unavailable here}} | ||
set {} | ||
} | ||
|
||
var unavailableSetter: Value { | ||
get { .defaultValue } | ||
@available(*, unavailable) | ||
set { fatalError() } // expected-note 12 {{setter for 'unavailableSetter' has been explicitly marked unavailable here}} | ||
} | ||
|
||
var unavailableGetterAndSetter: Value { | ||
@available(*, unavailable) | ||
get { fatalError() } // expected-note 24 {{getter for 'unavailableGetterAndSetter' has been explicitly marked unavailable here}} | ||
@available(*, unavailable) | ||
set { fatalError() } // expected-note 12 {{setter for 'unavailableGetterAndSetter' has been explicitly marked unavailable here}} | ||
} | ||
} | ||
|
||
func takesIntInOut(_ i: inout Int) -> Int { | ||
return 0 | ||
} | ||
|
||
let someValue = Value.defaultValue | ||
|
||
func testRValueLoads() { | ||
var x = BaseStruct() // expected-warning {{variable 'x' was never mutated; consider changing to 'let' constant}} | ||
|
||
_ = x.available | ||
_ = x.available.a | ||
_ = x.available[0] | ||
_ = x.available[0].b | ||
|
||
_ = x.unavailableGetter // expected-error {{getter for 'unavailableGetter' is unavailable}} | ||
_ = x.unavailableGetter.a // expected-error {{getter for 'unavailableGetter' is unavailable}} | ||
_ = x.unavailableGetter[0] // expected-error {{getter for 'unavailableGetter' is unavailable}} | ||
_ = x.unavailableGetter[0].b // expected-error {{getter for 'unavailableGetter' is unavailable}} | ||
|
||
_ = x.unavailableSetter | ||
_ = x.unavailableSetter.a | ||
_ = x.unavailableSetter[0] | ||
_ = x.unavailableSetter[0].b | ||
|
||
_ = x.unavailableGetterAndSetter // expected-error {{getter for 'unavailableGetterAndSetter' is unavailable}} | ||
_ = x.unavailableGetterAndSetter.a // expected-error {{getter for 'unavailableGetterAndSetter' is unavailable}} | ||
_ = x.unavailableGetterAndSetter[0] // expected-error {{getter for 'unavailableGetterAndSetter' is unavailable}} | ||
_ = x.unavailableGetterAndSetter[0].b // expected-error {{getter for 'unavailableGetterAndSetter' is unavailable}} | ||
} | ||
|
||
func testLValueAssignments() { | ||
var x = BaseStruct() | ||
|
||
x.available = someValue | ||
x.available.a = someValue.a | ||
x.available[0] = someValue.a | ||
x.available[0].b = 1 | ||
|
||
x.unavailableGetter = someValue | ||
x.unavailableGetter.a = someValue.a // expected-error {{getter for 'unavailableGetter' is unavailable}} | ||
x.unavailableGetter[0] = someValue.a // expected-error {{getter for 'unavailableGetter' is unavailable}} | ||
x.unavailableGetter[0].b = 1 // expected-error {{getter for 'unavailableGetter' is unavailable}} | ||
|
||
x.unavailableSetter = someValue // expected-error {{setter for 'unavailableSetter' is unavailable}} | ||
x.unavailableSetter.a = someValue.a // FIXME: missing diagnostic for setter | ||
x.unavailableSetter[0] = someValue.a // expected-error {{setter for 'unavailableSetter' is unavailable}} | ||
x.unavailableSetter[0].b = 1 // expected-error {{setter for 'unavailableSetter' is unavailable}} | ||
|
||
x.unavailableGetterAndSetter = someValue // expected-error {{setter for 'unavailableGetterAndSetter' is unavailable}} | ||
x.unavailableGetterAndSetter.a = someValue.a // expected-error {{getter for 'unavailableGetterAndSetter' is unavailable}} FIXME: missing diagnostic for setter | ||
x.unavailableGetterAndSetter[0] = someValue.a // expected-error {{getter for 'unavailableGetterAndSetter' is unavailable}} expected-error {{setter for 'unavailableGetterAndSetter' is unavailable}} | ||
x.unavailableGetterAndSetter[0].b = 1 // expected-error {{getter for 'unavailableGetterAndSetter' is unavailable}} expected-error {{setter for 'unavailableGetterAndSetter' is unavailable}} | ||
} | ||
|
||
func testKeyPathLoads() { | ||
let a = [0] | ||
var x = BaseStruct() | ||
|
||
_ = x[keyPath: \.available] | ||
_ = x[keyPath: \.available.a] | ||
_ = x[keyPath: \.available[0]] | ||
_ = x[keyPath: \.available[0].b] | ||
_ = a[keyPath: \.[takesIntInOut(&x.available.a.b)]] | ||
_ = a[keyPath: \.[takesIntInOut(&x.available[0].b)]] | ||
|
||
_ = x[keyPath: \.unavailableGetter] // FIXME: missing diagnostic for getter | ||
_ = x[keyPath: \.unavailableGetter.a] // FIXME: missing diagnostic for getter | ||
_ = x[keyPath: \.unavailableGetter[0]] // FIXME: missing diagnostic for getter | ||
_ = x[keyPath: \.unavailableGetter[0].b] // FIXME: missing diagnostic for getter | ||
_ = a[keyPath: \.[takesIntInOut(&x.unavailableGetter.a.b)]] // expected-error {{getter for 'unavailableGetter' is unavailable}} | ||
_ = a[keyPath: \.[takesIntInOut(&x.unavailableGetter[0].b)]] // expected-error {{getter for 'unavailableGetter' is unavailable}} | ||
|
||
_ = x[keyPath: \.unavailableSetter] | ||
_ = x[keyPath: \.unavailableSetter.a] | ||
_ = x[keyPath: \.unavailableSetter[0]] | ||
_ = x[keyPath: \.unavailableSetter[0].b] | ||
_ = a[keyPath: \.[takesIntInOut(&x.unavailableSetter.a.b)]] // FIXME: missing diagnostic for setter | ||
_ = a[keyPath: \.[takesIntInOut(&x.unavailableSetter[0].b)]] // expected-error {{setter for 'unavailableSetter' is unavailable}} | ||
|
||
_ = x[keyPath: \.unavailableGetterAndSetter] // FIXME: missing diagnostic for getter | ||
_ = x[keyPath: \.unavailableGetterAndSetter.a] // FIXME: missing diagnostic for getter | ||
_ = x[keyPath: \.unavailableGetterAndSetter[0]] // FIXME: missing diagnostic for getter | ||
_ = x[keyPath: \.unavailableGetterAndSetter[0].b] // FIXME: missing diagnostic for getter | ||
_ = a[keyPath: \.[takesIntInOut(&x.unavailableGetterAndSetter.a.b)]] // expected-error {{getter for 'unavailableGetterAndSetter' is unavailable}} FIXME: missing diagnostic for setter | ||
_ = a[keyPath: \.[takesIntInOut(&x.unavailableGetterAndSetter[0].b)]] // expected-error {{getter for 'unavailableGetterAndSetter' is unavailable}} expected-error {{setter for 'unavailableGetterAndSetter' is unavailable}} | ||
} | ||
|
||
func testKeyPathAssignments() { | ||
var a = [0] | ||
var x = BaseStruct() | ||
|
||
x[keyPath: \.available] = someValue | ||
x[keyPath: \.available.a] = someValue.a | ||
x[keyPath: \.available[0]] = someValue.a | ||
x[keyPath: \.available[0].b] = 1 | ||
x[keyPath: \.available] = someValue | ||
a[keyPath: \.[takesIntInOut(&x.available.a.b)]] = 0 | ||
a[keyPath: \.[takesIntInOut(&x.available[0].b)]] = 0 | ||
|
||
x[keyPath: \.unavailableGetter] = someValue | ||
x[keyPath: \.unavailableGetter.a] = someValue.a // FIXME: missing diagnostic for getter | ||
x[keyPath: \.unavailableGetter[0]] = someValue.a // FIXME: missing diagnostic for getter | ||
x[keyPath: \.unavailableGetter[0].b] = 1 // FIXME: missing diagnostic for getter | ||
a[keyPath: \.[takesIntInOut(&x.unavailableGetter.a.b)]] = 0 // expected-error {{getter for 'unavailableGetter' is unavailable}} | ||
a[keyPath: \.[takesIntInOut(&x.unavailableGetter[0].b)]] = 0 // expected-error {{getter for 'unavailableGetter' is unavailable}} | ||
|
||
x[keyPath: \.unavailableSetter] = someValue | ||
x[keyPath: \.unavailableSetter.a] = someValue.a // FIXME: missing diagnostic for setter | ||
x[keyPath: \.unavailableSetter[0]] = someValue.a // FIXME: missing diagnostic for setter | ||
x[keyPath: \.unavailableSetter[0].b] = 1 // FIXME: missing diagnostic for setter | ||
a[keyPath: \.[takesIntInOut(&x.unavailableSetter.a.b)]] = 0 // FIXME: missing diagnostic for setter | ||
a[keyPath: \.[takesIntInOut(&x.unavailableSetter[0].b)]] = 0 // expected-error {{setter for 'unavailableSetter' is unavailable}} | ||
|
||
x[keyPath: \.unavailableGetterAndSetter] = someValue | ||
x[keyPath: \.unavailableGetterAndSetter.a] = someValue.a // FIXME: missing diagnostics for getter and setter | ||
x[keyPath: \.unavailableGetterAndSetter[0]] = someValue.a // FIXME: missing diagnostics for getter and setter | ||
x[keyPath: \.unavailableGetterAndSetter[0].b] = 1 // FIXME: missing diagnostics for getter and setter | ||
a[keyPath: \.[takesIntInOut(&x.unavailableGetterAndSetter.a.b)]] = 0 // expected-error {{getter for 'unavailableGetterAndSetter' is unavailable}} FIXME: missing diagnostic for setter | ||
a[keyPath: \.[takesIntInOut(&x.unavailableGetterAndSetter[0].b)]] = 0 // expected-error {{getter for 'unavailableGetterAndSetter' is unavailable}} expected-error {{setter for 'unavailableGetterAndSetter' is unavailable}} | ||
} | ||
|
||
func testMutatingMember() { | ||
var x = BaseStruct() | ||
let a = [0] | ||
|
||
x.available.setToZero() | ||
x.available[0].setToZero() | ||
_ = a[x.available.setToZero()] | ||
_ = a[x.available.a.setToZero()] | ||
_ = a[x.available[0].setToZero()] | ||
|
||
x.unavailableGetter.setToZero() // expected-error {{getter for 'unavailableGetter' is unavailable}} | ||
x.unavailableGetter[0].setToZero() // expected-error {{getter for 'unavailableGetter' is unavailable}} | ||
_ = a[x.unavailableGetter.setToZero()] // expected-error {{getter for 'unavailableGetter' is unavailable}} | ||
_ = a[x.unavailableGetter.a.setToZero()] // expected-error {{getter for 'unavailableGetter' is unavailable}} | ||
_ = a[x.unavailableGetter[0].setToZero()] // expected-error {{getter for 'unavailableGetter' is unavailable}} | ||
|
||
x.unavailableSetter.setToZero() // expected-error {{setter for 'unavailableSetter' is unavailable}} | ||
x.unavailableSetter[0].setToZero() // expected-error {{setter for 'unavailableSetter' is unavailable}} | ||
_ = a[x.unavailableSetter.setToZero()] // expected-error {{setter for 'unavailableSetter' is unavailable}} | ||
_ = a[x.unavailableSetter.a.setToZero()] // FIXME: missing diagnostic for setter | ||
_ = a[x.unavailableSetter[0].setToZero()] // expected-error {{setter for 'unavailableSetter' is unavailable}} | ||
|
||
x.unavailableGetterAndSetter.setToZero() // expected-error {{getter for 'unavailableGetterAndSetter' is unavailable}} expected-error {{setter for 'unavailableGetterAndSetter' is unavailable}} | ||
x.unavailableGetterAndSetter[0].setToZero() // expected-error {{getter for 'unavailableGetterAndSetter' is unavailable}} expected-error {{setter for 'unavailableGetterAndSetter' is unavailable}} | ||
_ = a[x.unavailableGetterAndSetter.setToZero()] // expected-error {{getter for 'unavailableGetterAndSetter' is unavailable}} expected-error {{setter for 'unavailableGetterAndSetter' is unavailable}} | ||
_ = a[x.unavailableGetterAndSetter.a.setToZero()] // expected-error {{getter for 'unavailableGetterAndSetter' is unavailable}} FIXME: should diagnose setter | ||
_ = a[x.unavailableGetterAndSetter[0].setToZero()] // expected-error {{getter for 'unavailableGetterAndSetter' is unavailable}} expected-error {{setter for 'unavailableGetterAndSetter' is unavailable}} | ||
} | ||
|
||
func testPassAsInOutParameter() { | ||
func takesInOut<T>(_ t: inout T) {} | ||
|
||
var x = BaseStruct() | ||
|
||
takesInOut(&x.available) | ||
takesInOut(&x.available.a) | ||
takesInOut(&x.available[0]) | ||
takesInOut(&x.available[0].b) | ||
|
||
takesInOut(&x.unavailableGetter) // expected-error {{getter for 'unavailableGetter' is unavailable}} | ||
takesInOut(&x.unavailableGetter.a) // expected-error {{getter for 'unavailableGetter' is unavailable}} | ||
takesInOut(&x.unavailableGetter[0]) // expected-error {{getter for 'unavailableGetter' is unavailable}} | ||
takesInOut(&x.unavailableGetter[0].b) // expected-error {{getter for 'unavailableGetter' is unavailable}} | ||
|
||
takesInOut(&x.unavailableSetter) // expected-error {{setter for 'unavailableSetter' is unavailable}} | ||
takesInOut(&x.unavailableSetter.a) // | ||
takesInOut(&x.unavailableSetter[0]) // expected-error {{setter for 'unavailableSetter' is unavailable}} | ||
takesInOut(&x.unavailableSetter[0].b) // expected-error {{setter for 'unavailableSetter' is unavailable}} | ||
|
||
takesInOut(&x.unavailableGetterAndSetter) // expected-error {{getter for 'unavailableGetterAndSetter' is unavailable}} expected-error {{setter for 'unavailableGetterAndSetter' is unavailable}} | ||
takesInOut(&x.unavailableGetterAndSetter.a) // expected-error {{getter for 'unavailableGetterAndSetter' is unavailable}} FIXME: missing diagnostic for setter | ||
takesInOut(&x.unavailableGetterAndSetter[0]) // expected-error {{getter for 'unavailableGetterAndSetter' is unavailable}} expected-error {{setter for 'unavailableGetterAndSetter' is unavailable}} | ||
takesInOut(&x.unavailableGetterAndSetter[0].b) // expected-error {{getter for 'unavailableGetterAndSetter' is unavailable}} expected-error {{setter for 'unavailableGetterAndSetter' is unavailable}} | ||
} | ||
|
||
var global = BaseStruct() | ||
|
||
struct TestPatternBindingInitExprs { | ||
var available = global.available | ||
var available_a = global.available.a | ||
var available_0 = global.available[0] | ||
var available_0_b = global.available[0].b | ||
|
||
var unavailableGetter = global.unavailableGetter // expected-error {{getter for 'unavailableGetter' is unavailable}} | ||
var unavailableGetter_a = global.unavailableGetter.a // expected-error {{getter for 'unavailableGetter' is unavailable}} | ||
var unavailableGetter_0 = global.unavailableGetter[0] // expected-error {{getter for 'unavailableGetter' is unavailable}} | ||
var unavailableGetter_0_b = global.unavailableGetter[0].b // expected-error {{getter for 'unavailableGetter' is unavailable}} | ||
|
||
var unavailableSetter = global.unavailableSetter | ||
var unavailableSetter_a = global.unavailableSetter.a | ||
var unavailableSetter_0 = global.unavailableSetter[0] | ||
var unavailableSetter_0_b = global.unavailableSetter[0].b | ||
|
||
var unavailableGetterAndSetter = global.unavailableGetterAndSetter // expected-error {{getter for 'unavailableGetterAndSetter' is unavailable}} | ||
var unavailableGetterAndSetter_a = global.unavailableGetterAndSetter.a // expected-error {{getter for 'unavailableGetterAndSetter' is unavailable}} | ||
var unavailableGetterAndSetter_0 = global.unavailableGetterAndSetter[0] // expected-error {{getter for 'unavailableGetterAndSetter' is unavailable}} | ||
var unavailableGetterAndSetter_0_b = global.unavailableGetterAndSetter[0].b // expected-error {{getter for 'unavailableGetterAndSetter' is unavailable}} | ||
} |
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.