@@ -29,7 +29,7 @@ import config.Printers.{overload, typr, unapp}
2929import TypeApplications ._
3030
3131import reporting .diagnostic .Message
32- import reporting .diagnostic .messages .{UnexpectedPatternForSummonFrom , NotAMember }
32+ import reporting .diagnostic .messages .{UnexpectedPatternForSummonFrom , NotAMember , MissingIdent }
3333import reporting .trace
3434import Constants .{Constant , IntTag , LongTag }
3535import dotty .tools .dotc .reporting .diagnostic .messages .{UnapplyInvalidReturnType , NotAnExtractor , UnapplyInvalidNumberOfArguments }
@@ -819,12 +819,13 @@ trait Applications extends Compatibility {
819819 tryEither {
820820 typedExpr(fn, pt)
821821 } { (result, tstate) =>
822- def fallBack = {
823- tstate.commit()
822+ def fallBack (nuState : TyperState ) =
823+ if (nuState ne ctx.typerState) && ! saysNotFound(nuState, EmptyTypeName )
824+ then nuState.commit() // nuState messages are more interesting that tstate's "not found"
825+ else tstate.commit() // it's "not found" both ways; keep original message
824826 result
825- }
826- if (untpd.isPath(fn)) tryNew(untpd)(fn, pt, fallBack)
827- else fallBack
827+ if untpd.isPath(fn) then tryNew(untpd)(fn, pt, fallBack)
828+ else fallBack(ctx.typerState)
828829 }
829830
830831 /** Typecheck application. Result could be an `Apply` node,
@@ -1056,6 +1057,21 @@ trait Applications extends Compatibility {
10561057 tree
10571058 }
10581059
1060+ /** Does `state` contain a single "NotAMember" or "MissingIdent" message as
1061+ * pending error message that says `$memberName is not a member of ...` or
1062+ * `Not found: $memberName`? If memberName is empty, any name will do.
1063+ */
1064+ def saysNotFound (state : TyperState , memberName : Name )(using Context ): Boolean =
1065+ state.reporter.pendingMessages match
1066+ case msg :: Nil =>
1067+ msg.contained match
1068+ case NotAMember (_, name, _, _) =>
1069+ memberName.isEmpty || name == memberName
1070+ case MissingIdent (_, _, name) =>
1071+ memberName.isEmpty || name == memberName
1072+ case _ => false
1073+ case _ => false
1074+
10591075 def typedUnApply (tree : untpd.Apply , selType : Type )(implicit ctx : Context ): Tree = {
10601076 record(" typedUnApply" )
10611077 val Apply (qual, args) = tree
@@ -1073,15 +1089,10 @@ trait Applications extends Compatibility {
10731089 */
10741090 def reportErrors (tree : Tree , state : TyperState ): Tree =
10751091 assert(state.reporter.hasErrors)
1076- val msgs = state.reporter.removeBufferedMessages
1077- msgs match
1078- case msg :: Nil =>
1079- msg.contained match
1080- case NotAMember (_, nme.unapply, _, _) => return notAnExtractor(tree)
1081- case _ =>
1082- case _ =>
1083- msgs.foreach(ctx.reporter.report)
1084- tree
1092+ if saysNotFound(state, nme.unapply) then notAnExtractor(tree)
1093+ else
1094+ state.reporter.flush()
1095+ tree
10851096
10861097 /** If this is a term ref tree, try to typecheck with its type name.
10871098 * If this refers to a type alias, follow the alias, and if
@@ -1145,7 +1156,12 @@ trait Applications extends Compatibility {
11451156 tryWithName(nme.unapply) {
11461157 (sel, state) =>
11471158 tryWithName(nme.unapplySeq) {
1148- (_, _) => fallBack(sel, state)
1159+ (sel2, state2) =>
1160+ // if both fail, return unapply error, unless that is simply a
1161+ // "not a member", and the unapplySeq error is more refined.
1162+ if saysNotFound(state, nme.unapply) && ! saysNotFound(state2, nme.unapplySeq)
1163+ then fallBack(sel2, state2)
1164+ else fallBack(sel, state)
11491165 }
11501166 }
11511167 }
0 commit comments