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

Warn on bad extensions of aliases #22362

Merged
merged 4 commits into from
Jan 29, 2025
Merged

Conversation

RoccoMathijn
Copy link
Contributor

Fixes #22233

@RoccoMathijn
Copy link
Contributor Author

Hi @som-snytt! Would you like to have a look at this since you opened the issue and the change is in code that you authored?

Copy link
Member

@KacperFKorban KacperFKorban left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks great! Thanks for the contribution.

I added a small nitpick comment, but you can ignore it if you don't like it, since it's purely a personal preference/opinion.

compiler/src/dotty/tools/dotc/typer/RefChecks.scala Outdated Show resolved Hide resolved
@KacperFKorban
Copy link
Member

Sorry, I got used to doing reviews for people that can merge by themselves, so the call for action is very unclear 😅 , so either:

  1. push a change to the branch,
  2. or answer my comment

@som-snytt
Copy link
Contributor

I'm suspicious about aliases that are not effectively final. I'm taking a look now.

@som-snytt
Copy link
Contributor

This is the use case I was thinking of, but it is covered by the previous change, not to warn on overrides.

It's already covered in tests/warn/i16743.scala although I've made it look slightly different.

extension (s: String) def length = 42 // warn

import compiletime.*

trait T:
  def t = "t"

trait Quote:
  type Tree
  given TreeMethods = deferred
  trait TreeMethods:
    extension (self: Tree) def t: String

class QuotesImpl extends Quote:
  type Tree = T
  override given TreeMethods:
    extension (self: Tree) def t: String = self.t

Copy link
Contributor

@som-snytt som-snytt left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Otherwise LGTM!

compiler/src/dotty/tools/dotc/typer/RefChecks.scala Outdated Show resolved Hide resolved
@@ -0,0 +1,7 @@
-- [E194] Potential Issue Warning: tests/warn/i22233.scala:1:26 --------------------------------------------------------
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

probably a check file is not needed, as the text is vetted by the original test.

what I would do is move tests/pos/ext-override.scala to warns.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I removed the check file 👍

Also I moved tests/pos/ext-override.scala to the warn but actually I don't understand the reasoning. The tests in warn all give a warning right? In this test case there are no warnings. Could you elaborate?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@RoccoMathijn they allow warn tests to have zero warnings, which is useful. I think (IMHO) tests about lack of warning should go in warn, while testing "does this compile" remain in pos. A warn test can still have -Werror to announce that no warns are expected (so you don't have to scan the test code).

@KacperFKorban
Copy link
Member

@som-snytt I was thinking about a similar example:

//> using scala 3.nightly

class Animal {
  def show: String = "Animal"
  def show1: String = "Animal"
}
class Dog extends Animal

abstract class A:
  type X
  extension (a: X) def show: String

class B extends A:
  override type X = Animal
  extension (d: X) override def show: String = "Dog"

class C:
  type X = Animal
  extension (d: X) def show1: String = "Dog" // no warn on nightly, warn now

@main
def main =
  given B {}
  val dog = new Dog
  println(dog.show)
  given C {}
  println(dog.show1)

This change is closer to being correct IMO. Though, I'm not sure if we should also warn on B#show, since this one also will never be used. Though even if that's the case, I think that it would be an unrelated bug.

@som-snytt
Copy link
Contributor

@KacperFKorban yes. dog.show is a good one, I'll use that for all future simple examples.

The justification for not warning at the override in B is "don't warn for something the user can do nothing about".

Some -Wunused are silenced by ???, so another choice would be to warn normally but not if the RHS is ???. Also the override extension could be marked @unused. I agree that would be a future enhancement, a Spree for another day.

Another example for overriding is that -Wunused:params avoids warning if the signature is "fixed" by a superclass, because maybe you can't change it; but IIRC I dropped that heuristic and instead just require @unused if that is intended. The same logic could apply to B here: warn by default but provide easy explicit escape hatches.

@som-snytt
Copy link
Contributor

I forgot https://github.com/scala/scala3/pull/21191/files
and #21190

in case it is relevant.

Copy link
Member

@KacperFKorban KacperFKorban left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks Good! Thanks!

@KacperFKorban KacperFKorban merged commit 5fe57c2 into scala:main Jan 29, 2025
29 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Warn on bad extensions of effectively final aliases
3 participants