From 6137fd58034d7cb5feff90ec26447fd800b37ddd Mon Sep 17 00:00:00 2001 From: Martin Odersky Date: Tue, 4 Aug 2020 17:14:20 +0200 Subject: [PATCH 1/4] Make Type#orElse an inline method --- compiler/src/dotty/tools/dotc/core/Types.scala | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compiler/src/dotty/tools/dotc/core/Types.scala b/compiler/src/dotty/tools/dotc/core/Types.scala index df248eb2987e..d053c1fc87c2 100644 --- a/compiler/src/dotty/tools/dotc/core/Types.scala +++ b/compiler/src/dotty/tools/dotc/core/Types.scala @@ -143,7 +143,7 @@ object Types { final def exists: Boolean = this.ne(NoType) /** This type, if it exists, otherwise `that` type */ - def orElse(that: => Type): Type = if (exists) this else that + inline def orElse(inline that: => Type): Type = if (exists) this else that /** Is this type a value type? */ final def isValueType: Boolean = this.isInstanceOf[ValueType] From 06250cd41e24a473489ee219670a7ba10e91c6e5 Mon Sep 17 00:00:00 2001 From: Martin Odersky Date: Sat, 22 Aug 2020 11:00:48 +0200 Subject: [PATCH 2/4] Avoid closure creation in Checking --- compiler/src/dotty/tools/dotc/typer/Checking.scala | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compiler/src/dotty/tools/dotc/typer/Checking.scala b/compiler/src/dotty/tools/dotc/typer/Checking.scala index 2b8987103556..204cf29a2058 100644 --- a/compiler/src/dotty/tools/dotc/typer/Checking.scala +++ b/compiler/src/dotty/tools/dotc/typer/Checking.scala @@ -433,7 +433,7 @@ object Checking { def checkNoConflict(flag1: FlagSet, flag2: FlagSet, msg: => String) = if (sym.isAllOf(flag1 | flag2)) fail(msg) def checkCombination(flag1: FlagSet, flag2: FlagSet) = - checkNoConflict(flag1, flag2, i"illegal combination of modifiers: `${flag1.flagsString}` and `${flag2.flagsString}` for: $sym") + if sym.isAllOf(flag1 | flag2) then fail(i"illegal combination of modifiers: `${flag1.flagsString}` and `${flag2.flagsString}` for: $sym") def checkApplicable(flag: FlagSet, ok: Boolean) = if (!ok && !sym.is(Synthetic)) fail(i"modifier `${flag.flagsString}` is not allowed for this definition") From fb158586956d67441fe75b04041142061d3eec36 Mon Sep 17 00:00:00 2001 From: Martin Odersky Date: Wed, 29 Jul 2020 19:24:51 +0200 Subject: [PATCH 3/4] Omit unnecessary setNewScope --- compiler/src/dotty/tools/dotc/typer/Typer.scala | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compiler/src/dotty/tools/dotc/typer/Typer.scala b/compiler/src/dotty/tools/dotc/typer/Typer.scala index 31e8fac005dc..a0131a45ad17 100644 --- a/compiler/src/dotty/tools/dotc/typer/Typer.scala +++ b/compiler/src/dotty/tools/dotc/typer/Typer.scala @@ -2432,7 +2432,7 @@ class Typer extends Namer case tree: untpd.Bind => typedBind(tree, pt) case tree: untpd.ValDef => if (tree.isEmpty) tpd.EmptyValDef - else typedValDef(tree, sym)(using ctx.localContext(tree, sym).setNewScope) + else typedValDef(tree, sym)(using ctx.localContext(tree, sym)) case tree: untpd.DefDef => val typer1 = localTyper(sym) typer1.typedDefDef(tree, sym)(using ctx.localContext(tree, sym).setTyper(typer1)) From 8e17b76c8d202abd85ef3d21f137ca0712a125a0 Mon Sep 17 00:00:00 2001 From: Martin Odersky Date: Thu, 30 Jul 2020 14:46:09 +0200 Subject: [PATCH 4/4] Create fewer extension names --- compiler/src/dotty/tools/dotc/typer/Applications.scala | 7 +++---- compiler/src/dotty/tools/dotc/typer/Implicits.scala | 8 ++++---- compiler/src/dotty/tools/dotc/typer/ProtoTypes.scala | 9 +++++++-- compiler/src/dotty/tools/dotc/typer/Typer.scala | 4 ++-- tests/neg/i7813.scala | 2 +- 5 files changed, 17 insertions(+), 13 deletions(-) diff --git a/compiler/src/dotty/tools/dotc/typer/Applications.scala b/compiler/src/dotty/tools/dotc/typer/Applications.scala index 9d030fb14ea6..fa3a1899246c 100644 --- a/compiler/src/dotty/tools/dotc/typer/Applications.scala +++ b/compiler/src/dotty/tools/dotc/typer/Applications.scala @@ -1357,11 +1357,10 @@ trait Applications extends Compatibility { followApply && tp.member(nme.apply).hasAltWith(d => p(TermRef(tp, nme.apply, d))) } - /** Does `tp` have an extension method named `extension_name` with this-argument `argType` and - * result matching `resultType`? + /** Does `tp` have an extension method named `xname` with this-argument `argType` and + * result matching `resultType`? `xname` is supposed to start with `extension_`. */ - def hasExtensionMethod(tp: Type, name: TermName, argType: Type, resultType: Type)(using Context) = { - val xname = name.toExtensionName + def hasExtensionMethodNamed(tp: Type, xname: TermName, argType: Type, resultType: Type)(using Context) = { def qualifies(mbr: Denotation) = mbr.exists && isApplicableType(tp.select(xname, mbr), argType :: Nil, resultType) tp.memberBasedOnFlags(xname, required = ExtensionMethod) match { diff --git a/compiler/src/dotty/tools/dotc/typer/Implicits.scala b/compiler/src/dotty/tools/dotc/typer/Implicits.scala index cba3af104944..7a4f1dcab4c4 100644 --- a/compiler/src/dotty/tools/dotc/typer/Implicits.scala +++ b/compiler/src/dotty/tools/dotc/typer/Implicits.scala @@ -69,8 +69,8 @@ object Implicits: * method with the selecting name? False otherwise. */ def hasExtMethod(tp: Type, expected: Type)(using Context) = expected match - case SelectionProto(name, _, _, _) => - tp.memberBasedOnFlags(name.toExtensionName, required = ExtensionMethod).exists + case selProto @ SelectionProto(_: TermName, _, _, _) => + tp.memberBasedOnFlags(selProto.extensionName, required = ExtensionMethod).exists case _ => false def strictEquality(using Context): Boolean = @@ -1034,9 +1034,9 @@ trait Implicits: pt, locked) } pt match - case SelectionProto(name: TermName, mbrType, _, _) if cand.isExtension => + case selProto @ SelectionProto(_: TermName, mbrType, _, _) if cand.isExtension => def tryExtension(using Context) = - extMethodApply(untpd.Select(untpdGenerated, name.toExtensionName), argument, mbrType) + extMethodApply(untpd.Select(untpdGenerated, selProto.extensionName), argument, mbrType) if cand.isConversion then val extensionCtx, conversionCtx = ctx.fresh.setNewTyperState() val extensionResult = tryExtension(using extensionCtx) diff --git a/compiler/src/dotty/tools/dotc/typer/ProtoTypes.scala b/compiler/src/dotty/tools/dotc/typer/ProtoTypes.scala index 6920d972b387..44beaffa55a0 100644 --- a/compiler/src/dotty/tools/dotc/typer/ProtoTypes.scala +++ b/compiler/src/dotty/tools/dotc/typer/ProtoTypes.scala @@ -129,6 +129,11 @@ object ProtoTypes { abstract case class SelectionProto(name: Name, memberProto: Type, compat: Compatibility, privateOK: Boolean) extends CachedProxyType with ProtoType with ValueTypeOrProto { + private var myExtensionName: TermName = null + def extensionName: TermName = + if myExtensionName == null then myExtensionName = name.toExtensionName + myExtensionName + /** Is the set of members of this type unknown? This is the case if: * 1. The type has Nothing or Wildcard as a prefix or underlying type * 2. The type has an uninstantiated TypeVar as a prefix or underlying type, @@ -416,8 +421,8 @@ object ProtoTypes { def isMatchedBy(tp: Type, keepConstraint: Boolean)(using Context): Boolean = ctx.typer.isApplicableType(tp, argType :: Nil, resultType) || { resType match { - case SelectionProto(name: TermName, mbrType, _, _) => - ctx.typer.hasExtensionMethod(tp, name, argType, mbrType) + case selProto @ SelectionProto(_: TermName, mbrType, _, _) => + ctx.typer.hasExtensionMethodNamed(tp, selProto.extensionName, argType, mbrType) //.reporting(i"has ext $tp $name $argType $mbrType: $result") case _ => false diff --git a/compiler/src/dotty/tools/dotc/typer/Typer.scala b/compiler/src/dotty/tools/dotc/typer/Typer.scala index a0131a45ad17..037aeb3adf68 100644 --- a/compiler/src/dotty/tools/dotc/typer/Typer.scala +++ b/compiler/src/dotty/tools/dotc/typer/Typer.scala @@ -3468,10 +3468,10 @@ class Typer extends Namer // try an extension method in scope pt match { - case SelectionProto(name, mbrType, _, _) => + case selProto @ SelectionProto(_: TermName, mbrType, _, _) => def tryExtension(using Context): Tree = try - findRef(name.toExtensionName, WildcardType, ExtensionMethod, tree.srcPos) match { + findRef(selProto.extensionName, WildcardType, ExtensionMethod, tree.srcPos) match { case ref: TermRef => extMethodApply(untpd.ref(ref).withSpan(tree.span), tree, mbrType) case _ => EmptyTree diff --git a/tests/neg/i7813.scala b/tests/neg/i7813.scala index b314072c2bf5..ba8cde5821c6 100644 --- a/tests/neg/i7813.scala +++ b/tests/neg/i7813.scala @@ -1,3 +1,3 @@ implicit def f[X <: Undefined](implicit a: Int): X = ??? // error -def g(arg: h.NonExistent): Int = ??? +def g(arg: h.NonExistent): Int = ??? // error val h: Int = ??? \ No newline at end of file