@@ -13,6 +13,8 @@ import ast.Trees._
13
13
import NameOps ._
14
14
import collection .mutable
15
15
import reporting .diagnostic .messages ._
16
+ import util .Stats .record
17
+ import Inferencing ._
16
18
import Checking .{checkNoPrivateLeaks , checkNoWildcard }
17
19
18
20
trait TypeAssigner {
@@ -163,6 +165,20 @@ trait TypeAssigner {
163
165
164
166
def arrayToRepeated (tree : Tree )(implicit ctx : Context ): Tree = toRepeated(tree, defn.ArrayClass )
165
167
168
+ def tryEither [T ](op : Context => T )(fallBack : (T , TyperState ) => T )(implicit ctx : Context ): T = {
169
+ val nestedCtx = ctx.fresh.setNewTyperState()
170
+ val result = op(nestedCtx)
171
+ if (nestedCtx.reporter.hasErrors && ! nestedCtx.reporter.hasStickyErrors) {
172
+ record(" tryEither.fallBack" )
173
+ fallBack(result, nestedCtx.typerState)
174
+ }
175
+ else {
176
+ record(" tryEither.commit" )
177
+ nestedCtx.typerState.commit()
178
+ result
179
+ }
180
+ }
181
+
166
182
/** A denotation exists really if it exists and does not point to a stale symbol. */
167
183
final def reallyExists (denot : Denotation )(implicit ctx : Context ): Boolean = try
168
184
denot match {
@@ -228,6 +244,7 @@ trait TypeAssigner {
228
244
229
245
/** The type of the selection `tree`, where `qual1` is the typed qualifier part. */
230
246
def selectionType (tree : untpd.RefTree , qual1 : Tree )(implicit ctx : Context ): Type = {
247
+
231
248
var qualType = qual1.tpe.widenIfUnstable
232
249
if (! qualType.hasSimpleKind && tree.name != nme.CONSTRUCTOR )
233
250
// constructors are selected on typeconstructor, type arguments are passed afterwards
@@ -236,29 +253,39 @@ trait TypeAssigner {
236
253
qualType = errorType(em " $qualType is illegal as a selection prefix " , qual1.sourcePos)
237
254
val name = tree.name
238
255
val mbr = qualType.member(name)
256
+
257
+ def fail = if (name == nme.CONSTRUCTOR )
258
+ errorType(ex " $qualType does not have a constructor " , tree.sourcePos)
259
+ else {
260
+ val kind = if (name.isTypeName) " type" else " value"
261
+ val addendum =
262
+ if (qualType.derivesFrom(defn.DynamicClass ))
263
+ " \n possible cause: maybe a wrong Dynamic method signature?"
264
+ else qual1.getAttachment(Typer .HiddenSearchFailure ) match {
265
+ case Some (failure) if ! failure.reason.isInstanceOf [Implicits .NoMatchingImplicits ] =>
266
+ i """ .
267
+ |An extension method was tried, but could not be fully constructed:
268
+ |
269
+ | ${failure.tree.show.replace(" \n " , " \n " )}"""
270
+ case _ => " "
271
+ }
272
+ errorType(NotAMember (qualType, name, kind, addendum), tree.sourcePos)
273
+ }
274
+
239
275
if (reallyExists(mbr))
240
276
qualType.select(name, mbr)
241
277
else if (qualType.derivesFrom(defn.DynamicClass ) && name.isTermName && ! Dynamic .isDynamicMethod(name))
242
278
TryDynamicCallType
243
279
else if (qualType.isErroneous || name.toTermName == nme.ERROR )
244
280
UnspecifiedErrorType
245
- else if (name == nme.CONSTRUCTOR )
246
- errorType(ex " $qualType does not have a constructor " , tree.sourcePos)
247
- else {
248
- val kind = if (name.isTypeName) " type" else " value"
249
- val addendum =
250
- if (qualType.derivesFrom(defn.DynamicClass ))
251
- " \n possible cause: maybe a wrong Dynamic method signature?"
252
- else qual1.getAttachment(Typer .HiddenSearchFailure ) match {
253
- case Some (failure) if ! failure.reason.isInstanceOf [Implicits .NoMatchingImplicits ] =>
254
- i """ .
255
- |An extension method was tried, but could not be fully constructed:
256
- |
257
- | ${failure.tree.show.replace(" \n " , " \n " )}"""
258
- case _ => " "
259
- }
260
- errorType(NotAMember (qualType, name, kind, addendum), tree.sourcePos)
261
- }
281
+ else if (! isFullyDefined(qualType, force = ForceDegree .none))
282
+ tryEither { implicit ctx =>
283
+ fullyDefinedType(qualType, " selection prefix" , qual1.span)
284
+ selectionType(tree, qual1)
285
+ } { (_, _) =>
286
+ fail
287
+ }
288
+ else fail
262
289
}
263
290
264
291
/** The type of the selection in `tree`, where `qual1` is the typed qualifier part.
0 commit comments