Skip to content

Commit 3c7ccd5

Browse files
committed
fix namer
1. distinguish decl conflict and override error 2. always check a method's body even if its type signature is wrong 3. when resolving formal params, continue resolving its type and try our best to generate a correct and full function signature
1 parent eacc811 commit 3c7ccd5

File tree

1 file changed

+22
-15
lines changed

1 file changed

+22
-15
lines changed

src/main/scala/decaf/frontend/typecheck/Namer.scala

Lines changed: 22 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -225,7 +225,9 @@ class Namer(implicit config: Config) extends Phase[Tree, Typed.Tree]("namer", co
225225
*/
226226
def resolveField(field: Field)(implicit ctx: ScopeContext): Option[Typed.Field] = {
227227
val resolved = ctx.findConflict(field.name) match {
228-
case Some(earlier) =>
228+
case Some(earlier) if earlier.domain == ctx.currentScope => // always conflict
229+
issue(new DeclConflictError(field.name, earlier.pos, field.pos)); None
230+
case Some(earlier) => // maybe override?
229231
(earlier, field) match {
230232
case (_: MemberVarSymbol, _: VarSymbol) =>
231233
issue(new OverridingVarError(field.name, field.pos))
@@ -270,19 +272,16 @@ class Namer(implicit config: Config) extends Phase[Tree, Typed.Tree]("namer", co
270272
}
271273
case m @ MethodDef(mod, id, returnType, params, body) =>
272274
val rt = typeTypeLit(returnType)
273-
rt.typ match {
274-
case NoType => None
275-
case retType =>
276-
val formalScope = new FormalScope
277-
val formalCtx: ScopeContext = ctx.open(formalScope)
278-
if (!m.isStatic) formalCtx.declare(LocalVarSymbol.thisVar(ctx.currentClass.typ, id.pos))
279-
val typedParams = params.flatMap { resolveLocalVarDef(_)(formalCtx, true) }
280-
val funType = FunType(typedParams.map(_.typeLit.typ), retType)
281-
val symbol = new MethodSymbol(m, funType, formalScope, ctx.currentClass)
282-
ctx.declare(symbol)
283-
val block = resolveBlock(body)(formalCtx)
284-
Some(Typed.MethodDef(mod, id, rt, typedParams, block)(symbol))
285-
}
275+
val retType = rt.typ
276+
val formalScope = new FormalScope
277+
val formalCtx: ScopeContext = ctx.open(formalScope)
278+
if (!m.isStatic) formalCtx.declare(LocalVarSymbol.thisVar(ctx.currentClass.typ, id.pos))
279+
val typedParams = params.flatMap { resolveLocalVarDef(_)(formalCtx, true) }
280+
val funType = FunType(typedParams.map(_.typeLit.typ), retType)
281+
val symbol = new MethodSymbol(m, funType, formalScope, ctx.currentClass)
282+
ctx.declare(symbol)
283+
val block = resolveBlock(body)(formalCtx)
284+
Some(Typed.MethodDef(mod, id, rt, typedParams, block)(symbol))
286285
}
287286
}
288287
resolved.map(_.setPos(field.pos))
@@ -342,7 +341,15 @@ class Namer(implicit config: Config) extends Phase[Tree, Typed.Tree]("namer", co
342341
ctx.findConflict(v.name) match {
343342
case Some(earlier) =>
344343
issue(new DeclConflictError(v.name, earlier.pos, v.pos))
345-
None
344+
// NOTE: when type check a method, even though this parameter is conflicting, we still need to know what is the
345+
// type. Suppose this type is ok, we can still construct the full method type signature, to the user's
346+
// expectation.
347+
if (isParam) {
348+
val typedTypeLit = typeTypeLit(v.typeLit)
349+
Some(Typed.LocalVarDef(typedTypeLit, v.id, v.init, v.assignPos)(null))
350+
} else {
351+
None
352+
}
346353
case None =>
347354
val typedTypeLit = typeTypeLit(v.typeLit)
348355
typedTypeLit.typ match {

0 commit comments

Comments
 (0)