@@ -1812,71 +1812,71 @@ static std::pair<Type, Type> getTypeOfReferenceWithSpecialTypeCheckingSemantics(
1812
1812
llvm_unreachable (" Unhandled DeclTypeCheckingSemantics in switch." );
1813
1813
}
1814
1814
1815
- // / \returns true if given declaration is an instance method marked as
1816
- // / `mutating`, false otherwise.
1817
- bool isMutatingMethod (const ValueDecl *decl) {
1818
- if (!(decl->isInstanceMember () && isa<FuncDecl>(decl)))
1819
- return false ;
1820
- return cast<FuncDecl>(decl)->isMutating ();
1821
- }
1822
-
1823
- static bool shouldCheckForPartialApplication (ConstraintSystem &cs,
1824
- const ValueDecl *decl,
1825
- ConstraintLocator *locator) {
1826
- auto *anchor = locator->getAnchor ();
1827
- if (!(anchor && isa<UnresolvedDotExpr>(anchor)))
1828
- return false ;
1829
-
1830
- // If this is a reference to instance method marked as 'mutating'
1831
- // it should be checked for invalid partial application.
1832
- if (isMutatingMethod (decl))
1833
- return true ;
1834
-
1835
- // Another unsupported partial application is related
1836
- // to constructor delegation via `self.init` or `super.init`.
1837
-
1838
- if (!isa<ConstructorDecl>(decl))
1839
- return false ;
1840
-
1841
- auto *UDE = cast<UnresolvedDotExpr>(anchor);
1842
- // This is `super.init`
1843
- if (UDE->getBase ()->isSuperExpr ())
1844
- return true ;
1845
-
1846
- // Or this might be `self.init`.
1847
- if (auto *DRE = dyn_cast<DeclRefExpr>(UDE->getBase ())) {
1848
- if (auto *baseDecl = DRE->getDecl ())
1849
- return baseDecl->getBaseName () == cs.getASTContext ().Id_self ;
1850
- }
1851
-
1852
- return false ;
1853
- }
1854
-
1855
1815
// / Try to identify and fix failures related to partial function application
1856
1816
// / e.g. partial application of `init` or 'mutating' instance methods.
1857
1817
static std::pair<bool , unsigned >
1858
- isInvalidPartialApplication (ConstraintSystem &cs, const ValueDecl *member,
1818
+ isInvalidPartialApplication (ConstraintSystem &cs,
1819
+ const AbstractFunctionDecl *member,
1859
1820
ConstraintLocator *locator) {
1860
- if (!shouldCheckForPartialApplication (cs, member, locator))
1861
- return {false , 0 };
1821
+ auto *UDE = dyn_cast_or_null<UnresolvedDotExpr>(locator->getAnchor ());
1822
+ if (UDE == nullptr )
1823
+ return {false ,0 };
1862
1824
1863
- auto anchor = cast<UnresolvedDotExpr>(locator->getAnchor ());
1864
- // If this choice is a partial application of `init` or
1865
- // `mutating` instance method we should report that it's not allowed.
1866
1825
auto baseTy =
1867
- cs.simplifyType (cs.getType (anchor->getBase ()))->getWithoutSpecifierType ();
1826
+ cs.simplifyType (cs.getType (UDE->getBase ()))->getWithoutSpecifierType ();
1827
+
1828
+ auto isInvalidIfPartiallyApplied = [&]() {
1829
+ if (auto *FD = dyn_cast<FuncDecl>(member)) {
1830
+ // 'mutating' instance methods cannot be partially applied.
1831
+ if (FD->isMutating ())
1832
+ return true ;
1833
+
1834
+ // Instance methods cannot be referenced on 'super' from a static
1835
+ // context.
1836
+ if (UDE->getBase ()->isSuperExpr () &&
1837
+ baseTy->is <MetatypeType>() &&
1838
+ !FD->isStatic ())
1839
+ return true ;
1840
+ }
1868
1841
1869
- // Partial applications are not allowed only for constructor
1870
- // delegation, reference on the metatype is considered acceptable.
1871
- if (baseTy->is <MetatypeType>() && isa<ConstructorDecl>(member))
1872
- return {false , 0 };
1842
+ // Another unsupported partial application is related
1843
+ // to constructor delegation via 'self.init' or 'super.init'.
1844
+ //
1845
+ // Note that you can also write 'self.init' or 'super.init'
1846
+ // inside a static context -- since 'self' is a metatype there
1847
+ // it doesn't have the special delegation meaning that it does
1848
+ // in the body of a constructor.
1849
+ if (isa<ConstructorDecl>(member) && !baseTy->is <MetatypeType>()) {
1850
+ // Check for a `super.init` delegation...
1851
+ if (UDE->getBase ()->isSuperExpr ())
1852
+ return true ;
1853
+
1854
+ // ... and `self.init` delegation. Note that in a static context,
1855
+ // `self.init` is just an ordinary partial application; it's OK
1856
+ // because there's no associated instance for delegation.
1857
+ if (auto *DRE = dyn_cast<DeclRefExpr>(UDE->getBase ())) {
1858
+ if (auto *baseDecl = DRE->getDecl ()) {
1859
+ if (baseDecl->getBaseName () == cs.getASTContext ().Id_self )
1860
+ return true ;
1861
+ }
1862
+ }
1863
+ }
1864
+
1865
+ return false ;
1866
+ };
1867
+
1868
+ if (!isInvalidIfPartiallyApplied ())
1869
+ return {false ,0 };
1873
1870
1874
1871
// If base is a metatype it would be ignored (unless this is an initializer
1875
1872
// call), but if it is some other type it means that we have a single
1876
1873
// application level already.
1877
- unsigned level = baseTy->is <MetatypeType>() ? 0 : 1 ;
1878
- if (auto *call = dyn_cast_or_null<CallExpr>(cs.getParentExpr (anchor))) {
1879
- level += dyn_cast_or_null<CallExpr>(cs.getParentExpr (call)) ? 2 : 1 ;
1874
+ unsigned level = 0 ;
1875
+ if (!baseTy->is <MetatypeType>())
1876
+ level++;
1877
+
1878
+ if (auto *call = dyn_cast_or_null<CallExpr>(cs.getParentExpr (UDE))) {
1879
+ level += 1 ;
1880
1880
}
1881
1881
1882
1882
return {true , level};
@@ -2357,39 +2357,41 @@ void ConstraintSystem::resolveOverload(ConstraintLocator *locator,
2357
2357
}
2358
2358
}
2359
2359
2360
- // Check whether applying this overload would result in invalid
2361
- // partial function application e.g. partial application of
2362
- // mutating method or initializer.
2363
-
2364
- // This check is supposed to be performed without
2365
- // `shouldAttemptFixes` because name lookup can't
2366
- // detect that particular partial application is
2367
- // invalid, so it has to return all of the candidates.
2368
-
2369
- bool isInvalidPartialApply;
2370
- unsigned level;
2371
-
2372
- std::tie (isInvalidPartialApply, level) =
2373
- isInvalidPartialApplication (*this , decl, locator);
2374
-
2375
- if (isInvalidPartialApply) {
2376
- // No application at all e.g. `Foo.bar`.
2377
- if (level == 0 ) {
2378
- // Swift 4 and earlier failed to diagnose a reference to a mutating
2379
- // method without any applications at all, which would get
2380
- // miscompiled into a function with undefined behavior. Warn for
2381
- // source compatibility.
2382
- bool isWarning = !getASTContext ().isSwiftVersionAtLeast (5 );
2383
- (void )recordFix (
2384
- AllowInvalidPartialApplication::create (isWarning, *this , locator));
2385
- } else if (level == 1 ) {
2386
- // `Self` parameter is applied, e.g. `foo.bar` or `Foo.bar(&foo)`
2387
- (void )recordFix (AllowInvalidPartialApplication::create (
2388
- /* isWarning=*/ false , *this , locator));
2389
- }
2360
+ if (auto *afd = dyn_cast<AbstractFunctionDecl>(decl)) {
2361
+ // Check whether applying this overload would result in invalid
2362
+ // partial function application e.g. partial application of
2363
+ // mutating method or initializer.
2364
+
2365
+ // This check is supposed to be performed without
2366
+ // `shouldAttemptFixes` because name lookup can't
2367
+ // detect that particular partial application is
2368
+ // invalid, so it has to return all of the candidates.
2369
+
2370
+ bool isInvalidPartialApply;
2371
+ unsigned level;
2372
+
2373
+ std::tie (isInvalidPartialApply, level) =
2374
+ isInvalidPartialApplication (*this , afd, locator);
2375
+
2376
+ if (isInvalidPartialApply) {
2377
+ // No application at all e.g. `Foo.bar`.
2378
+ if (level == 0 ) {
2379
+ // Swift 4 and earlier failed to diagnose a reference to a mutating
2380
+ // method without any applications at all, which would get
2381
+ // miscompiled into a function with undefined behavior. Warn for
2382
+ // source compatibility.
2383
+ bool isWarning = !getASTContext ().isSwiftVersionAtLeast (5 );
2384
+ (void )recordFix (
2385
+ AllowInvalidPartialApplication::create (isWarning, *this , locator));
2386
+ } else if (level == 1 ) {
2387
+ // `Self` parameter is applied, e.g. `foo.bar` or `Foo.bar(&foo)`
2388
+ (void )recordFix (AllowInvalidPartialApplication::create (
2389
+ /* isWarning=*/ false , *this , locator));
2390
+ }
2390
2391
2391
- // Otherwise both `Self` and arguments are applied,
2392
- // e.g. `foo.bar()` or `Foo.bar(&foo)()`, and there is nothing to do.
2392
+ // Otherwise both `Self` and arguments are applied,
2393
+ // e.g. `foo.bar()` or `Foo.bar(&foo)()`, and there is nothing to do.
2394
+ }
2393
2395
}
2394
2396
}
2395
2397
0 commit comments