@@ -101,6 +101,35 @@ Expr *FailureDiagnostic::getArgumentExprFor(Expr *anchor) const {
101
101
return nullptr ;
102
102
}
103
103
104
+ // TODO: Replace duplications of this logic with calls to this.
105
+ Optional<SelectedOverload> FailureDiagnostic::getChoiceFor (Expr *expr) {
106
+ auto &cs = getConstraintSystem ();
107
+ ConstraintLocator *locator = nullptr ;
108
+
109
+ if (auto *call = dyn_cast<CallExpr>(expr)) {
110
+ auto *fnExpr = call->getFn ();
111
+ return getChoiceFor (fnExpr);
112
+ } else if (auto *UDE = dyn_cast<UnresolvedDotExpr>(expr)) {
113
+ locator = cs.getConstraintLocator (UDE, ConstraintLocator::Member);
114
+ } else if (auto *UME = dyn_cast<UnresolvedMemberExpr>(expr)) {
115
+ locator = cs.getConstraintLocator (UME, ConstraintLocator::UnresolvedMember);
116
+ } else if (auto *TE = dyn_cast<TypeExpr>(expr)) {
117
+ locator = cs.getConstraintLocator (call,
118
+ {ConstraintLocator::ApplyFunction,
119
+ ConstraintLocator::ConstructorMember},
120
+ /* summaryFlags=*/ 0 );
121
+ } else if (auto *SE = dyn_cast<SubscriptExpr>(expr)) {
122
+ locator = cs.getConstraintLocator (SE, ConstraintLocator::SubscriptMember);
123
+ } else {
124
+ locator = cs.getConstraintLocator (expr);
125
+ }
126
+
127
+ if (!locator)
128
+ return None;
129
+
130
+ return getOverloadChoiceIfAvailable (locator);
131
+ }
132
+
104
133
Type RequirementFailure::getOwnerType () const {
105
134
return getType (getRawAnchor ())
106
135
->getInOutObjectType ()
@@ -2042,42 +2071,43 @@ bool AllowTypeOrInstanceMemberFailure::diagnoseAsError() {
2042
2071
emitDiagnostic (loc, diag::super_initializer_not_in_initializer);
2043
2072
return true ;
2044
2073
}
2074
+
2075
+ auto isInsideCall = [this ](Expr *expr) {
2076
+ auto &cs = getConstraintSystem ();
2077
+ auto argExpr = cs.getParentExpr (expr);
2078
+ if (!argExpr)
2079
+ return false ;
2080
+ auto possibleCallExpr = cs.getParentExpr (expr);
2081
+ return possibleCallExpr && isa<CallExpr>(possibleCallExpr);
2082
+ };
2083
+
2084
+ auto *initCall = cs.getParentExpr (cs.getParentExpr (ctorRef));
2085
+
2086
+ auto isImmutable = [&DC](ValueDecl *decl) {
2087
+ if (auto *storage = dyn_cast<AbstractStorageDecl>(decl))
2088
+ return !storage->isSettable (DC) ||
2089
+ !storage->isSetterAccessibleFrom (DC);
2045
2090
2046
- // Dig through the chain of member accesses until we find the last
2047
- // UnresolvedDotExpr.
2048
- auto *lastUnresolved = ctorRef;
2049
- while (auto *nextMember =
2050
- dyn_cast_or_null<UnresolvedDotExpr>(lastUnresolved->getBase ()))
2051
- lastUnresolved = nextMember;
2052
-
2053
- if (auto *DRE = dyn_cast<DeclRefExpr>(lastUnresolved->getBase ())) {
2054
- auto isInsideCall = [this ](Expr *expr) {
2055
- auto &cs = getConstraintSystem ();
2056
- auto argExpr = cs.getParentExpr (expr);
2057
- if (!argExpr)
2058
- return false ;
2059
- auto possibleCallExpr = cs.getParentExpr (expr);
2060
- return possibleCallExpr && isa<CallExpr>(possibleCallExpr);
2061
- };
2062
-
2063
- auto *initCall = cs.getParentExpr (cs.getParentExpr (ctorRef));
2064
-
2065
- // We can only check if the base is settable here so provide the
2066
- // assignment diagnostic as it's our best guess.
2067
- if (DRE->getDecl ()->isSettable (DC, DRE) && !isInsideCall (initCall) &&
2091
+ return false ;
2092
+ };
2093
+
2094
+ auto selection = getChoiceFor (ctorRef->getBase ());
2095
+ if (selection) {
2096
+ OverloadChoice choice = selection.getValue ().choice ;
2097
+ if (choice.isDecl () && !isImmutable (choice.getDecl ()) && !isInsideCall (initCall) &&
2068
2098
cs.getContextualTypePurpose () == CTP_Unused) {
2069
2099
auto fixItLoc = ctorRef->getBase ()->getSourceRange ().End ;
2070
2100
emitDiagnostic (loc, diag::init_not_instance_member_use_assignment)
2071
2101
.fixItInsertAfter (fixItLoc, " = " );
2072
2102
return true ;
2073
2103
}
2074
- }
2075
2104
2076
- SourceRange fixItRng = ctorRef->getNameLoc ().getSourceRange ();
2077
- emitDiagnostic (loc, diag::init_not_instance_member)
2078
- .fixItInsert (fixItRng.Start , " type(of: " )
2079
- .fixItInsertAfter (fixItRng.End , " )" );
2080
- return true ;
2105
+ SourceRange fixItRng = ctorRef->getNameLoc ().getSourceRange ();
2106
+ emitDiagnostic (loc, diag::init_not_instance_member)
2107
+ .fixItInsert (fixItRng.Start , " type(of: " )
2108
+ .fixItInsertAfter (fixItRng.End , " )" );
2109
+ return true ;
2110
+ }
2081
2111
}
2082
2112
}
2083
2113
0 commit comments