@@ -4581,6 +4581,186 @@ typeCheckArgumentChildIndependently(Expr *argExpr, Type argType,
4581
4581
TE->isImplicit (), TT);
4582
4582
}
4583
4583
4584
+ static bool diagnoseImplicitSelfErrors (Expr *fnExpr, Expr *argExpr,
4585
+ CalleeCandidateInfo &CCI,
4586
+ ArrayRef<Identifier> argLabels,
4587
+ ConstraintSystem *CS) {
4588
+ // If candidate list is empty it means that problem is somewhere else,
4589
+ // since we need to have candidates which might be shadowing other funcs.
4590
+ if (CCI.empty () || !CCI[0 ].getDecl ())
4591
+ return false ;
4592
+
4593
+ auto &TC = CS->TC ;
4594
+ // Call expression is formed as 'foo.bar' where 'foo' might be an
4595
+ // implicit "Self" reference, such use wouldn't provide good diagnostics
4596
+ // for situations where instance members have equal names to functions in
4597
+ // Swift Standard Library e.g. min/max.
4598
+ auto UDE = dyn_cast<UnresolvedDotExpr>(fnExpr);
4599
+ if (!UDE)
4600
+ return false ;
4601
+
4602
+ auto baseExpr = dyn_cast<DeclRefExpr>(UDE->getBase ());
4603
+ if (!baseExpr)
4604
+ return false ;
4605
+
4606
+ auto baseDecl = baseExpr->getDecl ();
4607
+ if (!baseExpr->isImplicit () || baseDecl->getName () != TC.Context .Id_self )
4608
+ return false ;
4609
+
4610
+ // Our base expression is an implicit 'self.' reference e.g.
4611
+ //
4612
+ // extension Sequence {
4613
+ // func test() -> Int {
4614
+ // return max(1, 2)
4615
+ // }
4616
+ // }
4617
+ //
4618
+ // In this example the Sequence class already has two methods named 'max'
4619
+ // none of which accept two arguments, but there is a function in
4620
+ // Swift Standard Library called 'max' which does accept two arguments,
4621
+ // so user might have called that by mistake without realizing that
4622
+ // compiler would add implicit 'self.' prefix to the call of 'max'.
4623
+ ExprCleaner cleanup (argExpr);
4624
+
4625
+ // Let's type check argument expression without any contextual information.
4626
+ ConcreteDeclRef ref = nullptr ;
4627
+ auto typeResult = TC.getTypeOfExpressionWithoutApplying (argExpr, CS->DC , ref);
4628
+ if (!typeResult.hasValue ())
4629
+ return false ;
4630
+
4631
+ auto argType = typeResult.getValue ();
4632
+
4633
+ // If argument type couldn't be properly resolved or has errors,
4634
+ // we can't diagnose anything in here, it points to the different problem.
4635
+ if (isUnresolvedOrTypeVarType (argType) || argType->hasError ())
4636
+ return false ;
4637
+
4638
+ auto context = CS->DC ;
4639
+ using CandididateMap =
4640
+ llvm::SmallDenseMap<ValueDecl *, llvm::SmallVector<OverloadChoice, 2 >>;
4641
+
4642
+ auto getBaseKind = [](ValueDecl *base) -> DescriptiveDeclKind {
4643
+ DescriptiveDeclKind kind = DescriptiveDeclKind::Module;
4644
+ if (!base)
4645
+ return kind;
4646
+
4647
+ auto context = base->getDeclContext ();
4648
+ do {
4649
+ if (isa<ExtensionDecl>(context))
4650
+ return DescriptiveDeclKind::Extension;
4651
+
4652
+ if (auto nominal = dyn_cast<NominalTypeDecl>(context)) {
4653
+ kind = nominal->getDescriptiveKind ();
4654
+ break ;
4655
+ }
4656
+
4657
+ context = context->getParent ();
4658
+ } while (context);
4659
+
4660
+ return kind;
4661
+ };
4662
+
4663
+ auto getBaseName = [](DeclContext *context) -> DeclName {
4664
+ if (context->isTypeContext ()) {
4665
+ auto generic = context->getAsGenericTypeOrGenericTypeExtensionContext ();
4666
+ return generic->getName ();
4667
+ } else if (context->isModuleScopeContext ())
4668
+ return context->getParentModule ()->getName ();
4669
+ else
4670
+ llvm_unreachable (" Unsupported base" );
4671
+ };
4672
+
4673
+ auto diagnoseShadowing = [&](ValueDecl *base,
4674
+ ArrayRef<OverloadChoice> candidates) -> bool {
4675
+ CalleeCandidateInfo calleeInfo (base ? base->getInterfaceType () : nullptr ,
4676
+ candidates, CCI.hasTrailingClosure , CS,
4677
+ base);
4678
+
4679
+ calleeInfo.filterList (argType, argLabels);
4680
+ if (calleeInfo.closeness != CC_ExactMatch)
4681
+ return false ;
4682
+
4683
+ auto choice = calleeInfo.candidates [0 ].getDecl ();
4684
+ auto baseKind = getBaseKind (base);
4685
+ auto baseName = getBaseName (choice->getDeclContext ());
4686
+
4687
+ auto origCandidate = CCI[0 ].getDecl ();
4688
+ TC.diagnose (UDE->getLoc (), diag::member_shadows_global_function,
4689
+ UDE->getName (), origCandidate->getDescriptiveKind (),
4690
+ origCandidate->getFullName (), choice->getDescriptiveKind (),
4691
+ choice->getFullName (), baseKind, baseName);
4692
+
4693
+ auto topLevelDiag = diag::fix_unqualified_access_top_level;
4694
+ if (baseKind == DescriptiveDeclKind::Module)
4695
+ topLevelDiag = diag::fix_unqualified_access_top_level_multi;
4696
+
4697
+ auto name = baseName.getBaseName ();
4698
+ SmallString<32 > namePlusDot = name.str ();
4699
+ namePlusDot.push_back (' .' );
4700
+
4701
+ TC.diagnose (UDE->getLoc (), topLevelDiag, namePlusDot,
4702
+ choice->getDescriptiveKind (), name)
4703
+ .fixItInsert (UDE->getStartLoc (), namePlusDot);
4704
+
4705
+ for (auto &candidate : calleeInfo.candidates ) {
4706
+ if (auto decl = candidate.getDecl ())
4707
+ TC.diagnose (decl, diag::decl_declared_here, decl->getFullName ());
4708
+ }
4709
+
4710
+ return true ;
4711
+ };
4712
+
4713
+ // For each of the parent contexts, let's try to find any candidates
4714
+ // which have the same name and the same number of arguments as callee.
4715
+ while (context->getParent ()) {
4716
+ auto result = TC.lookupUnqualified (context, UDE->getName (), UDE->getLoc ());
4717
+ context = context->getParent ();
4718
+
4719
+ if (!result || result.empty ())
4720
+ continue ;
4721
+
4722
+ CandididateMap candidates;
4723
+ for (const auto &candidate : result) {
4724
+ auto base = candidate.Base ;
4725
+ if ((base && base->isInvalid ()) || candidate->isInvalid ())
4726
+ continue ;
4727
+
4728
+ // If base is present but it doesn't represent a valid nominal,
4729
+ // we can't use current candidate as one of the choices.
4730
+ if (base && !base->getInterfaceType ()->getNominalOrBoundGenericNominal ())
4731
+ continue ;
4732
+
4733
+ auto context = candidate->getDeclContext ();
4734
+ // We are only interested in static or global functions, because
4735
+ // there is no way to call anything else properly.
4736
+ if (!candidate->isStatic () && !context->isModuleScopeContext ())
4737
+ continue ;
4738
+
4739
+ OverloadChoice choice (base ? base->getInterfaceType () : nullptr ,
4740
+ candidate, false , UDE->getFunctionRefKind ());
4741
+
4742
+ if (base) { // Let's group all of the candidates have a common base.
4743
+ candidates[base].push_back (choice);
4744
+ continue ;
4745
+ }
4746
+
4747
+ // If there is no base, it means this is one of the global functions,
4748
+ // let's try to diagnose its shadowing inline.
4749
+ if (diagnoseShadowing (base, choice))
4750
+ return true ;
4751
+ }
4752
+
4753
+ if (candidates.empty ())
4754
+ continue ;
4755
+
4756
+ for (const auto &candidate : candidates) {
4757
+ if (diagnoseShadowing (candidate.getFirst (), candidate.getSecond ()))
4758
+ return true ;
4759
+ }
4760
+ }
4761
+
4762
+ return false ;
4763
+ }
4584
4764
4585
4765
// / Emit a class of diagnostics that we only know how to generate when there is
4586
4766
// / exactly one candidate we know about. Return true if an error is emitted.
@@ -4984,6 +5164,10 @@ bool FailureDiagnosis::diagnoseParameterErrors(CalleeCandidateInfo &CCI,
4984
5164
}
4985
5165
}
4986
5166
5167
+ // Try to diagnose errors related to the use of implicit self reference.
5168
+ if (diagnoseImplicitSelfErrors (fnExpr, argExpr, CCI, argLabels, CS))
5169
+ return true ;
5170
+
4987
5171
// Do all the stuff that we only have implemented when there is a single
4988
5172
// candidate.
4989
5173
if (diagnoseSingleCandidateFailures (CCI, fnExpr, argExpr, argLabels))
0 commit comments