diff options
author | Martin Odersky <odersky@gmail.com> | 2006-06-27 15:27:12 +0000 |
---|---|---|
committer | Martin Odersky <odersky@gmail.com> | 2006-06-27 15:27:12 +0000 |
commit | 972ecebb2794655b543fde5c8a4f75614729ce5c (patch) | |
tree | 185a9cdad776cd2bda468f79797ff362fa22e006 | |
parent | 5a17c91819ebeca83dcdfcfb1dc49e1bc7322a87 (diff) | |
download | scala-972ecebb2794655b543fde5c8a4f75614729ce5c.tar.gz scala-972ecebb2794655b543fde5c8a4f75614729ce5c.tar.bz2 scala-972ecebb2794655b543fde5c8a4f75614729ce5c.zip |
Fixed bugs 633, 637, 639, 640
-rw-r--r-- | src/compiler/scala/tools/nsc/CompileSocket.scala | 8 | ||||
-rw-r--r-- | src/compiler/scala/tools/nsc/ast/parser/Parsers.scala | 7 | ||||
-rw-r--r-- | src/compiler/scala/tools/nsc/symtab/SymbolLoaders.scala | 7 | ||||
-rw-r--r-- | src/compiler/scala/tools/nsc/symtab/Types.scala | 14 | ||||
-rw-r--r-- | src/compiler/scala/tools/nsc/typechecker/Contexts.scala | 17 | ||||
-rw-r--r-- | src/compiler/scala/tools/nsc/typechecker/Namers.scala | 136 | ||||
-rw-r--r-- | src/compiler/scala/tools/nsc/typechecker/Typers.scala | 286 | ||||
-rw-r--r-- | test/files/neg/bug563.check | 7 | ||||
-rw-r--r-- | test/files/neg/bug633.check | 4 | ||||
-rw-r--r-- | test/files/neg/bug633.scala | 8 | ||||
-rw-r--r-- | test/files/neg/bug639.check | 9 | ||||
-rw-r--r-- | test/files/neg/bug639.scala | 3 | ||||
-rw-r--r-- | test/files/pos/bug640.scala | 2 | ||||
-rw-r--r-- | test/files/run/bigints.check | 5 | ||||
-rwxr-xr-x | test/files/run/bigints.scala | 14 | ||||
-rw-r--r-- | test/files/run/bug629.check | 1 | ||||
-rw-r--r-- | test/files/run/bug629.scala | 13 |
17 files changed, 319 insertions, 222 deletions
diff --git a/src/compiler/scala/tools/nsc/CompileSocket.scala b/src/compiler/scala/tools/nsc/CompileSocket.scala index 32683d9029..5549cf18b7 100644 --- a/src/compiler/scala/tools/nsc/CompileSocket.scala +++ b/src/compiler/scala/tools/nsc/CompileSocket.scala @@ -99,6 +99,7 @@ object CompileSocket { def deletePort(port: int): unit = portFile(port).delete() def getOrCreateSocket(vmArgs: String): Socket = { + val nAttempts = 9; def getsock(attempts: int): Socket = if (attempts == 0) { System.err.println("unable to establish connection to server; exiting"); @@ -114,10 +115,13 @@ object CompileSocket { System.err.println("...connection attempt to server at port "+port+" failed; re-trying...") if (attempts % 2 == 0) portFile(port).delete() Thread.sleep(100) - getsock(attempts - 1) + val result = getsock(attempts - 1) + if (attempts == nAttempts) + System.err.println("... connection established at port "+port) + result } } - getsock(9) + getsock(nAttempts) } def getSocket(serverAdr: String): Socket = { diff --git a/src/compiler/scala/tools/nsc/ast/parser/Parsers.scala b/src/compiler/scala/tools/nsc/ast/parser/Parsers.scala index ce885459a9..bc0b7a035e 100644 --- a/src/compiler/scala/tools/nsc/ast/parser/Parsers.scala +++ b/src/compiler/scala/tools/nsc/ast/parser/Parsers.scala @@ -43,9 +43,10 @@ import Tokens._; trait Parsers requires SyntaxAnalyzer { import global._; + private val glob: global.type = global; import posAssigner.atPos; - class Parser(unit: CompilationUnit) { + class Parser(unit: global.CompilationUnit) { val in = new Scanner(unit); @@ -1316,7 +1317,7 @@ trait Parsers requires SyntaxAnalyzer { param } val params = new ListBuffer[AbsTypeDef]; - newLineOptWhenFollowedBy(LBRACKET); + //newLineOptWhenFollowedBy(LBRACKET); if (in.token == LBRACKET) { in.nextToken(); params += typeParam(); @@ -1825,7 +1826,7 @@ trait Parsers requires SyntaxAnalyzer { nvps.toList } else List() val constr = atPos(pos) { New(t, List(args)) } - atPos(pos) { Attribute(constr, nameValuePairs) } + atPos(pos) { glob.Attribute(constr, nameValuePairs) } } def mixinAttribute(attrs: List[Tree]) = { diff --git a/src/compiler/scala/tools/nsc/symtab/SymbolLoaders.scala b/src/compiler/scala/tools/nsc/symtab/SymbolLoaders.scala index de8af15695..5611af7b1e 100644 --- a/src/compiler/scala/tools/nsc/symtab/SymbolLoaders.scala +++ b/src/compiler/scala/tools/nsc/symtab/SymbolLoaders.scala @@ -49,8 +49,9 @@ abstract class SymbolLoaders { phase = currentphase; def source = kindString + " " + sourceString; informTime("loaded " + source, start); - if (root.rawInfo != this) { - ok = true; + if (root.rawInfo == this && root.linkedSym.rawInfo == this) + throw new TypeError(source + " does not define " + root) + ok = true; /* val sourceFile0 = if (sourceFile == null) (root match { case clazz: ClassSymbol => clazz.sourceFile; @@ -59,7 +60,6 @@ abstract class SymbolLoaders { setSource(root.linkedModule.moduleClass, sourceFile0); setSource(root.linkedClass, sourceFile0); */ - } else throw new TypeError(source + " does not define " + root) } catch { case ex: IOException => ok = false; @@ -72,6 +72,7 @@ abstract class SymbolLoaders { initRoot(root); if (!root.isPackageClass) initRoot(root.linkedSym); } + override def load(root: Symbol): unit = complete(root); private def initRoot(root: Symbol): unit = { diff --git a/src/compiler/scala/tools/nsc/symtab/Types.scala b/src/compiler/scala/tools/nsc/symtab/Types.scala index e2f8e23b3f..117f4d73cf 100644 --- a/src/compiler/scala/tools/nsc/symtab/Types.scala +++ b/src/compiler/scala/tools/nsc/symtab/Types.scala @@ -890,8 +890,14 @@ trait Types requires SymbolTable { } val str = (pre.prefixString + sym.nameString + (if (args.isEmpty) "" else args.mkString("[", ",", "]"))) - if (sym.isPackageClass) "package "+str - else if (sym.isModuleClass) "object "+str + if (sym.isPackageClass) + "package "+str + else if (sym.isModuleClass) + "object "+str + else if (sym.isAnonymousClass && sym.isInitialized) + sym.info.parents.mkString("", " with ", "{ ... }") + else if (sym.isRefinementClass && sym.isInitialized) + sym.info.toString() else str } @@ -2178,7 +2184,9 @@ trait Types requires SymbolTable { // Errors and Diagnostics --------------------------------------------------------- /** An exception signalling a type error */ - class TypeError(val msg: String) extends java.lang.Error(msg); + class TypeError(val pos: int, val msg: String) extends java.lang.Error(msg) { + def this(msg: String) = this(Position.NOPOS, msg) + } class NoCommonType(tps: List[Type]) extends java.lang.Error( "lub/glb of incompatible types: " + tps.mkString("", " and ", "")); diff --git a/src/compiler/scala/tools/nsc/typechecker/Contexts.scala b/src/compiler/scala/tools/nsc/typechecker/Contexts.scala index f85c5040e4..82c12f7e4b 100644 --- a/src/compiler/scala/tools/nsc/typechecker/Contexts.scala +++ b/src/compiler/scala/tools/nsc/typechecker/Contexts.scala @@ -72,7 +72,7 @@ trait Contexts requires Analyzer { // template or package definition var enclMethod: Context = _; // The next outer context whose tree is a method var variance: int = _; // Variance relative to enclosing class. - private var _undetparams: List[Symbol] = List(); // Undetermined type parameters + private var _undetparams: List[Symbol] = List(); // Undetermined type parameters, not inherited to child contexts var depth: int = 0 var imports: List[ImportInfo] = List() @@ -83,6 +83,7 @@ trait Contexts requires Analyzer { var reportGeneralErrors = false var implicitsEnabled = false var checking = false + var retyping = false var savedTypeBounds: List[Pair[Symbol, Type]] = List() @@ -121,6 +122,7 @@ trait Contexts requires Analyzer { c.reportGeneralErrors = this.reportGeneralErrors c.implicitsEnabled = this.implicitsEnabled c.checking = this.checking + c.retyping = this.retyping c.outer = this c } @@ -148,10 +150,15 @@ trait Contexts requires Analyzer { def make(tree: Tree): Context = make(tree, owner) - def makeImplicit(reportAmbiguousErrors: boolean) = { + def makeSilent(reportAmbiguousErrors: boolean): Context = { val c = make(tree) - c.reportAmbiguousErrors = reportAmbiguousErrors c.reportGeneralErrors = false + c.reportAmbiguousErrors = reportAmbiguousErrors + c + } + + def makeImplicit(reportAmbiguousErrors: boolean) = { + val c = makeSilent(reportAmbiguousErrors) c.implicitsEnabled = false c } @@ -191,7 +198,7 @@ trait Contexts requires Analyzer { if (reportGeneralErrors) unit.error(pos, if (checking) "**** ERROR DURING INTERNAL CHECKING ****\n" + msg else msg) else - throw new TypeError(msg) + throw new TypeError(pos, msg) def ambiguousError(pos: int, pre: Type, sym1: Symbol, sym2: Symbol, rest: String): unit = { val msg = @@ -202,7 +209,7 @@ trait Contexts requires Analyzer { if (reportAmbiguousErrors) { if (!pre.isErroneous && !sym1.isErroneous && !sym2.isErroneous) unit.error(pos, msg) - } else throw new TypeError(msg) + } else throw new TypeError(pos, msg) } def outerContext(clazz: Symbol): Context = { diff --git a/src/compiler/scala/tools/nsc/typechecker/Namers.scala b/src/compiler/scala/tools/nsc/typechecker/Namers.scala index 0dab8927f5..f9e886ab8c 100644 --- a/src/compiler/scala/tools/nsc/typechecker/Namers.scala +++ b/src/compiler/scala/tools/nsc/typechecker/Namers.scala @@ -233,7 +233,7 @@ trait Namers requires Analyzer { tree.pos, mods.flags & AccessFlags | METHOD | CASE, name.toTermName) .setInfo(innerNamer.caseFactoryCompleter(tree)); setPrivateWithin(tree.symbol, mods); - } + } tree.symbol = enterClassSymbol(tree.pos, mods.flags, name); setPrivateWithin(tree.symbol, mods); finishWith(tparams); @@ -459,73 +459,75 @@ trait Namers requires Analyzer { private def aliasTypeSig(tpsym: Symbol, tparams: List[AbsTypeDef], rhs: Tree): Type = makePolyType(typer.reenterTypeParams(tparams), typer.typedType(rhs).tpe); - private def typeSig(tree: Tree): Type = deSkolemize { - try { - val sym: Symbol = tree.symbol; - tree match { - case ClassDef(_, _, tparams, tpt, impl) => - new Namer(context.makeNewScope(tree, sym)).classSig(tparams, tpt, impl) - - case ModuleDef(_, _, impl) => - val clazz = sym.moduleClass; - clazz.setInfo(new Namer(context.make(tree, clazz)).templateSig(impl)); - //clazz.typeOfThis = singleType(sym.owner.thisType, sym); - clazz.tpe; - - case DefDef(_, _, tparams, vparamss, tpt, rhs) => - val result = - new Namer(context.makeNewScope(tree, sym)).methodSig(tparams, vparamss, tpt, rhs); - checkContractive(sym, result) - - case ValDef(_, _, tpt, rhs) => - if (tpt.isEmpty) { - if (rhs.isEmpty) { - context.error(tpt.pos, "missing parameter type"); - ErrorType + private def typeSig(tree: Tree): Type = { + val result = + try { + val sym: Symbol = tree.symbol; + tree match { + case ClassDef(_, _, tparams, tpt, impl) => + new Namer(context.makeNewScope(tree, sym)).classSig(tparams, tpt, impl) + + case ModuleDef(_, _, impl) => + val clazz = sym.moduleClass; + clazz.setInfo(new Namer(context.make(tree, clazz)).templateSig(impl)); + //clazz.typeOfThis = singleType(sym.owner.thisType, sym); + clazz.tpe; + + case DefDef(_, _, tparams, vparamss, tpt, rhs) => + val result = + new Namer(context.makeNewScope(tree, sym)).methodSig(tparams, vparamss, tpt, rhs); + checkContractive(sym, result) + + case ValDef(_, _, tpt, rhs) => + if (tpt.isEmpty) { + if (rhs.isEmpty) { + context.error(tpt.pos, "missing parameter type"); + ErrorType + } else { + tpt.tpe = deconstIfNotFinal(sym, newTyper(context.make(tree, sym)).computeType(rhs)); + tpt.tpe + } } else { - tpt.tpe = deconstIfNotFinal(sym, newTyper(context.make(tree, sym)).computeType(rhs)); - tpt.tpe + val typer1 = + if (sym.hasFlag(PARAM) && sym.owner.isConstructor && !phase.erasedTypes) + newTyper(context.makeConstructorContext) + else typer; + typer1.typedType(tpt).tpe + } + + case AliasTypeDef(_, _, tparams, rhs) => + new Namer(context.makeNewScope(tree, sym)).aliasTypeSig(sym, tparams, rhs) + + case AbsTypeDef(_, _, lo, hi) => + //System.out.println("bounds of " + sym + ":" + sym.tpe + " = " + typer.typedType(hi).tpe); + TypeBounds(typer.typedType(lo).tpe, typer.typedType(hi).tpe); + + case Import(expr, selectors) => + val expr1 = typer.typedQualifier(expr); + val base = expr1.tpe; + typer.checkStable(expr1); + def checkSelectors(selectors: List[Pair[Name, Name]]): unit = selectors match { + case Pair(from, to) :: rest => + if (from != nme.WILDCARD && base != ErrorType && + base.member(from) == NoSymbol && base.member(from.toTypeName) == NoSymbol) + context.error(tree.pos, from.decode + " is not a member of " + expr); + if (from != nme.WILDCARD && (rest.exists (sel => sel._1 == from))) + context.error(tree.pos, from.decode + " is renamed twice"); + if (to != null && to != nme.WILDCARD && (rest exists (sel => sel._2 == to))) + context.error(tree.pos, to.decode + " appears twice as a target of a renaming"); + checkSelectors(rest) + case Nil => } - } else { - val typer1 = - if (sym.hasFlag(PARAM) && sym.owner.isConstructor && !phase.erasedTypes) - newTyper(context.makeConstructorContext) - else typer; - typer1.typedType(tpt).tpe - } - - case AliasTypeDef(_, _, tparams, rhs) => - new Namer(context.makeNewScope(tree, sym)).aliasTypeSig(sym, tparams, rhs) - - case AbsTypeDef(_, _, lo, hi) => - //System.out.println("bounds of " + sym + ":" + sym.tpe + " = " + typer.typedType(hi).tpe); - TypeBounds(typer.typedType(lo).tpe, typer.typedType(hi).tpe); - - case Import(expr, selectors) => - val expr1 = typer.typedQualifier(expr); - val base = expr1.tpe; - typer.checkStable(expr1); - def checkSelectors(selectors: List[Pair[Name, Name]]): unit = selectors match { - case Pair(from, to) :: rest => - if (from != nme.WILDCARD && base != ErrorType && - base.member(from) == NoSymbol && base.member(from.toTypeName) == NoSymbol) - context.error(tree.pos, from.decode + " is not a member of " + expr); - if (from != nme.WILDCARD && (rest.exists (sel => sel._1 == from))) - context.error(tree.pos, from.decode + " is renamed twice"); - if (to != null && to != nme.WILDCARD && (rest exists (sel => sel._2 == to))) - context.error(tree.pos, to.decode + " appears twice as a target of a renaming"); - checkSelectors(rest) - case Nil => - } - checkSelectors(selectors); - ImportType(expr1) - } - } catch { - case ex: TypeError => - //System.out.println("caught " + ex + " in typeSig");//DEBUG - typer.reportTypeError(tree.pos, ex); - ErrorType - } + checkSelectors(selectors); + ImportType(expr1) + } + } catch { + case ex: TypeError => + //System.out.println("caught " + ex + " in typeSig");//DEBUG + typer.reportTypeError(tree.pos, ex); + ErrorType + } + deSkolemize(result) } /** Check that symbol's definition is well-formed. This means: @@ -546,7 +548,7 @@ trait Namers requires Analyzer { Flags.flagsToString(flag1) + " and " + Flags.flagsToString(flag2)); if (sym.hasFlag(IMPLICIT) && !sym.isTerm) context.error(sym.pos, "`implicit' modifier can be used only for values, variables and methods"); - if (sym.hasFlag(IMPLICIT) && sym.owner.isPackage) + if (sym.hasFlag(IMPLICIT) && sym.owner.isPackageClass) context.error(sym.pos, "`implicit' modifier cannot be used for top-level objects"); if (sym.hasFlag(ABSTRACT) && !sym.isClass) context.error(sym.pos, "`abstract' modifier can be used only for classes; " + diff --git a/src/compiler/scala/tools/nsc/typechecker/Typers.scala b/src/compiler/scala/tools/nsc/typechecker/Typers.scala index 9d488261b4..bce9133222 100644 --- a/src/compiler/scala/tools/nsc/typechecker/Typers.scala +++ b/src/compiler/scala/tools/nsc/typechecker/Typers.scala @@ -58,7 +58,6 @@ trait Typers requires Analyzer { private def inferView(pos: int, from: Type, to: Type, reportAmbiguous: boolean): Tree = { if (settings.debug.value) log("infer view from "+from+" to "+to);//debug - assert(!(from <:< to))//debug if (phase.erasedTypes) EmptyTree else from match { case MethodType(_, _) => EmptyTree @@ -124,11 +123,14 @@ trait Typers requires Analyzer { private val stickyModes: int = EXPRmode | PATTERNmode | TYPEmode | CONSTmode + private def funMode(mode: int) = mode & stickyModes | FUNmode | POLYmode + /** Report a type error. * @param pos The position where to report the error * @param ex The exception that caused the error */ - def reportTypeError(pos: int, ex: TypeError): unit = { + def reportTypeError(pos0: int, ex: TypeError): unit = { if (settings.debug.value) ex.printStackTrace() + val pos = if (ex.pos == Position.NOPOS) pos0 else ex.pos ex match { case CyclicReference(sym, info: TypeCompleter) => context.unit.error( @@ -1011,9 +1013,98 @@ trait Typers requires Analyzer { result } - protected def typed1(tree: Tree, mode: int, pt: Type): Tree = { + def typedArg(arg: Tree, mode: int, pt: Type): Tree = { + val argTyper = if ((mode & SCCmode) != 0) newTyper(context.makeConstructorContext) + else this + argTyper.typed(arg, mode & (stickyModes | POLYmode), pt) + } + + def typedArgs(args: List[Tree], mode: int) = + List.mapConserve(args)(arg => typedArg(arg, mode, WildcardType)) + + def typedApply(tree: Tree, fun0: Tree, args: List[Tree], mode: int, pt: Type): Tree = { + var fun = fun0; + if (fun.hasSymbol && (fun.symbol hasFlag OVERLOADED)) { + // preadapt symbol to number of arguments given + val argtypes = args map (arg => AllClass.tpe) + val pre = fun.symbol.tpe.prefix + val sym = fun.symbol filter (alt => + isApplicable(context.undetparams, pre.memberType(alt), argtypes, pt)) + if (sym != NoSymbol) + fun = adapt(fun setSymbol sym setType pre.memberType(sym), funMode(mode), WildcardType) + } + fun.tpe match { + case OverloadedType(pre, alts) => + val args1 = typedArgs(args, mode) + inferMethodAlternative(fun, context.undetparams, args1 map (.tpe.deconst), pt) + typedApply(tree, adapt(fun, funMode(mode), WildcardType), args1, mode, pt) + case MethodType(formals0, restpe) => + val formals = formalTypes(formals0, args.length) + if (formals.length != args.length) { + //System.out.println(""+formals.length+" "+args.length);//DEBUG + errorTree(tree, "wrong number of arguments for "+treeSymTypeMsg(fun)) + } else { + val tparams = context.undetparams + context.undetparams = List() + if (tparams.isEmpty) { + val args1 = List.map2(args, formals)((arg, formal) => + typedArg(arg, mode, formal)) + def ifPatternSkipFormals(tp: Type) = tp match { + case MethodType(_, rtp) if ((mode & PATTERNmode) != 0) => rtp + case _ => tp + } + if (fun.symbol == List_apply && args.isEmpty) { + gen.mkNil setType restpe + } + else if ((mode & CONSTmode) != 0 && fun.symbol.owner == PredefModule.tpe.symbol && fun.symbol.name == nme.Array) { + val elems = new Array[Constant](args1.length) + var i = 0; + for (val arg <- args1) arg match { + case Literal(value) => + elems(i) = value + i = i + 1 + case _ => errorTree(arg, "constant required") + } + val arrayConst = new ArrayConstant(elems, restpe) + Literal(arrayConst) setType ConstantType(arrayConst) + } + else + constfold(copy.Apply(tree, fun, args1).setType(ifPatternSkipFormals(restpe))) + } else { + assert((mode & PATTERNmode) == 0); // this case cannot arise for patterns + val lenientTargs = protoTypeArgs(tparams, formals, restpe, pt) + val strictTargs = List.map2(lenientTargs, tparams)((targ, tparam) => + if (targ == WildcardType) tparam.tpe else targ) + def typedArgToPoly(arg: Tree, formal: Type): Tree = { + val lenientPt = formal.subst(tparams, lenientTargs) + val arg1 = typedArg(arg, mode | POLYmode, lenientPt) + val argtparams = context.undetparams + context.undetparams = List() + if (!argtparams.isEmpty) { + val strictPt = formal.subst(tparams, strictTargs) + inferArgumentInstance(arg1, argtparams, strictPt, lenientPt) + } + arg1 + } + val args1 = List.map2(args, formals)(typedArgToPoly) + if (args1 exists (.tpe.isError)) setError(tree) + else { + if (settings.debug.value) log("infer method inst "+fun+", tparams = "+tparams+", args = "+args1.map(.tpe)+", pt = "+pt+", lobounds = "+tparams.map(.tpe.bounds.lo));//debug + val undetparams = inferMethodInstance(fun, tparams, args1, pt) + val result = typedApply(tree, fun, args1, mode, pt) + context.undetparams = undetparams + result + } + } + } + case ErrorType => + setError(tree) + case _ => + errorTree(tree, ""+fun+" does not take parameters") + } + } - def funmode = mode & stickyModes | FUNmode | POLYmode + protected def typed1(tree: Tree, mode: int, pt: Type): Tree = { def ptOrLub(tps: List[Type]) = if (isFullyDefined(pt)) pt else lub(tps) @@ -1040,121 +1131,61 @@ trait Typers requires Analyzer { errorTree(tree, treeSymTypeMsg(fun)+" does not take type parameters.") } - def typedArg(arg: Tree, pt: Type, polyMode: int): Tree = { - val argTyper = if ((mode & SCCmode) != 0) newTyper(context.makeConstructorContext) - else this - argTyper.typed(arg, mode & stickyModes | polyMode, pt) - } - - def typedArgs(args: List[Tree]) = - List.mapConserve(args)(arg => typedArg(arg, WildcardType, 0)) - - def typedApply(fun0: Tree, args: List[Tree]): Tree = { - var fun = fun0; - if (fun.hasSymbol && (fun.symbol hasFlag OVERLOADED)) { - // preadapt symbol to number of arguments given - val argtypes = args map (arg => AllClass.tpe) - val pre = fun.symbol.tpe.prefix - val sym = fun.symbol filter (alt => - isApplicable(context.undetparams, pre.memberType(alt), argtypes, pt)) - if (sym != NoSymbol) - fun = adapt(fun setSymbol sym setType pre.memberType(sym), funmode, WildcardType) - } - fun.tpe match { - case OverloadedType(pre, alts) => - val args1 = typedArgs(args) - inferMethodAlternative(fun, context.undetparams, args1 map (.tpe.deconst), pt) - typedApply(adapt(fun, funmode, WildcardType), args1) - case MethodType(formals0, restpe) => - val formals = formalTypes(formals0, args.length) - if (formals.length != args.length) { - //System.out.println(""+formals.length+" "+args.length);//DEBUG - errorTree(tree, "wrong number of arguments for "+treeSymTypeMsg(fun)) - } else { - val tparams = context.undetparams - context.undetparams = List() - if (tparams.isEmpty) { - val args1 = List.map2(args, formals)((arg, formal) => typedArg(arg, formal, 0)) - def ifPatternSkipFormals(tp: Type) = tp match { - case MethodType(_, rtp) if ((mode & PATTERNmode) != 0) => rtp - case _ => tp - } - if (fun.symbol == List_apply && args.isEmpty) { - gen.mkNil setType restpe - } - else if ((mode & CONSTmode) != 0 && fun.symbol.owner == PredefModule.tpe.symbol && fun.symbol.name == nme.Array) { - val elems = new Array[Constant](args1.length) - var i = 0; - for (val arg <- args1) arg match { - case Literal(value) => - elems(i) = value - i = i + 1 - case _ => errorTree(arg, "constant required") - } - val arrayConst = new ArrayConstant(elems, restpe) - Literal(arrayConst) setType ConstantType(arrayConst) - } - else - constfold(copy.Apply(tree, fun, args1).setType(ifPatternSkipFormals(restpe))) - } else { - assert((mode & PATTERNmode) == 0); // this case cannot arise for patterns - val lenientTargs = protoTypeArgs(tparams, formals, restpe, pt) - val strictTargs = List.map2(lenientTargs, tparams)((targ, tparam) => - if (targ == WildcardType) tparam.tpe else targ) - def typedArgToPoly(arg: Tree, formal: Type): Tree = { - val lenientPt = formal.subst(tparams, lenientTargs) - val arg1 = typedArg(arg, lenientPt, POLYmode) - val argtparams = context.undetparams - context.undetparams = List() - if (!argtparams.isEmpty) { - val strictPt = formal.subst(tparams, strictTargs) - inferArgumentInstance(arg1, argtparams, strictPt, lenientPt) - } - arg1 - } - val args1 = List.map2(args, formals)(typedArgToPoly) - if (args1 exists (.tpe.isError)) setError(tree) - else { - if (settings.debug.value) log("infer method inst "+fun+", tparams = "+tparams+", args = "+args1.map(.tpe)+", pt = "+pt+", lobounds = "+tparams.map(.tpe.bounds.lo));//debug - val undetparams = inferMethodInstance(fun, tparams, args1, pt) - val result = typedApply(fun, args1) - context.undetparams = undetparams - result - } - } - } - case ErrorType => - setError(tree) - case _ => - errorTree(tree, ""+fun+" does not take parameters") - } - } - def tryTypedArgs(args: List[Tree]) = { - val reportGeneralErrors = context.reportGeneralErrors - val reportAmbiguousErrors = context.reportAmbiguousErrors try { - context.reportGeneralErrors = false - context.reportAmbiguousErrors = false - typedArgs(args) + val c = context.makeSilent(false) + c.retyping = true + newTyper(c).typedArgs(args, mode) } catch { case ex: TypeError => null - } finally { - context.reportGeneralErrors = reportGeneralErrors - context.reportAmbiguousErrors = reportAmbiguousErrors } } /** Try to apply function to arguments; if it does not work try to insert an implicit * conversion */ + def tryTypedApply(fun: Tree, args: List[Tree]): Tree = try { + if (context.reportGeneralErrors) { + val context1 = context.makeSilent(context.reportAmbiguousErrors) + context1.undetparams = context.undetparams + val typer1 = newTyper(context1) + val result = typer1.typedApply(tree, fun, args, mode, pt) + context.undetparams = context1.undetparams + result + } else { + typedApply(tree, fun, args, mode, pt) + } + } catch { + case ex: CyclicReference => + throw ex + case ex: TypeError => + val Select(qual, name) = fun + val args1 = tryTypedArgs(args) + val qual1 = + if (args1 != null && !pt.isError) { + def templateArgType(arg: Tree) = + new BoundedWildcardType(TypeBounds(arg.tpe, AnyClass.tpe)) + adaptToMember(qual, name, MethodType(args1 map templateArgType, pt)) + } else qual + if (qual1 ne qual) { + val tree1 = Apply(Select(qual1, name) setPos fun.pos, args1) setPos tree.pos + typed1(tree1, mode | SNDTRYmode, pt) + } else { + reportTypeError(tree.pos, ex) + setError(tree) + } + } +/* + /** Try to apply function to arguments; if it does not work try to insert an implicit + * conversion + */ def tryTypedApply(fun: Tree, args: List[Tree]): Tree = { val reportGeneralErrors = context.reportGeneralErrors val undetparams = context.undetparams try { context.reportGeneralErrors = false - typedApply(fun, args) + typedApply(tree, fun, args, mode, pt) } catch { case ex: CyclicReference => throw ex @@ -1173,7 +1204,7 @@ trait Typers requires Analyzer { context.reportGeneralErrors = reportGeneralErrors } } - +*/ /** Attribute a selection where `tree' is `qual.name'. * `qual' is already attributed. */ @@ -1374,14 +1405,9 @@ trait Typers requires Analyzer { null } typed(constr, mode | CONSTmode, AttributeClass.tpe) match { - case t @ Apply(Select(New(tpt), nme.CONSTRUCTOR), args) => + case Apply(Select(New(tpt), nme.CONSTRUCTOR), args) => val constrArgs = args map getConstant - val attrScope = tpt.tpe.decls.filter(s => (s.isMethod && !s.isConstructor)) - val names = new collection.mutable.HashSet[Symbol] - names ++= attrScope.elements - if (args.length == 1) { - names.filter(sym => sym.name != nme.value) - } + val attrScope = tpt.tpe.decls; val nvPairs = elements map { case Assign(ntree @ Ident(name), rhs) => { val sym = attrScope.lookup(name); @@ -1389,23 +1415,12 @@ trait Typers requires Analyzer { error(ntree.pos, "unknown attribute element name: " + name) attrError = true; null - } else if (!names.contains(sym)) { - error(ntree.pos, "duplicate value for element " + name) - attrError = true; - null } else { - names -= sym Pair(sym, getConstant(typed(rhs, mode | CONSTmode, sym.tpe.resultType))) } } } - for (val name <- names) { - if (!name.attributes.contains(Triple(AnnotationDefaultAttr.tpe, List(), List()))) { - error(t.pos, "attribute " + tpt.tpe.symbol.fullNameString + " is missing element " + name.name) - attrError = true; - } - } if (!attrError) { val attrInfo = Triple(tpt.tpe, constrArgs, nvPairs) val attributed = @@ -1568,7 +1583,7 @@ trait Typers requires Analyzer { case TypeApply(fun, args) => val args1 = List.mapConserve(args)(typedType) // do args first in order to maintain conext.undetparams on the function side. - typedTypeApply(typed(fun, funmode | TAPPmode, WildcardType), args1) + typedTypeApply(typed(fun, funMode(mode) | TAPPmode, WildcardType), args1) case Apply(Block(stats, expr), args) => typed1(Block(stats, Apply(expr, args)), mode, pt) @@ -1580,7 +1595,7 @@ trait Typers requires Analyzer { typed1(tree, mode & ~PATTERNmode | EXPRmode, pt) } else { val funpt = if ((mode & PATTERNmode) != 0) pt else WildcardType - var fun1 = typed(fun, funmode, funpt) + var fun1 = typed(fun, funMode(mode), funpt) if (stableApplication) fun1 = stabilizeFun(fun1, mode, pt) // if function is overloaded, filter all alternatives that match // number of arguments and expected result type. @@ -1591,7 +1606,7 @@ trait Typers requires Analyzer { !fun1.tpe.isInstanceOf[ImplicitMethodType] && (mode & (EXPRmode | SNDTRYmode)) == EXPRmode) tryTypedApply(fun1, args) else { - typedApply(fun1, args) + typedApply(tree, fun1, args, mode, pt) } } @@ -1707,6 +1722,11 @@ trait Typers requires Analyzer { if (settings.debug.value) { assert(pt != null, tree);//debug } + if (context.retyping && + tree.tpe != null && (tree.tpe.isErroneous || !(tree.tpe <:< pt))) { + tree.tpe = null + if (tree.hasSymbol) tree.symbol = NoSymbol + } //System.out.println("typing "+tree+", "+context.undetparams);//DEBUG val tree1 = if (tree.tpe != null) tree else typed1(tree, mode, pt) //System.out.println("typed "+tree1+":"+tree1.tpe+", "+context.undetparams);//DEBUG @@ -1716,14 +1736,14 @@ trait Typers requires Analyzer { } catch { case ex: TypeError => //System.out.println("caught "+ex+" in typed");//DEBUG - reportTypeError(tree.pos, ex) - setError(tree) - case ex: Throwable => - if (settings.debug.value) - System.out.println("exception when typing "+tree+", pt = "+pt) - if (context != null && context.unit != null && context.unit.source != null && tree != null) - logError("AT: " + context.unit.source.dbg(tree.pos), ex); - throw(ex) + reportTypeError(tree.pos, ex) + setError(tree) + case ex: Throwable => + if (settings.debug.value) + System.out.println("exception when typing "+tree+", pt = "+pt) + if (context != null && context.unit != null && context.unit.source != null && tree != null) + logError("AT: " + context.unit.source.dbg(tree.pos), ex); + throw(ex) } def atOwner(owner: Symbol): Typer = diff --git a/test/files/neg/bug563.check b/test/files/neg/bug563.check index 0f2eac240e..3c7423ea7d 100644 --- a/test/files/neg/bug563.check +++ b/test/files/neg/bug563.check @@ -1,9 +1,4 @@ bug563.scala:6 error: missing parameter type map(n,ptr => new Cell(ptr.elem)); ^ -bug563.scala:6 error: no type parameters for method map: (scala.List[A],(A) => R)scala.List[R] exist so that it can be applied to arguments (scala.List[scala.Cell[scala.Int]],(<error>) => <error>) - --- because --- -result type scala.List[R] is incompatible with expected type scala.Unit - map(n,ptr => new Cell(ptr.elem)); - ^ -two errors found +one error found diff --git a/test/files/neg/bug633.check b/test/files/neg/bug633.check new file mode 100644 index 0000000000..55f827ee69 --- /dev/null +++ b/test/files/neg/bug633.check @@ -0,0 +1,4 @@ +bug633.scala:3 error: not found: type ListBuffer + def t(a : ListBuffer[String]) = { + ^ +one error found diff --git a/test/files/neg/bug633.scala b/test/files/neg/bug633.scala new file mode 100644 index 0000000000..fd4e560720 --- /dev/null +++ b/test/files/neg/bug633.scala @@ -0,0 +1,8 @@ +object Test +{ + def t(a : ListBuffer[String]) = { + Console.println(a.length) + } + + def main(argv : Array[String]) = t(null) +} diff --git a/test/files/neg/bug639.check b/test/files/neg/bug639.check new file mode 100644 index 0000000000..7458952ce3 --- /dev/null +++ b/test/files/neg/bug639.check @@ -0,0 +1,9 @@ +/home/odersky/scala/test/files/pos/bug639.scala:1 error: not found: value a +import a._ + ^ +/home/odersky/scala/test/files/pos/bug639.scala:2 error: type mismatch; + found : B + required: scala.Attribute +[B] + ^ +two errors found diff --git a/test/files/neg/bug639.scala b/test/files/neg/bug639.scala new file mode 100644 index 0000000000..7be0968069 --- /dev/null +++ b/test/files/neg/bug639.scala @@ -0,0 +1,3 @@ +import a._ +[B] +class C diff --git a/test/files/pos/bug640.scala b/test/files/pos/bug640.scala new file mode 100644 index 0000000000..d46ecb7546 --- /dev/null +++ b/test/files/pos/bug640.scala @@ -0,0 +1,2 @@ +[serializable] class A +[serializable] class B extends A diff --git a/test/files/run/bigints.check b/test/files/run/bigints.check new file mode 100644 index 0000000000..fb50db6447 --- /dev/null +++ b/test/files/run/bigints.check @@ -0,0 +1,5 @@ +3 +true +false +true +true diff --git a/test/files/run/bigints.scala b/test/files/run/bigints.scala new file mode 100755 index 0000000000..f1328274c6 --- /dev/null +++ b/test/files/run/bigints.scala @@ -0,0 +1,14 @@ +object Test extends Application { + import BigInt._ + + val x: BigInt = 1 + val y = x + 1 + val z = 1 + y + System.out.println(z) + System.out.println(z <= 3) + System.out.println(3 < z) + System.out.println(z == 3) + System.out.println(3 == z) + +} + diff --git a/test/files/run/bug629.check b/test/files/run/bug629.check new file mode 100644 index 0000000000..d86bac9de5 --- /dev/null +++ b/test/files/run/bug629.check @@ -0,0 +1 @@ +OK diff --git a/test/files/run/bug629.scala b/test/files/run/bug629.scala new file mode 100644 index 0000000000..67baead5f1 --- /dev/null +++ b/test/files/run/bug629.scala @@ -0,0 +1,13 @@ +object Test +{ + def main(args : Array[String]) : Unit = Console.println(new C(1)) +} + +abstract class A(val x : Int) + +class C(x : Int) extends A(x) +{ + override def toString() = "OK" + val v = new D + class D { def value = x } +} |