Skip to content

Fix #1703 #1718

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 3 commits into from
Nov 17, 2016
Merged
Show file tree
Hide file tree
Changes from 2 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
32 changes: 24 additions & 8 deletions src/dotty/tools/dotc/ast/Desugar.scala
Original file line number Diff line number Diff line change
Expand Up @@ -250,7 +250,8 @@ object desugar {

/** The expansion of a class definition. See inline comments for what is involved */
def classDef(cdef: TypeDef)(implicit ctx: Context): Tree = {
val TypeDef(name, impl @ Template(constr0, parents, self, _)) = cdef
val className = checkNotReservedName(cdef).asTypeName
val impl @ Template(constr0, parents, self, _) = cdef.rhs
val mods = cdef.mods
val companionMods = mods.withFlags((mods.flags & AccessFlags).toCommonFlags)

Expand Down Expand Up @@ -384,7 +385,7 @@ object desugar {
def companionDefs(parentTpt: Tree, defs: List[Tree]) =
moduleDef(
ModuleDef(
name.toTermName, Template(emptyConstructor, parentTpt :: Nil, EmptyValDef, defs))
className.toTermName, Template(emptyConstructor, parentTpt :: Nil, EmptyValDef, defs))
.withMods(companionMods | Synthetic))
.withPos(cdef.pos).toList

Expand Down Expand Up @@ -443,7 +444,7 @@ object desugar {
else
// implicit wrapper is typechecked in same scope as constructor, so
// we can reuse the constructor parameters; no derived params are needed.
DefDef(name.toTermName, constrTparams, constrVparamss, classTypeRef, creatorExpr)
DefDef(className.toTermName, constrTparams, constrVparamss, classTypeRef, creatorExpr)
.withMods(companionMods | Synthetic | Implicit)
.withPos(cdef.pos) :: Nil

Expand All @@ -460,6 +461,7 @@ object desugar {
val caseAccessor = if (isCaseClass) CaseAccessor else EmptyFlags
val vparamAccessors = derivedVparamss.flatten.map(_.withMods(originalVparams.next.mods | caseAccessor))
cpy.TypeDef(cdef)(
name = className,
rhs = cpy.Template(impl)(constr, parents1, self1,
tparamAccessors ::: vparamAccessors ::: normalizedBody ::: caseClassMeths),
tparams = Nil)
Expand All @@ -485,20 +487,21 @@ object desugar {
* <module> final class name$ extends parents { self: name.type => body }
*/
def moduleDef(mdef: ModuleDef)(implicit ctx: Context): Tree = {
val ModuleDef(name, tmpl) = mdef
val moduleName = checkNotReservedName(mdef).asTermName
val tmpl = mdef.impl
val mods = mdef.mods
if (mods is Package)
PackageDef(Ident(name), cpy.ModuleDef(mdef)(nme.PACKAGE, tmpl).withMods(mods &~ Package) :: Nil)
PackageDef(Ident(moduleName), cpy.ModuleDef(mdef)(nme.PACKAGE, tmpl).withMods(mods &~ Package) :: Nil)
else {
val clsName = name.moduleClassName
val clsName = moduleName.moduleClassName
val clsRef = Ident(clsName)
val modul = ValDef(name, clsRef, New(clsRef, Nil))
val modul = ValDef(moduleName, clsRef, New(clsRef, Nil))
.withMods(mods | ModuleCreationFlags | mods.flags & AccessFlags)
.withPos(mdef.pos)
val ValDef(selfName, selfTpt, _) = tmpl.self
val selfMods = tmpl.self.mods
if (!selfTpt.isEmpty) ctx.error(ObjectMayNotHaveSelfType(mdef), tmpl.self.pos)
val clsSelf = ValDef(selfName, SingletonTypeTree(Ident(name)), tmpl.self.rhs)
val clsSelf = ValDef(selfName, SingletonTypeTree(Ident(moduleName)), tmpl.self.rhs)
.withMods(selfMods)
.withPos(tmpl.self.pos orElse tmpl.pos.startPos)
val clsTmpl = cpy.Template(tmpl)(self = clsSelf, body = tmpl.body)
Expand All @@ -508,6 +511,19 @@ object desugar {
}
}

/** The name of `mdef`, after checking that it does not redefine a Scala core class.
* If it does redefine, issue an error and return a mangled name instead of the original one.
*/
def checkNotReservedName(mdef: MemberDef)(implicit ctx: Context): Name = {
val name = mdef.name
if (ctx.owner == defn.ScalaPackageClass && defn.reservedScalaClassNames.contains(name.toTypeName)) {
def kind = if (name.isTypeName) "class" else "object"
ctx.error(em"illegal redefinition of standard $kind $name", mdef.pos)
name.errorName
}
else name
}

/** val p1, ..., pN: T = E
* ==>
* makePatDef[[val p1: T1 = E]]; ...; makePatDef[[val pN: TN = E]]
Expand Down
20 changes: 12 additions & 8 deletions src/dotty/tools/dotc/core/Definitions.scala
Original file line number Diff line number Diff line change
Expand Up @@ -633,9 +633,9 @@ class Definitions {
name.startsWith(prefix) && name.drop(prefix.length).forall(_.isDigit)
}

def isBottomClass(cls: Symbol) =
def isBottomClass(cls: Symbol) =
cls == NothingClass || cls == NullClass
def isBottomType(tp: Type) =
def isBottomType(tp: Type) =
tp.derivesFrom(NothingClass) || tp.derivesFrom(NullClass)

def isFunctionClass(cls: Symbol) = isVarArityClass(cls, tpnme.Function)
Expand Down Expand Up @@ -761,7 +761,7 @@ class Definitions {
// ----- Initialization ---------------------------------------------------

/** Lists core classes that don't have underlying bytecode, but are synthesized on-the-fly in every reflection universe */
lazy val syntheticCoreClasses = List(
lazy val syntheticScalaClasses = List(
AnyClass,
AnyRefAlias,
RepeatedParamClass,
Expand All @@ -770,12 +770,16 @@ class Definitions {
NullClass,
NothingClass,
SingletonClass,
EqualsPatternClass,
EqualsPatternClass)

lazy val syntheticCoreClasses = syntheticScalaClasses ++ List(
EmptyPackageVal,
OpsPackageClass)

/** Lists core methods that don't have underlying bytecode, but are synthesized on-the-fly in every reflection universe */
lazy val syntheticCoreMethods = AnyMethods ++ ObjectMethods ++ List(String_+, throwMethod)
/** Lists core methods that don't have underlying bytecode, but are synthesized on-the-fly in every reflection universe */
lazy val syntheticCoreMethods = AnyMethods ++ ObjectMethods ++ List(String_+, throwMethod)

lazy val reservedScalaClassNames: Set[Name] = syntheticScalaClasses.map(_.name).toSet

private[this] var _isInitialized = false
private def isInitialized = _isInitialized
Expand All @@ -785,8 +789,8 @@ class Definitions {
if (!_isInitialized) {
// force initialization of every symbol that is synthesized or hijacked by the compiler
val forced = syntheticCoreClasses ++ syntheticCoreMethods ++ ScalaValueClasses()
// Enter all symbols from the scalaShadowing package in the scala package

// Enter all symbols from the scalaShadowing package in the scala package
for (m <- ScalaShadowingPackageClass.info.decls)
ScalaPackageClass.enter(m)

Expand Down
2 changes: 2 additions & 0 deletions src/dotty/tools/dotc/core/NameOps.scala
Original file line number Diff line number Diff line change
Expand Up @@ -186,6 +186,8 @@ object NameOps {

def implClassName: N = likeTyped(name ++ tpnme.IMPL_CLASS_SUFFIX)

def errorName: N = likeTyped(name ++ nme.ERROR)

def freshened(implicit ctx: Context): N =
likeTyped(
if (name.isModuleClassName) name.stripModuleClassSuffix.freshened.moduleClassName
Expand Down
3 changes: 2 additions & 1 deletion src/dotty/tools/dotc/parsing/Parsers.scala
Original file line number Diff line number Diff line change
Expand Up @@ -2149,7 +2149,8 @@ object Parsers {
self = makeSelfDef(nme.WILDCARD, tpt).withPos(first.pos)
case _ =>
val ValDef(name, tpt, _) = convertToParam(first, expected = "self type clause")
self = makeSelfDef(name, tpt).withPos(first.pos)
if (name != nme.ERROR)
self = makeSelfDef(name, tpt).withPos(first.pos)
}
in.nextToken()
} else {
Expand Down
6 changes: 6 additions & 0 deletions tests/neg/i1688.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
package scala
sealed trait Null // error

object Null // error

class AnyVal // error
5 changes: 5 additions & 0 deletions tests/pos/i1703.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
class DuplicateClassName { () => {
{ () =>
}
}
}
Copy link
Contributor

Choose a reason for hiding this comment

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

LGTM, except the the test tests/pos/i1703.scala should be in neg directory.