-
Notifications
You must be signed in to change notification settings - Fork 1.1k
Fix #5224: Make implicit shadowing conform to the rules in the spec #5227
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
Conversation
The previous version of implicit shadowing considered a nested reference as a shadow _only_ if it matched the prototype of the implicit search. This is not backed up by the spec, and is different to what scalac does. Arguably, the spec is right here: We should consider an implicit ineligible if it is not visible as a simple name because a nested reference has the same name, no matter what the type of the nested reference is.
Helps to trouble-shoot the culprit during parallel testing
Should a nested non-implicit definition shadow an implicit definition, ie. should the following not compile, object Test {
class Foo
implicit def foo: Foo = ???
{
def foo = ???
implicitly[Foo] // outer foo is shadowed
}
} |
Since the type does not matter, we don't need to adapt it.
object Test {
class Foo
implicit def foo: Foo = ???
{
def foo = ???
implicitly[Foo] // outer foo is shadowed
} This should not compile, since the rules say "implicits are eligible if they can be referred to by a simple identifier". That's not the case in this example. |
FWIW, it compiles both with Dotty prior to this PR and Scala 2.13.x. |
I'd like to play around with this a bit ... I was digging around here because I had a hunch that shadowing might interact badly with your implicit caching strategy. I wasn't able to come up with a problematic case for caching because, prior to this PR, eligible implicits more or less only increased monotonically with more nested scopes. Now that shadowing can knock out arbitrary implicit definitions in outer scopes I think it might be possible to trick the caching mechanism into miscompiling. |
@odersky that example still compiles after this PR. The issue is in |
Correction, the problem seems to be here: https://github.com/lampepfl/dotty/blob/876fb32f830602e3175eb19bbc043b6079d3c449/compiler/src/dotty/tools/dotc/typer/Implicits.scala#L963-L970 Second time though, |
Is the issue that contextual implicits are retained in the cache and then found via a cache hit when only the implicit scope should be considered? |
That's also as required. Implicits in the implicit scope cannot be shadowed. The rules are: Contextual implicit: Any implicit value that can be referred to with a simple name qualifies Shadowing comes up only indirectly, to check that any contextual implicit that was found actually qualifies. |
Understood. But there's no implicit scope in play here. |
I think there is: The full type is (Aside: We should try whether we can reduce this aspect of type prefixes contributing to the implicit scope. In the past there have been some abuses where implicits were placed in package objects which made their implicit scope surprisingly large. So it might be good if we could at least avoid packages as parts of implicit scopes.) |
The previous version of implicit shadowing considered a nested reference
as a shadow only if it matched the prototype of the implicit search.
This is not backed up by the spec, and is different to what scalac does.
Arguably, the spec is right here: We should consider an implicit ineligible
if it is not visible as a simple name because a nested reference has the
same name, no matter what the type of the nested reference is.