Description
Describe the bug
The new shorthand syntax for optional binding in if
, guard
and while
conditions does not provide a reference to the original bound variable. This is also not the case for the extended syntax let i = i
but with it we are able to jump to the original via the variable reference on the right-hand side.
Steps To Reproduce
Run swift-ide-test -print-indexed-symbols -source-filename
for the file main.swift
with the content
private class C {
let i: Int? = nil
func f() -> Int {
if let i { return i }
if let i = i { return i }
return 0
}
}
We receive the following output:
1:15 | class/Swift | C | s:14swift_ide_test1C33_655A52213DC570E6117BF12D4C61C186LLC | Def | rel: 0
2:9 | instance-property/Swift | i | s:14swift_ide_test1C33_655A52213DC570E6117BF12D4C61C186LLC1iSiSgvp | Def,RelChild | rel: 1
RelChild | class/Swift | C | s:14swift_ide_test1C33_655A52213DC570E6117BF12D4C61C186LLC
2:9 | instance-method/acc-get/Swift | getter:i | s:14swift_ide_test1C33_655A52213DC570E6117BF12D4C61C186LLC1iSiSgvg | Def,Impl,RelChild,RelAcc | rel: 1
RelChild,RelAcc | instance-property/Swift | i | s:14swift_ide_test1C33_655A52213DC570E6117BF12D4C61C186LLC1iSiSgvp
2:9 | instance-method/acc-set/Swift | setter:i | s:14swift_ide_test1C33_655A52213DC570E6117BF12D4C61C186LLC1iSiSgvs | Def,Impl,RelChild,RelAcc | rel: 1
RelChild,RelAcc | instance-property/Swift | i | s:14swift_ide_test1C33_655A52213DC570E6117BF12D4C61C186LLC1iSiSgvp
2:12 | struct/Swift | Int | s:Si | Ref,RelCont | rel: 1
RelCont | instance-property/Swift | i | s:14swift_ide_test1C33_655A52213DC570E6117BF12D4C61C186LLC1iSiSgvp
4:10 | instance-method/Swift | f() | s:14swift_ide_test1C33_655A52213DC570E6117BF12D4C61C186LLC1fSiyF | Def,Dyn,RelChild | rel: 1
RelChild | class/Swift | C | s:14swift_ide_test1C33_655A52213DC570E6117BF12D4C61C186LLC
4:17 | struct/Swift | Int | s:Si | Ref,RelCont | rel: 1
RelCont | instance-method/Swift | f() | s:14swift_ide_test1C33_655A52213DC570E6117BF12D4C61C186LLC1fSiyF
6:20 | instance-property/Swift | i | s:14swift_ide_test1C33_655A52213DC570E6117BF12D4C61C186LLC1iSiSgvp | Ref,Read,RelCont | rel: 1
RelCont | instance-method/Swift | f() | s:14swift_ide_test1C33_655A52213DC570E6117BF12D4C61C186LLC1fSiyF
6:20 | instance-method/acc-get/Swift | getter:i | s:14swift_ide_test1C33_655A52213DC570E6117BF12D4C61C186LLC1iSiSgvg | Ref,Call,Impl,RelCall,RelCont | rel: 1
RelCall,RelCont | instance-method/Swift | f() | s:14swift_ide_test1C33_655A52213DC570E6117BF12D4C61C186LLC1fSiyF
1:15 | constructor/Swift | init() | s:14swift_ide_test1C33_655A52213DC570E6117BF12D4C61C186LLCADycfc | Def,Impl,RelChild | rel: 1
RelChild | class/Swift | C | s:14swift_ide_test1C33_655A52213DC570E6117BF12D4C61C186LLC
Notice that while the binding let i = i
references the original class property i
this is not the case for the binding let i
.
This is an issue in editors where a "Jump to Definition" doesn't work anymore. Even more problematic, however, it is for linter tools which are now unable to answer questions like "Are all declared variables used somewhere?". I especially want to mention SwiftLint, the unused_declaration
rule of which is currently not working.
Expected behavior
A redeclared variable should have a reference to its original.
Writing this sentence I feel like this is more a feature request than a bug. It would also be helpful in code like
func f(a: Int) {
// ...
var a = 1
// ...
}
where "Jump to Definition" on var a
would jump to the function parameter.
Environment
- macOS 12.6
- Xcode 14.0.1 14A400
- Swift 5.7 (swiftlang-5.7.0.127.4 clang-1400.0.29.50)