Skip to content

Add "Xlint:implicit-no-annotation" #5915

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

Closed
wants to merge 1 commit into from

Conversation

edmundnoble
Copy link
Contributor

@edmundnoble edmundnoble commented May 20, 2017

Wondering if this needs a more self-explanatory name. Warns on implicits without type annotations.

Edit: Also please let me know if I am doing this in the wrong phase; I went as early as possible just because this info is available right away.

@scala-jenkins scala-jenkins added this to the 2.12.3 milestone May 20, 2017
@sjrd
Copy link
Member

sjrd commented May 20, 2017

An implicit val in a local scope (e.g., within a def) should be allowed not to have a type annotation. Only field vals require a type annotation.

However, all defs require a type annotation.

@edmundnoble
Copy link
Contributor Author

Why exactly? I am working off of the comment in isValid in Implicits.scala, which seems to state that implicits without type annotations will not be considered for implicit resolution unless they occur before the search location in the source.

@sjrd
Copy link
Member

sjrd commented May 20, 2017

Because scala/scala3#1784 and scala/scala3#1785.

Local implicit vals are only visible in the scope that follows them, so it is safe to let their type be inferred. Moreover, it is extremely annoying to write explicit types for local implicit vals. For example the Scala.js codebase is full of

def someTransformation(tree: Tree): Tree = {
  implicit val pos = tree.pos
  ...
}

@edmundnoble
Copy link
Contributor Author

Makes sense to me. I'll try to make the change.

@edmundnoble edmundnoble force-pushed the implicit-no-annotation branch from 36ea4c8 to f092e93 Compare May 22, 2017 05:39
@edmundnoble
Copy link
Contributor Author

Change made and tested.

@sjrd
Copy link
Member

sjrd commented May 23, 2017

Thanks. I guess someone from the core team has to take over the technical review at this point.

@retronym
Copy link
Member

Copy link
Member

@retronym retronym left a comment

Choose a reason for hiding this comment

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

It is also worth looking at the history of the corresponding rule in the wartremover lint tool: https://github.com/wartremover/wartremover/commits/master/core/src/main/scala/wartremover/warts/ExplicitImplicitTypes.scala

It evolved to allow { impicit x => ... } lambda params without an result type on the ValDef representing the lamdba param x; added an some sort of exception for implicit classes.

@@ -710,6 +710,9 @@ trait Namers extends MethodSynthesis {
if (isScala) {
if (nme.isSetterName(tree.name)) ValOrVarWithSetterSuffixError(tree)
if (tree.mods.isPrivateLocal && tree.mods.isCaseAccessor) PrivateThisCaseClassParameterError(tree)
if (tree.mods.isImplicit && !owner.isTerm && settings.warnImplicitNoAnnotation && tree.tpt.isEmpty) {
reporter.warning(tree.pos, s"implicit value ${tree.name} has no type annotation")
Copy link
Member

Choose a reason for hiding this comment

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

Should be .name.decoded to avoid displaying encoded names like '$colon$colon`.

Copy link
Member

Choose a reason for hiding this comment

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

The term "type annotation" is widely understood but the spec talks about "result types" in this context (and about "type ascriptions" after expressions).

A precedent for wording of this sort of message is:

scala> def foo = { return 1; 1 }
<console>:11: error: method foo has return statement; needs result type
       def foo = { return 1; 1 }
                   ^

s/needs/should have a and I think it fits here.

Copy link
Member

Choose a reason for hiding this comment

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

(I guess this is to avoid overloading the term "annotation" with @annotations.)

Copy link
Contributor

Choose a reason for hiding this comment

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

Not that further motivation is needed, but I expected it to warn about lacking an implicit not found annotation.

@@ -108,7 +108,7 @@ object ScalaOptionParser {
"-g" -> List("line", "none", "notailcails", "source", "vars"),
"-target" -> List("jvm-1.5", "jvm-1.6", "jvm-1.7", "jvm-1.8"))
private def multiChoiceSettingNames = Map[String, List[String]](
"-Xlint" -> List("adapted-args", "nullary-unit", "inaccessible", "nullary-override", "infer-any", "missing-interpolator", "doc-detached", "private-shadow", "type-parameter-shadow", "poly-implicit-overload", "option-implicit", "delayedinit-select", "by-name-right-associative", "package-object-classes", "unsound-match", "stars-align"),
"-Xlint" -> List("adapted-args", "nullary-unit", "inaccessible", "nullary-override", "infer-any", "missing-interpolator", "doc-detached", "private-shadow", "type-parameter-shadow", "poly-implicit-overload", "option-implicit", "delayedinit-select", "by-name-right-associative", "package-object-classes", "unsound-match", "stars-align", "no-implicit-annotation"),
Copy link
Member

Choose a reason for hiding this comment

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

Perhaps: implicit-result-type

Copy link
Member

Choose a reason for hiding this comment

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

Without the rename, there is a typo here:

s/no-implicit-annotation/implicit-no-annotation

(The fact that you need to repeat yourself here is my fault, sorry...)

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'm curious; so my motivation was that it seems to be that all of these lint options are named for what they warn for. Nullary-unit, inaccessible, adapted args, these are all the "bad" that the lint option actually warns for itself. "implicit-result-type" seems inconsistent, because it would be named for the condition needed to not warn.

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 thought about it and I agree the rename is the most consistent option.

Copy link
Contributor

Choose a reason for hiding this comment

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

This still looks unfixed?

Copy link
Contributor

Choose a reason for hiding this comment

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

I can attest that naming these options is hard. I suspect no one will ever request -Xlint:poly-implicit-overload. You warn for implicit-lacks-type, or -Xlint:infer-X, since the warning is triggered by inference. -Xlint:infer-implicit-type.

@retronym
Copy link
Member

When adding a new warning, it's a can be helpful to run it across a few projects and review the output. That often turns up false positives. You can also post a gist of the output to help us review.

Here's how that looks for "re-starring" (using your modified compiler as the new reference compiler):

% sbt setupPublishCore publishLocal | tail -n 20

% git diff -U1
diff --git a/build.sbt b/build.sbt
index 8557e1280d..1e70b7d9ca 100644
--- a/build.sbt
+++ b/build.sbt
@@ -145,2 +145,3 @@ lazy val commonSettings = clearSourceAndResourceDirectories ++ publishSettings +
   fork in run := true,
+  scalacOptions in Compile ++= Seq("-Xlint:implicit-no-annotation"),
   scalacOptions in Compile in doc ++= Seq(

% sbt -Dstarr.version=2.12.3-bin-f092e93-SNAPSHOT test:compile

https://gist.github.com/53444a774c7675d7f115bd58b65ab498

@Jasper-M
Copy link
Contributor

Jasper-M commented May 31, 2017

Does this also warn for implicit objects? Because they have the same problem.
Dotty doesn't seem to have a problem with implicit objects though, so maybe they can be fixed.

@SethTisue SethTisue modified the milestones: 2.12.4, 2.12.3 Jun 27, 2017
@adriaanm
Copy link
Contributor

@edmundnoble, what's your plan regarding getting this across the finish line in time for 2.12.4? This would be a nice lint option and it looks like there isn't much more polish needed. To be included in 2.12.4, PRs must be mergeable (approved by reviewer) by Wed Sep 27.

@adriaanm adriaanm added the release-notes worth highlighting in next release notes label Sep 21, 2017
@edmundnoble edmundnoble force-pushed the implicit-no-annotation branch 2 times, most recently from 876630d to b688a4f Compare September 24, 2017 21:24
@edmundnoble
Copy link
Contributor Author

edmundnoble commented Sep 24, 2017

@retronym I've rebased, and added tests for the special cases you've mentioned: they didn't require any more changes to the warning check. I also changed "type annotation" to "result type" in the lint option and the warning itself.

I'm considering maybe relaxing the implicit def condition to allow no result type if the RHS is just a new call, but I think this is worth merging into 2.12.4 as it is now.
EDIT: I'm considering this exception based mostly on implicit conversions into AnyVal classes which usually take this form as well as the cases I encountered after re-starring.

@adriaanm
Copy link
Contributor

We'll allow PRs currently scheduled for 2.12.4 to be merged until Friday, run benchmarks and community builds over the weekend and Monday, and cut the release on Tuesday. Any PRs that regress performance / break the community build will be reverted and rescheduled for 2.12.5.

@adriaanm adriaanm modified the milestones: 2.12.4, 2.12.5 Oct 1, 2017
@adriaanm
Copy link
Contributor

adriaanm commented Oct 1, 2017

We ran out of time here for 2.12.4, but let's get this into a nightly as soon as all review comments are implemented.

@martin-g
Copy link

Ping! Is it a good time to merge this PR for 2.12.5 ?

@SethTisue
Copy link
Member

should I do a community build run so we can grep the log for the new warning and see what turns up?

@lrytz
Copy link
Member

lrytz commented Feb 23, 2018

@edmundnoble as far as I can see there are still a few minor changes to be done:

  • rename the option from no-implicit-annotation to implicit-result-type across the PR (including test file names)
  • use tree.name.decoded instead of tree.name in the warning messages, thest for such names
  • update the warning messages from has no type annotation to should have a result type

@SethTisue the logic looks correct, so you can run it through the community build already now.

@lrytz lrytz self-assigned this Feb 23, 2018
@SethTisue
Copy link
Member

SethTisue commented Feb 28, 2018

I'm sorry this PR sat so long — we are really trying to do better on this in 2018

gah, and actually I can't run (not easily, anyway) the community build until this is rebased, the validate-publish-core job was deleted. @edmundnoble would you mind rebasing onto current 2.12.x...?

Add local test

Remove warning for local implicit vals

More tests, inspired by WartRemover's

Implicit object test
@lrytz lrytz force-pushed the implicit-no-annotation branch from b688a4f to ce8ec43 Compare March 1, 2018 12:51
@lrytz
Copy link
Member

lrytz commented Mar 1, 2018

@edmundnoble / @SethTisue I rebased and pushed -f to edmundnoble/implicit-no-annotation (there were no conflicts)

@SethTisue
Copy link
Member

SethTisue commented Mar 2, 2018

community build run queued: https://scala-ci.typesafe.com/view/scala-2.12.x/job/scala-2.12.x-integrate-community-build/2635/ (404 til Jenkins finishes shaving his toes)

@lrytz
Copy link
Member

lrytz commented Mar 2, 2018

That didn't go very far:

ERROR: Couldn't find any revision to build. Verify the repository and branch configuration for this job.

@SethTisue
Copy link
Member

@SethTisue
Copy link
Member

gah, that timed out. queued run 2645. builds from 2643 should still be cached, so when it comes time to grep the logs, we'll need to grep both of them together.

@SethTisue
Copy link
Member

(note that these runs don't explicitly enable the new flag everywhere, so we're only seeing the warnings for projects that have -Xlint enabled. this is probably sufficient to evaluate the quality.)

@lrytz
Copy link
Member

lrytz commented Mar 8, 2018

The build timed out; there's 125 lines with "has no type annotation" in the log, checking if those are all intended would give a good estimate.

@SethTisue
Copy link
Member

in run 2645 which is a continuation of 2643, there are a bunch of new compiler errors like:

[kind-projector] [error] /home/jenkins/workspace/scala-2.12.x-integrate-community-build/target-0.9.11/project-builds/kind-projector-cad88983fe673ab2ad72b4a5f1d7ca5de5e38d0e/src/main/scala/KindProjector.scala:93:14: not enough arguments for method require: (requirement: Boolean, message: => Any)Unit.
[kind-projector] [error] Unspecified value parameter message.
[kind-projector] [error]       require(i >= 0)
[kind-projector] [error]              ^

@lrytz lrytz modified the milestones: 2.12.5, 2.12.6 Mar 12, 2018
@SethTisue
Copy link
Member

this needs another rebase, now, in order to get better community build results

@SethTisue SethTisue modified the milestones: 2.12.6, 2.12.7 Mar 23, 2018
@adriaanm
Copy link
Contributor

Closing due to inactivity. Happy to accept a resubmission, though that should go to 2.13.x now.

@adriaanm adriaanm closed this May 30, 2018
@som-snytt
Copy link
Contributor

Maybe the community build should be peer-to-peer, with "volunteer" computers all over the world verifying every scala project for every commit.

@adriaanm
Copy link
Contributor

We promise we won't mine bitcoin in macros.

@SethTisue SethTisue removed this from the 2.12.7 milestone Sep 10, 2018
@som-snytt
Copy link
Contributor

This noble effort landed not as a lint but under -Xsource:3.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
release-notes worth highlighting in next release notes
Projects
None yet
Development

Successfully merging this pull request may close these issues.