aboutsummaryrefslogtreecommitdiff
path: root/src/dotty/tools/dotc/ast
diff options
context:
space:
mode:
authorodersky <odersky@gmail.com>2016-11-16 19:09:33 +0100
committerGitHub <noreply@github.com>2016-11-16 19:09:33 +0100
commit0397af7b3f014b2bbb0655b7162897f7a942f81d (patch)
tree6db8c73c77026131628d10c65f0cf5201e762e39 /src/dotty/tools/dotc/ast
parentadb37eee8974be841ff5eef2655c23394c05badb (diff)
parentfb59174be6193d7cb05bea6d375e34ec1cd52f46 (diff)
downloaddotty-0397af7b3f014b2bbb0655b7162897f7a942f81d.tar.gz
dotty-0397af7b3f014b2bbb0655b7162897f7a942f81d.tar.bz2
dotty-0397af7b3f014b2bbb0655b7162897f7a942f81d.zip
Merge pull request #1717 from dotty-staging/fix-#1688
Don't allow redefinition of core classes
Diffstat (limited to 'src/dotty/tools/dotc/ast')
-rw-r--r--src/dotty/tools/dotc/ast/Desugar.scala32
1 files changed, 24 insertions, 8 deletions
diff --git a/src/dotty/tools/dotc/ast/Desugar.scala b/src/dotty/tools/dotc/ast/Desugar.scala
index 349fbfb2c..d568e3d31 100644
--- a/src/dotty/tools/dotc/ast/Desugar.scala
+++ b/src/dotty/tools/dotc/ast/Desugar.scala
@@ -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)
@@ -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
@@ -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
@@ -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)
@@ -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)
@@ -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]]