Skip to content

Fix overriding problems #1243

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

Merged
merged 16 commits into from
May 23, 2016
Merged

Fix overriding problems #1243

merged 16 commits into from
May 23, 2016

Conversation

odersky
Copy link
Contributor

@odersky odersky commented May 1, 2016

This fixes the missing "ambiguous overload" error of #1240. More work is needed to fix the multiple overriddenSymbols scenario.

Review by @retronym or @DarkDimius

!sym1.is(Bridge) && !sym2.is(Bridge))
// double definition of two methods with same signature in one class;
// don't merge them.
return NoDenotation
Copy link
Member

Choose a reason for hiding this comment

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

Can we get here with private sym1 or sym2? That's another case that prevents overriding.

Copy link
Member

@retronym retronym May 1, 2016

Choose a reason for hiding this comment

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

Also, can we get here with constructors? These also cannot be invoved in overriding.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

In both cases, the existing resolution will pick the right symbol. So these should not be a problem.

@odersky
Copy link
Contributor Author

odersky commented May 17, 2016

Going to merge by tomorrow unless there are further comments

odersky added 13 commits May 18, 2016 19:43
scala#1240 shows that we need to detect ambiguous overloads of methods
coming from the same base class (with different signatures there)
that have the same signature in some deriving class. This was
undetected before because the two methods were simply merged into
one overloaded alternative.
Once we do not merge methods with same signature anymore
we got an ambiguous overload between the constructors of
Any and Object after erasure (when all Any methods are
moved to Object). To avoid this, we map the Any constructor
to the Object constructor after erasure.
This happens once we do not merge methods with the same signature coming
from the same class.
When finding two symbols in the same class that have the same signature
as seen from some prefix, issue a merge error.

This is simpler and more robust than the alternative of producing an overloaded
denotation and dealing with it afterwards.
This showcases a tricky interaction between overloading and overriding.
See discussion of scala#1240 for context.
…e TermRef

This happens once we do not merge methods with the same signature coming
from the same class. (reverted from commit 83262d0)

This case no longer applies as such a situation will now give a MergeError instead.
We cannot throw a merge error if atSignature does not give
a unique single denotation. Counter example is compiling dotty itself,
where we get a false negative during bridge generation.

Instead, atSigature needs to return a normal denotation, and we
need to check separately where required that a denotation is in
fact a SingleDenotation.
Used to throw an uncaught merge error in checkAllOverrides
when compiling i1240c.scala.
Real test is in neg/customargs
During an attempted dotty bootstrap it was noted that Types.scala did not compile
anymore, because `checkUnique` threw a `TypeError` during erasure. The issue was an
overloaded member `name` in TermrefWithSig. In NamedType:

    def name: Name

In TermRef:

    def name: TermName

Before erasure, there's one member `name`, after erasure there are two (because after
erasure result type counts). The error arose when trying to recompute a member
of a `TermRefWithSig` where the name is `name` and the expected signature is `(Nil, ?)`.
Since there are two members that match the name and the signature, `checkUnique`
triggered a `TypeError`. Before adding `checkUnique`, the previous `atSignature`
call would just have returned an arbitrary choice among the two alternative definitions
of `name`.

The fix is not to use `checkUnique` but to fall back to `d.current` in the case where
several alternatives appear.

Interestingly, the failure only triggers when -Ycheck options are *disabled*. I added a new
test that compiles Types.scala without checks, so we catch this and possibly  similar bugs
in the future.
@odersky
Copy link
Contributor Author

odersky commented May 19, 2016

Added one important commit and rebased to master.

@smarter
Copy link
Member

smarter commented May 19, 2016

Interestingly, the failure only triggers when -Ycheck options are disabled

Any idea why?

@DarkDimius
Copy link
Contributor

@odersky I didn't yet have a chance to see if this fix is sufficient. I'm fine with meging it now if it's needed in the mainline.

odersky added 3 commits May 19, 2016 17:14
The previous additional test messed up partest in that file Types.scala
was copied twice into the partest-generated directory and then the
pos/core tests would compile both copies. This gave a double definition
which manifested itself under -Yno-double-bindings as an assertion error.

Ideally, partest generation would guard against this situation. For now I avoid
the problem by compiling the whole of core without -Ycheck, not jst Types.scala.
Unrelated to other commits but useful to get in.
@odersky odersky mentioned this pull request May 20, 2016
@odersky
Copy link
Contributor Author

odersky commented May 20, 2016

/rebuild

@odersky odersky merged commit 3e3df65 into scala:master May 23, 2016
@allanrenucci allanrenucci deleted the fix-#1240 branch December 14, 2017 16:59
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.

4 participants