Skip to content

Commit ca0491a

Browse files
authored
Merge pull request #85151 from xedin/rdar-161419917
[CSOptimizer] Update unary call favoring to include resolved member r…
2 parents 373cbe9 + e1a6077 commit ca0491a

File tree

3 files changed

+47
-6
lines changed

3 files changed

+47
-6
lines changed

lib/Sema/CSOptimizer.cpp

Lines changed: 19 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -14,10 +14,11 @@
1414
//
1515
//===----------------------------------------------------------------------===//
1616

17-
#include "TypeChecker.h"
1817
#include "OpenedExistentials.h"
18+
#include "TypeChecker.h"
1919
#include "swift/AST/ConformanceLookup.h"
2020
#include "swift/AST/ExistentialLayout.h"
21+
#include "swift/AST/Expr.h"
2122
#include "swift/AST/GenericSignature.h"
2223
#include "swift/Basic/Defer.h"
2324
#include "swift/Basic/OptionSet.h"
@@ -28,7 +29,6 @@
2829
#include "llvm/ADT/PointerIntPair.h"
2930
#include "llvm/ADT/SmallVector.h"
3031
#include "llvm/ADT/TinyPtrVector.h"
31-
#include "llvm/Support/SaveAndRestore.h"
3232
#include "llvm/Support/raw_ostream.h"
3333
#include <cstddef>
3434
#include <functional>
@@ -709,15 +709,29 @@ static std::optional<DisjunctionInfo> preserveFavoringOfUnlabeledUnaryArgument(
709709

710710
auto *argument =
711711
argumentList->getUnlabeledUnaryExpr()->getSemanticsProvidingExpr();
712+
713+
// If the type associated with a member expression doesn't have any type
714+
// variables it means that it was resolved during pre-check to a single
715+
// declaration.
716+
//
717+
// This helps in situations like `Double(x)` where `x` is a property of some
718+
// type that is referenced using an implicit `self.` injected by the compiler.
719+
auto isResolvedMemberReference = [&cs](Expr *expr) -> bool {
720+
auto *UDE = dyn_cast<UnresolvedDotExpr>(expr);
721+
return UDE && !cs.getType(UDE)->hasTypeVariable();
722+
};
723+
712724
// The hack operated on "favored" types and only declaration references,
713725
// applications, and (dynamic) subscripts had them if they managed to
714726
// get an overload choice selected during constraint generation.
715-
// It's sometimes possible to infer a type of a literal and an operator
716-
// chain, so it should be allowed as well.
727+
//
728+
// It's sometimes possible to infer a type of a literal, an operator
729+
// chain, and a member, so it should be allowed as well.
717730
if (!(isExpr<DeclRefExpr>(argument) || isExpr<ApplyExpr>(argument) ||
718731
isExpr<SubscriptExpr>(argument) ||
719732
isExpr<DynamicSubscriptExpr>(argument) ||
720-
isExpr<LiteralExpr>(argument) || isExpr<BinaryExpr>(argument)))
733+
isExpr<LiteralExpr>(argument) || isExpr<BinaryExpr>(argument) ||
734+
isResolvedMemberReference(argument)))
721735
return DisjunctionInfo::none();
722736

723737
auto argumentType = cs.getType(argument)->getRValueType();

test/Constraints/old_hack_related_ambiguities.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -160,8 +160,8 @@ do {
160160
var p: UnsafeMutableRawPointer { get { fatalError() } }
161161

162162
func f(_ p: UnsafeMutableRawPointer) {
163-
// The old hack (which is now removed) couldn't handle member references, only direct declaration references.
164163
guard let x = UnsafeMutablePointer<Double>(OpaquePointer(self.p)) else {
164+
// expected-error@-1 {{initializer for conditional binding must have Optional type, not 'UnsafeMutablePointer<Double>'}}
165165
return
166166
}
167167
_ = x
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
// RUN: %scale-test --begin 1 --end 16 --step 1 --select NumLeafScopes %s
2+
// REQUIRES: asserts,no_asan
3+
4+
// There was a performance hack that handled calls with a single unlabeled argument
5+
// in a very specific way. For source compatibility reasons old behavior has to be
6+
// preserved in the disjunction optimizer as well, but the old hack missed a case
7+
// where a type of a member is known in advance (i.e. a property without overloads)
8+
// because there as another hack (shrink) for that. This test makes sure that
9+
// performance for such cases won't regress in the future.
10+
11+
struct Test {
12+
var v = 0
13+
14+
func test() {
15+
let _ = 1.0 * (
16+
1.0 * Double(v) +
17+
%for i in range(1, N):
18+
%if i % 2 == 0:
19+
1.0 * Double(v) +
20+
%else:
21+
1.0 * Double(self.v) +
22+
%end
23+
%end
24+
1.0 * Double(v)
25+
)
26+
}
27+
}

0 commit comments

Comments
 (0)