Skip to content

fix #1750: check problematic owner first to avoid cyclic reference #1852

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 3 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions compiler/src/dotty/tools/dotc/Compiler.scala
Original file line number Diff line number Diff line change
Expand Up @@ -44,13 +44,13 @@ class Compiler {
List(new FrontEnd), // Compiler frontend: scanner, parser, namer, typer
List(new sbt.ExtractDependencies), // Sends information on classes' dependencies to sbt via callbacks
List(new PostTyper), // Additional checks and cleanups after type checking
List(new RefChecks, // Various checks mostly related to abstract members and overriding
Copy link
Contributor

Choose a reason for hiding this comment

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

Add a comment here for why it was moved up?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

@felixmulder Thanks for looking at it. I tend to agree moving RefChecks before Pickler is a huge change we should try our best to avoid. Let's wait for some better fix that deprecate this one.

new CheckStatic), // Check restrictions that apply to @static members
List(new sbt.ExtractAPI), // Sends a representation of the API of classes to sbt via callbacks
List(new Pickler), // Generate TASTY info
List(new FirstTransform, // Some transformations to put trees into a canonical form
new CheckReentrant), // Internal use only: Check that compiled program has no data races involving global vars
List(new RefChecks, // Various checks mostly related to abstract members and overriding
new CheckStatic, // Check restrictions that apply to @static members
new ElimRepeated, // Rewrite vararg parameters and arguments
List(new ElimRepeated, // Rewrite vararg parameters and arguments
new NormalizeFlags, // Rewrite some definition flags
new ExtensionMethods, // Expand methods of value classes with extension methods
new ExpandSAMs, // Expand single abstract method closures to anonymous classes
Expand Down
14 changes: 13 additions & 1 deletion compiler/src/dotty/tools/dotc/typer/RefChecks.scala
Original file line number Diff line number Diff line change
Expand Up @@ -804,7 +804,19 @@ class RefChecks extends MiniPhase { thisTransformer =>
checkOverloadedRestrictions(cls)
checkParents(cls)
checkCompanionNameClashes(cls)
checkAllOverrides(cls)

def ownerPossibleProblematic(cls: Symbol) = {
!cls.owner.is(Flags.PackageClass) && cls.owner.isClass &&
cls.owner.info.baseClasses.exists(_.info.member(cls.name).exists)
}

// If owner is possibly problematic, check owner first.
// If there are overriding errors with owner, stop checking current to avoid cyclic reference.
// See neg/i1750.scala.
val errors = ctx.reporter.errorCount
if (ownerPossibleProblematic(cls)) checkAllOverrides(cls.owner)
if (ctx.reporter.errorCount == errors) checkAllOverrides(cls)

tree
} catch {
case ex: MergeError =>
Expand Down
12 changes: 12 additions & 0 deletions tests/neg/i1750.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
trait Lang1 {
trait Exp
trait Visitor { def f(left: Exp): Unit }
class Eval1 extends Visitor { self =>
def f(left: Exp) = ()
}
}

trait Lang2 extends Lang1 {
class Visitor extends Eval1 { Visitor => // error: overidding class definitions
}
}