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
Closed

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

swift-ci opened this issue Apr 11, 2017 · 8 comments

Comments

@swift-ci
Copy link
Collaborator

@swift-ci 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:

  • SR-4865 target self should be illegal in property constructor
  • SR-6895 Timer property with initializer and self target causes crash at runtime
  • SR-7198 Using self in computed let
  • SR-7368 Bugs of self-referencing Default Property Values in subclasses
  • SR-7981 self available without backticks in let initialization closure of NSObject
  • SR-8440 Using self inside a let initializer

relates to:

  • SR-4138 Static properties are allowed to use without qualifier in initializer of instance property

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

@belkadan belkadan commented Apr 11, 2017

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 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 nolanw commented Dec 14, 2020

There's more discussion at the closed-as-duplicate https://bugs.swift.org/browse/SR-4865

@typesanitizer
Copy link

@typesanitizer typesanitizer commented Jun 11, 2021

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

@swift-ci swift-ci commented Jun 20, 2021

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 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 keith commented Jan 5, 2022

I believe I found a case where this warning is invalid, I filed https://bugs.swift.org/browse/SR-15691

@keith
Copy link
Collaborator

@keith 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

@swift-ci swift-ci transferred this issue from apple/swift-issues Apr 25, 2022
This issue was closed.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

6 participants