Skip to content

Commit d8b210a

Browse files
Merge pull request #5627 from dotty-staging/fix-reporting-required
Better error messages for missing symbols
2 parents 8dbf130 + b161bd0 commit d8b210a

File tree

3 files changed

+56
-25
lines changed

3 files changed

+56
-25
lines changed

compiler/src/dotty/tools/dotc/core/Definitions.scala

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -496,10 +496,10 @@ class Definitions {
496496
def Int_<= : Symbol = Int_leR.symbol
497497
lazy val LongType: TypeRef = valueTypeRef("scala.Long", BoxedLongType, java.lang.Long.TYPE, LongEnc, nme.specializedTypeNames.Long)
498498
def LongClass(implicit ctx: Context): ClassSymbol = LongType.symbol.asClass
499-
lazy val Long_XOR_Long: Symbol = LongType.member(nme.XOR).requiredSymbol(
499+
lazy val Long_XOR_Long: Symbol = LongType.member(nme.XOR).requiredSymbol("method", nme.XOR, LongType.denot)(
500500
x => (x is Method) && (x.info.firstParamTypes.head isRef defn.LongClass)
501501
)
502-
lazy val Long_LSR_Int: Symbol = LongType.member(nme.LSR).requiredSymbol(
502+
lazy val Long_LSR_Int: Symbol = LongType.member(nme.LSR).requiredSymbol("method", nme.LSR, LongType.denot)(
503503
x => (x is Method) && (x.info.firstParamTypes.head isRef defn.IntClass)
504504
)
505505
lazy val Long_plusR: TermRef = LongClass.requiredMethodRef(nme.PLUS, List(LongType))
@@ -729,7 +729,7 @@ class Definitions {
729729
def TupleXXLModule(implicit ctx: Context): Symbol = TupleXXLClass.companionModule
730730

731731
def TupleXXL_apply(implicit ctx: Context): Symbol =
732-
TupleXXLModule.info.member(nme.apply).requiredSymbol(_.info.isVarArgsMethod)
732+
TupleXXLModule.info.member(nme.apply).requiredSymbol("method", nme.apply, TupleXXLModule)(_.info.isVarArgsMethod)
733733

734734
// Annotation base classes
735735
lazy val AnnotationType: TypeRef = ctx.requiredClassRef("scala.annotation.Annotation")

compiler/src/dotty/tools/dotc/core/Denotations.scala

Lines changed: 32 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -276,7 +276,14 @@ object Denotations {
276276
* if generateStubs is specified, return a stubsymbol if denotation is a missing ref.
277277
* Throw a `TypeError` if predicate fails to disambiguate symbol or no alternative matches.
278278
*/
279-
def requiredSymbol(p: Symbol => Boolean, source: AbstractFile = null, generateStubs: Boolean = true)(implicit ctx: Context): Symbol =
279+
def requiredSymbol(kind: String,
280+
name: Name,
281+
site: Denotation = NoDenotation,
282+
args: List[Type] = Nil,
283+
source: AbstractFile = null,
284+
generateStubs: Boolean = true)
285+
(p: Symbol => Boolean)
286+
(implicit ctx: Context): Symbol =
280287
disambiguate(p) match {
281288
case m @ MissingRef(ownerd, name) =>
282289
if (generateStubs) {
@@ -285,18 +292,25 @@ object Denotations {
285292
}
286293
else NoSymbol
287294
case NoDenotation | _: NoQualifyingRef =>
288-
throw new TypeError(i"None of the alternatives of $this satisfies required predicate")
295+
def argStr = if (args.isEmpty) "" else i" matching ($args%, %)"
296+
val msg =
297+
if (site.exists) i"$site does not have a member $kind $name$argStr"
298+
else i"missing: $kind $name$argStr"
299+
throw new TypeError(msg)
289300
case denot =>
290301
denot.symbol
291302
}
292303

293-
def requiredMethod(name: PreName)(implicit ctx: Context): TermSymbol =
294-
info.member(name.toTermName).requiredSymbol(_ is Method).asTerm
304+
def requiredMethod(pname: PreName)(implicit ctx: Context): TermSymbol = {
305+
val name = pname.toTermName
306+
info.member(name).requiredSymbol("method", name, this)(_ is Method).asTerm
307+
}
295308
def requiredMethodRef(name: PreName)(implicit ctx: Context): TermRef =
296309
requiredMethod(name).termRef
297310

298-
def requiredMethod(name: PreName, argTypes: List[Type])(implicit ctx: Context): TermSymbol = {
299-
info.member(name.toTermName).requiredSymbol { x =>
311+
def requiredMethod(pname: PreName, argTypes: List[Type])(implicit ctx: Context): TermSymbol = {
312+
val name = pname.toTermName
313+
info.member(name).requiredSymbol(i"method", name, this, argTypes) { x =>
300314
(x is Method) && {
301315
x.info.paramInfoss match {
302316
case paramInfos :: Nil => paramInfos.corresponds(argTypes)(_ =:= _)
@@ -308,16 +322,22 @@ object Denotations {
308322
def requiredMethodRef(name: PreName, argTypes: List[Type])(implicit ctx: Context): TermRef =
309323
requiredMethod(name, argTypes).termRef
310324

311-
def requiredValue(name: PreName)(implicit ctx: Context): TermSymbol =
312-
info.member(name.toTermName).requiredSymbol(_.info.isParameterless).asTerm
325+
def requiredValue(pname: PreName)(implicit ctx: Context): TermSymbol = {
326+
val name = pname.toTermName
327+
info.member(name).requiredSymbol("field or getter", name, this)(_.info.isParameterless).asTerm
328+
}
313329
def requiredValueRef(name: PreName)(implicit ctx: Context): TermRef =
314330
requiredValue(name).termRef
315331

316-
def requiredClass(name: PreName)(implicit ctx: Context): ClassSymbol =
317-
info.member(name.toTypeName).requiredSymbol(_.isClass).asClass
332+
def requiredClass(pname: PreName)(implicit ctx: Context): ClassSymbol = {
333+
val name = pname.toTypeName
334+
info.member(name).requiredSymbol("class", name, this)(_.isClass).asClass
335+
}
318336

319-
def requiredType(name: PreName)(implicit ctx: Context): TypeSymbol =
320-
info.member(name.toTypeName).requiredSymbol(_.isType).asType
337+
def requiredType(pname: PreName)(implicit ctx: Context): TypeSymbol = {
338+
val name = pname.toTypeName
339+
info.member(name).requiredSymbol("type", name, this)(_.isType).asType
340+
}
321341

322342
/** The alternative of this denotation that has a type matching `targetType` when seen
323343
* as a member of type `site`, `NoDenotation` if none exists.

compiler/src/dotty/tools/dotc/core/Symbols.scala

Lines changed: 21 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -363,32 +363,43 @@ trait Symbols { this: Context =>
363363

364364
// ----- Locating predefined symbols ----------------------------------------
365365

366-
def requiredPackage(path: PreName): TermSymbol =
367-
base.staticRef(path.toTermName, isPackage = true).requiredSymbol(_ is Package).asTerm
366+
def requiredPackage(path: PreName): TermSymbol = {
367+
val name = path.toTermName
368+
base.staticRef(name, isPackage = true).requiredSymbol("package", name)(_ is Package).asTerm
369+
}
368370

369371
def requiredPackageRef(path: PreName): TermRef = requiredPackage(path).termRef
370372

371-
def requiredClass(path: PreName): ClassSymbol =
372-
base.staticRef(path.toTypeName).requiredSymbol(_.isClass) match {
373+
def requiredClass(path: PreName): ClassSymbol = {
374+
val name = path.toTypeName
375+
base.staticRef(name).requiredSymbol("class", name)(_.isClass) match {
373376
case cls: ClassSymbol => cls
374377
case sym => defn.AnyClass
375378
}
379+
}
376380

377381
def requiredClassRef(path: PreName): TypeRef = requiredClass(path).typeRef
378382

379383
/** Get ClassSymbol if class is either defined in current compilation run
380384
* or present on classpath.
381385
* Returns NoSymbol otherwise. */
382-
def getClassIfDefined(path: PreName): Symbol =
383-
base.staticRef(path.toTypeName, generateStubs = false).requiredSymbol(_.isClass, generateStubs = false)
386+
def getClassIfDefined(path: PreName): Symbol = {
387+
val name = path.toTypeName
388+
base.staticRef(name, generateStubs = false)
389+
.requiredSymbol("class", name, generateStubs = false)(_.isClass)
390+
}
384391

385-
def requiredModule(path: PreName): TermSymbol =
386-
base.staticRef(path.toTermName).requiredSymbol(_ is Module).asTerm
392+
def requiredModule(path: PreName): TermSymbol = {
393+
val name = path.toTermName
394+
base.staticRef(name).requiredSymbol("object", name)(_ is Module).asTerm
395+
}
387396

388397
def requiredModuleRef(path: PreName): TermRef = requiredModule(path).termRef
389398

390-
def requiredMethod(path: PreName): TermSymbol =
391-
base.staticRef(path.toTermName).requiredSymbol(_ is Method).asTerm
399+
def requiredMethod(path: PreName): TermSymbol = {
400+
val name = path.toTermName
401+
base.staticRef(name).requiredSymbol("method", name)(_ is Method).asTerm
402+
}
392403

393404
def requiredMethodRef(path: PreName): TermRef = requiredMethod(path).termRef
394405
}

0 commit comments

Comments
 (0)