Skip to content
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

[SR-4559] Method called 'self' can be confused with regular 'self' #47136

Closed
swift-ci opened this issue Apr 11, 2017 · 8 comments · Fixed by #37992
Closed

[SR-4559] Method called 'self' can be confused with regular 'self' #47136

swift-ci opened this issue Apr 11, 2017 · 8 comments · Fixed by #37992
Labels
bug A deviation from expected or documented behavior. Also: expected but undesirable behavior. compiler The Swift compiler in itself diagnostics QoI Bug: Diagnostics Quality of Implementation expressions Feature: expressions identifiers Feature: Identifiers missing warning Bug: Missing warning self Feature → expressions: The 'self' expression swift 5.6 type checker Area → compiler: Semantic analysis

Comments

@swift-ci
Copy link
Collaborator

swift-ci commented Apr 11, 2017

Previous ID SR-4559
Radar rdar://problem/24223414
Original Reporter mouhcine (JIRA User)
Type Bug
Status Resolved
Resolution Done
Environment

macOS 10.12.4, Xcode 8.3.1

Additional Detail from JIRA
Votes 8
Component/s Compiler
Labels Bug
Assignee mouhcine (JIRA)
Priority Medium

md5: 557db84df0937d03fb4a61df8d1c72cf

is duplicated by:

relates to:

Issue Description:

This compiles because instance method `self` is accessible as a static member: `self`(_ self: TypeWithSelfMethod) -> () -> Void

func funcThatReturnsSomething(_ any: Any) -> Any {
    any
}

struct TypeWithSelfMethod {
    let property = self
    
    let propertyFromClosure: () = {
        print(self)
    }()
    
    let propertyFromFunc = funcThatReturnsSomething(self)
    
    func `self`() {
    }
}

This is particularly problematic as NSObject has a method with this name, so code to add target is compiling and doesn't refer to the self the user likely expects

import UIKit

class A: NSObject {

  private let control: UIControl = {
    let control = UIControl()
    control.addTarget(self, action: #selector(valueChanged), for: .valueChanged)
    return control
  }()

  @objc private func valueChanged() {
  }
}
@belkadan
Copy link
Contributor

It looks like there's no actual loss of safety here, because self isn't actually the object being initialized. I'm not quite sure what it is, and we should fix this, but it's not doing what you think it is.

<stdin>:9:11: error: value of type '(NSObject) -> () -> A' has no member 'x'
    print(self.x)
          ^~~~ ~

@swift-ci
Copy link
Collaborator Author

swift-ci commented Nov 17, 2018

Comment by Andrej (JIRA)

Consider the following example:

class Foo {

private let dimmingView: UIView = {
  let view = UIView();

  view.addGestureRecognizer(
    UITapGestureRecognizer(
      target: self, 
      action: #selector(handleBackdropTap(gestureRecognizer:))
    )
  )

  return view
}()

// ...

}

When you run this code you'll find that the view does have gesture recognizer added but its target is nil. This is highly misleading. I don't think Swift < 4 allowed this kind of behavior.

@nolanw
Copy link

nolanw commented Dec 14, 2020

There's more discussion at the closed-as-duplicate #47442

@typesanitizer
Copy link

Implementation notes from Slava and Pavel:

Approach 1: In contexts where self does not refer to an instance (i.e. outside of instance methods bodies and instance property bodies), references to the self method should be either qualified (so Foo.self) or the identifier is escaped with backticks (so `self`), otherwise, there is a warning. (say "self in a stored property initializer refers to the method NSObject.self, which may be unexpected" "add NSObject. to disable this warning" with fix-it). The best place to implement this is in PreCheckExpr.cpp, probably in resolveDeclRefExpr()

Approach 2: Implemented as a fix in constraint system, similar to AddQualifierToAccessTopLevelName that currently detects some forms of name shadowing. You'd likely have to implement a tailored fix for this situation and check all conversions from a function type to Any to make sure that function type doesn’t originate from an unapplied reference to member self on NSObject.

@swift-ci
Copy link
Collaborator Author

Comment by Jack March (JIRA)

Thanks a bunch theindigamer (JIRA User) for getting those notes! Went with approach 1 and made fix generic as isn't just for NSObject, it can also occur for any type that has/inherits a function called 'self'.

fix here #37992

@xedin
Copy link
Member

xedin commented Sep 3, 2021

Fixed by #37992 Please use next available snapshot of main branch to verify and close.

@keith
Copy link
Collaborator

keith commented Jan 5, 2022

I believe I found a case where this warning is invalid, I filed #57970

@keith
Copy link
Collaborator

keith commented Feb 23, 2022

Note that there is a swiftlint rule for many cases of this that you can enable now before the warning lands in swift 5.6 https://realm.github.io/SwiftLint/self_in_property_initialization.html

This issue was closed.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug A deviation from expected or documented behavior. Also: expected but undesirable behavior. compiler The Swift compiler in itself diagnostics QoI Bug: Diagnostics Quality of Implementation expressions Feature: expressions identifiers Feature: Identifiers missing warning Bug: Missing warning self Feature → expressions: The 'self' expression swift 5.6 type checker Area → compiler: Semantic analysis
Projects
None yet
7 participants