GSoC Swift Refactoring/Detection Tools

Hey Swift community!

Before the submission for GSoC proposals open up, I wanted to run by some ideas by you guys.
I have had two things I really want to do with this GSoC and they are the following,

  1. Remove unnecessary keywords and type declarations if deemed unnecessary. These include but are not limited to
  • Unambiguous self keywords
  • Unnecessary type declarations
  • and so on…
  1. Thread safety analysis during compile time
  • Would behave much like Clang’s −Wthread−safety
  • Warn users about code that is attempting to update UI while not on the main thread
  • and so on…

A little about me, I have submitted and successfully merged one PR so far! Also, I am an undergraduate student and that’s about it :)

2 Likes

/cc @Anna_Zaks @kubamracek

/cc @akyrtzi @Xi_Ge @blangmuir

Hi Mike, it is great to see you’re interested in a Google Summer of Code project for Swift!

Project 1 sounds useful and likely doable in a GSoC time frame. Do you have specific examples the kinds of patterns you would want to remove? Coming up with specific examples would help spur a discussion.

Project 2 sounds more ambitious – probably too much for a Google Summer of Code project. For example, Clang’s -Wthread-safety has been worked on by multiple people including a summer intern and it still isn’t finished yet.

Warning about code that is attempting to update UI while not on the main thread sounds interesting and useful (for example, Apple has a dynamic analysis tool, Main Thread Checker, that does this at run time from Xcode). However, a challenge for doing that at compile time is determining when a piece of code is run on the main thread. Do you have examples of specific patterns you would want to warn on?

For both of these projects, I think a good next step would be for you to come up with some specific examples that we could discuss!

@Devin_Coughlin Thanks for the feedback!

I completely agree with you on project 2 but it just seemed like a cool idea :)

For project 1, the simplest case I can think off the top of my head is using unnecessary self. to refer to a variable within a function of a struct. Other simple case would be suggesting the user to remove the Int in let n : Int = 3. Basically, it would act as a linter.

For project 2, I was wondering if we could detect the simplest of patterns where the user forgets to update the UI on the main thread. For example, in cases like

   generatePieChart { pieChart in
      DispatchQueue.main.async {
        self.chart.setImage(pieChart)
      }
    }

I always find myself forgetting to put the DispatchQueue.main.async there. To detect these patterns, we could maybe see if there is a UI related call within a closure and warn the user if it is not done on the main thread?

These are all very simple cases but I would love to hear if anyone else has additional anti-patterns they always found themselves repeating!

Some things you might want to think about for the first project:

  • Is this a user-triggered refactoring action or a compiler warning? I think the latter would struggle to find support as some people prefer to be explicit in some cases (e.g. some people use self. even when redundant for reasons I think are related to shadowed names from the enclosing scope being unshadowed during refactoring). It would also likely require an Evolution proposal which could take significant time to be resolved.
  • Explicit type hints are still required in some cases due to compiler performance issues and it will be hard to distinguish this from actual redundancy.
1 Like

So if I understand correctly, for the main thread project you are proposing to warn on:

 generatePieChart { pieChart in
   self.chart.setImage(pieChart)
 }

and indicate to the user that they should wrap the call to self.chart.setImage() in an async call on the main thread.

What if the call to generatePieChart is already on the main thread? In this case, adding the async call isn’t necessary. You’ll need a way to determine whether a piece of code is already executing on the main thread. (Or, that it is definitely not executing on the main thread).