File tree Expand file tree Collapse file tree 3 files changed +37
-2
lines changed Expand file tree Collapse file tree 3 files changed +37
-2
lines changed Original file line number Diff line number Diff line change @@ -1929,6 +1929,24 @@ bool TypeVariableBinding::attempt(ConstraintSystem &cs) const {
1929
1929
type = type->reconstituteSugar (/* recursive=*/ false );
1930
1930
}
1931
1931
1932
+ // If type variable has been marked as a possible hole due to
1933
+ // e.g. reference to a missing member. Let's propagate that
1934
+ // information to the object type of the optional type it's
1935
+ // about to be bound to.
1936
+ //
1937
+ // In some situations like pattern bindings e.g. `if let x = base?.member`
1938
+ // - if `member` doesn't exist, `x` cannot be determined either, which
1939
+ // leaves `OptionalEvaluationExpr` representing outer type of `base?.member`
1940
+ // without any contextual information, so even though `x` would get
1941
+ // bound to result type of the chain, underlying type variable wouldn't
1942
+ // be resolved, so we need to propagate holes up the conversion chain.
1943
+ if (TypeVar->getImpl ().canBindToHole ()) {
1944
+ if (auto objectTy = type->getOptionalObjectType ()) {
1945
+ if (auto *typeVar = objectTy->getAs <TypeVariableType>())
1946
+ cs.recordPotentialHole (typeVar);
1947
+ }
1948
+ }
1949
+
1932
1950
ConstraintSystem::TypeMatchOptions options;
1933
1951
1934
1952
options |= ConstraintSystem::TMF_GenerateConstraints;
Original file line number Diff line number Diff line change @@ -797,3 +797,21 @@ func test_weak_with_nonoptional_type() {
797
797
42
798
798
}
799
799
}
800
+
801
+ // rdar://80941497 - compiler fails to produce diagnostic when referencing missing member in optional context
802
+ func test_missing_member_in_optional_context( ) {
803
+ struct Test {
804
+ }
805
+
806
+ var test : Test ? = nil
807
+
808
+ tuplify ( true ) { c in
809
+ if let prop = test? . prop { // expected-error {{value of type 'Test' has no member 'prop'}}
810
+ 0
811
+ }
812
+
813
+ if let method = test? . method ( ) { // expected-error {{value of type 'Test' has no member 'method'}}
814
+ 1
815
+ }
816
+ }
817
+ }
Original file line number Diff line number Diff line change @@ -1089,8 +1089,7 @@ func rdar74711236() {
1089
1089
var s = S ( )
1090
1090
1091
1091
s. arr = {
1092
- // FIXME: Missing member reference is pattern needs a better diagnostic
1093
- if let type = context? . store { // expected-error {{type of expression is ambiguous without more context}}
1092
+ if let type = context? . store { // expected-error {{value of type 'Context' has no member 'store'}}
1094
1093
// `isSupported` should be an invalid declaration to trigger a crash in `map(\.option)`
1095
1094
let isSupported = context!. supported ( ) . contains ( type)
1096
1095
return ( isSupported ? [ type] : [ ] ) . map ( \. option)
You can’t perform that action at this time.
0 commit comments