|
14 | 14 | // |
15 | 15 | //===----------------------------------------------------------------------===// |
16 | 16 |
|
17 | | -#include "TypeChecker.h" |
18 | 17 | #include "OpenedExistentials.h" |
| 18 | +#include "TypeChecker.h" |
19 | 19 | #include "swift/AST/ConformanceLookup.h" |
20 | 20 | #include "swift/AST/ExistentialLayout.h" |
| 21 | +#include "swift/AST/Expr.h" |
21 | 22 | #include "swift/AST/GenericSignature.h" |
22 | 23 | #include "swift/Basic/Defer.h" |
23 | 24 | #include "swift/Basic/OptionSet.h" |
|
28 | 29 | #include "llvm/ADT/PointerIntPair.h" |
29 | 30 | #include "llvm/ADT/SmallVector.h" |
30 | 31 | #include "llvm/ADT/TinyPtrVector.h" |
31 | | -#include "llvm/Support/SaveAndRestore.h" |
32 | 32 | #include "llvm/Support/raw_ostream.h" |
33 | 33 | #include <cstddef> |
34 | 34 | #include <functional> |
@@ -709,15 +709,29 @@ static std::optional<DisjunctionInfo> preserveFavoringOfUnlabeledUnaryArgument( |
709 | 709 |
|
710 | 710 | auto *argument = |
711 | 711 | 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 | + |
712 | 724 | // The hack operated on "favored" types and only declaration references, |
713 | 725 | // applications, and (dynamic) subscripts had them if they managed to |
714 | 726 | // 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. |
717 | 730 | if (!(isExpr<DeclRefExpr>(argument) || isExpr<ApplyExpr>(argument) || |
718 | 731 | isExpr<SubscriptExpr>(argument) || |
719 | 732 | isExpr<DynamicSubscriptExpr>(argument) || |
720 | | - isExpr<LiteralExpr>(argument) || isExpr<BinaryExpr>(argument))) |
| 733 | + isExpr<LiteralExpr>(argument) || isExpr<BinaryExpr>(argument) || |
| 734 | + isResolvedMemberReference(argument))) |
721 | 735 | return DisjunctionInfo::none(); |
722 | 736 |
|
723 | 737 | auto argumentType = cs.getType(argument)->getRValueType(); |
|
0 commit comments