@@ -548,53 +548,32 @@ class Typer extends Namer
548
548
then
549
549
report.error(StableIdentPattern (tree, pt), tree.srcPos)
550
550
551
- def typedSelect (tree : untpd.Select , pt : Type , qual : Tree )(using Context ): Tree = qual match {
551
+ def typedSelect (tree0 : untpd.Select , pt : Type , qual : Tree )(using Context ): Tree = qual match
552
552
case qual : ExtMethodApply =>
553
553
qual.app
554
554
case qual =>
555
- val untpdSelect = cpy.Select (tree)(qual, tree.name)
556
- def finalize (tp : Type ) = assignType(untpdSelect, tp)
557
- val ownType = accessibleSelectionType(untpdSelect, qual)
555
+ val selName = tree0.name
556
+ val tree = cpy.Select (tree0)(qual, selName)
557
+ def finalize (tp : Type ) = assignType(tree, tp)
558
+ val ownType = accessibleSelectionType(tree, qual)
558
559
if ownType.exists then
559
- val select = assignType(untpdSelect , ownType)
560
+ val select = assignType(tree , ownType)
560
561
val select1 = toNotNullTermRef(select, pt)
561
562
562
- if (tree.name. isTypeName) checkStable(qual.tpe, qual.srcPos, " type prefix" )
563
+ if selName. isTypeName then checkStable(qual.tpe, qual.srcPos, " type prefix" )
563
564
checkStableIdentPattern(select1, pt)
564
565
ConstFold (select1)
565
566
else if couldInstantiateTypeVar(qual.tpe.widen) then
566
567
// try again with more defined qualifier type
567
- typedSelect(untpdSelect , pt, qual)
568
+ typedSelect(tree , pt, qual)
568
569
else if qual.tpe.derivesFrom(defn.DynamicClass )
569
- && tree.name. isTermName && ! isDynamicExpansion(untpdSelect )
570
+ && selName. isTermName && ! isDynamicExpansion(tree )
570
571
then
571
572
if pt.isInstanceOf [FunOrPolyProto ] || pt == AssignProto then finalize(TryDynamicCallType )
572
- else typedDynamicSelect(tree , Nil , pt)
573
+ else typedDynamicSelect(tree0 , Nil , pt)
573
574
else
574
- finalize(notAMember(untpdSelect, qual))
575
- /*
576
- // try an extension method in scope
577
- try
578
- val nestedCtx = ctx.fresh.setNewTyperState()
579
- findRef(selName, WildcardType, ExtensionMethod, EmptyFlags, tree.srcPos) match
580
- case ref: TermRef =>
581
- val app = extMethodApply(untpd.ref(ref).withSpan(tree.span), tree, pt)
582
- if !nestedCtx.reporter.hasErrors then
583
- nestedCtx.typerState.commit()
584
- return app
585
- else for err <- nestedCtx.reporter.allErrors.take(1) do
586
- rememberSearchFailure(tree,
587
- SearchFailure(app.withType(FailedExtension(app, pt, err.msg))))
588
- catch case ex: TypeError =>
589
- rememberSearchFailure(tree,
590
- SearchFailure(tree.withType(NestedFailure(ex.toMessage, pt))))
591
-
592
-
593
- val nestedCtx = ctx.fresh.setNewTyperState()
594
- case _ =>
595
- EmptyTree*/
596
-
597
- }
575
+ finalize(notAMember(tree, qual))
576
+ end typedSelect
598
577
599
578
def typedSelect (tree : untpd.Select , pt : Type )(using Context ): Tree = {
600
579
record(" typedSelect" )
@@ -2911,23 +2890,75 @@ class Typer extends Namer
2911
2890
}
2912
2891
}
2913
2892
2914
- /** If this tree is a select node `qual.name`, try to insert an implicit conversion
2915
- * `c` around `qual` so that `c(qual).name` conforms to `pt`.
2893
+ /** If this tree is a select node `qual.name` that does not conform to `pt`,
2894
+ * try to insert an implicit conversion `c` around `qual` so that
2895
+ * `c(qual).name` conforms to `pt`.
2916
2896
*/
2917
2897
def tryInsertImplicitOnQualifier (tree : Tree , pt : Type , locked : TypeVars )(using Context ): Option [Tree ] = trace(i " try insert impl on qualifier $tree $pt" ) {
2918
2898
tree match {
2919
- case Select (qual, name) if name != nme.CONSTRUCTOR =>
2920
- val qualProto = SelectionProto (name, pt, NoViewsAllowed , privateOK = false )
2921
- tryEither {
2922
- val qual1 = adapt(qual, qualProto, locked)
2923
- if ((qual eq qual1) || summon[Context ].reporter.hasErrors) None
2924
- else Some (typed(cpy.Select (tree)(untpd.TypedSplice (qual1), name), pt, locked))
2925
- } { (_, _) => None
2926
- }
2899
+ case tree @ Select (qual, name) if name != nme.CONSTRUCTOR =>
2900
+ val selProto = SelectionProto (name, pt, NoViewsAllowed , privateOK = false )
2901
+ if selProto.isMatchedBy(qual.tpe) then None
2902
+ else
2903
+ tryEither {
2904
+ val tree1 = tryExtensionOrConversion(tree, pt, qual, locked, NoViewsAllowed , privateOK = false )
2905
+ if tree1.isEmpty then None
2906
+ else Some (adapt(tree1, pt, locked))
2907
+ } { (_, _) => None
2908
+ }
2927
2909
case _ => None
2928
2910
}
2929
2911
}
2930
2912
2913
+ /** Given a selection `qual.name`, try to convert to an extension method
2914
+ * application `name(qual)` or insert an implicit conversion `c(qual).name`.
2915
+ */
2916
+ def tryExtensionOrConversion
2917
+ (tree : untpd.Select , pt : Type , qual : Tree , locked : TypeVars , compat : Compatibility , privateOK : Boolean )
2918
+ (using Context ): Tree =
2919
+
2920
+ def selectionProto = SelectionProto (tree.name, pt, compat, privateOK)
2921
+ // try an extension method in scope
2922
+ try
2923
+ val nestedCtx = ctx.fresh.setNewTyperState()
2924
+ findRef(tree.name, WildcardType , ExtensionMethod , EmptyFlags , qual.srcPos) match
2925
+ case ref : TermRef =>
2926
+ val app = extMethodApply(untpd.ref(ref).withSpan(tree.span), qual, pt)
2927
+ if ! nestedCtx.reporter.hasErrors then
2928
+ nestedCtx.typerState.commit()
2929
+ return app
2930
+ for err <- nestedCtx.reporter.allErrors.take(1 ) do
2931
+ rememberSearchFailure(qual,
2932
+ SearchFailure (app.withType(FailedExtension (app, selectionProto, err.msg))))
2933
+ case _ =>
2934
+ catch case ex : TypeError =>
2935
+ rememberSearchFailure(qual,
2936
+ SearchFailure (qual.withType(NestedFailure (ex.toMessage, selectionProto))))
2937
+
2938
+ // try an implicit conversion or given extension
2939
+ if ctx.mode.is(Mode .ImplicitsEnabled ) && qual.tpe.isValueType then
2940
+ trace(i " try insert impl on qualifier $tree $pt" ) {
2941
+ val selProto = selectionProto
2942
+ inferView(qual, selProto) match
2943
+ case SearchSuccess (found : ExtMethodApply , _, _) =>
2944
+ return found.app // nothing to check or adapt for extension method applications
2945
+ case SearchSuccess (found, _, _) =>
2946
+ checkImplicitConversionUseOK(found)
2947
+ val qual1 = withoutMode(Mode .ImplicitsEnabled )(adapt(found, selProto, locked))
2948
+ return typedSelect(tree, pt, qual1)
2949
+ case failure : SearchFailure =>
2950
+ if failure.isAmbiguous then
2951
+ return (
2952
+ if canDefineFurther(qual.tpe.widen) then
2953
+ tryExtensionOrConversion(tree, pt, qual, locked, compat, privateOK)
2954
+ else
2955
+ err.typeMismatch(qual, selProto, failure.reason) // TODO: report NotAMember instead, but need to be aware of failure
2956
+ )
2957
+ rememberSearchFailure(qual, failure)
2958
+ }
2959
+ EmptyTree
2960
+ end tryExtensionOrConversion
2961
+
2931
2962
/** Perform the following adaptations of expression, pattern or type `tree` wrt to
2932
2963
* given prototype `pt`:
2933
2964
* (1) Resolve overloading
0 commit comments