Skip to content

Commit 1e013a0

Browse files
committed
[ConstraintSystem] Move FailureDiagnostic::getFunctionArgApplyInfo
into `ConstraintSystem`.
1 parent ff53718 commit 1e013a0

File tree

5 files changed

+311
-311
lines changed

5 files changed

+311
-311
lines changed

lib/Sema/CSDiagnostics.cpp

Lines changed: 6 additions & 165 deletions
Original file line numberDiff line numberDiff line change
@@ -131,165 +131,6 @@ FailureDiagnostic::getChoiceFor(ConstraintLocator *locator) const {
131131
return getOverloadChoiceIfAvailable(cs.getCalleeLocator(locator));
132132
}
133133

134-
static Type resolveInterfaceType(ConstraintSystem &cs, Type type) {
135-
auto resolvedType = type.transform([&](Type type) -> Type {
136-
if (auto *tvt = type->getAs<TypeVariableType>()) {
137-
// If this type variable is for a generic parameter, return that.
138-
if (auto *gp = tvt->getImpl().getGenericParameter())
139-
return gp;
140-
141-
// Otherwise resolve its fixed type, mapped out of context.
142-
if (auto fixed = cs.getFixedType(tvt))
143-
return resolveInterfaceType(cs, fixed->mapTypeOutOfContext());
144-
145-
return cs.getRepresentative(tvt);
146-
}
147-
if (auto *dmt = type->getAs<DependentMemberType>()) {
148-
// For a dependent member, first resolve the base.
149-
auto newBase = resolveInterfaceType(cs, dmt->getBase());
150-
151-
// Then reconstruct using its associated type.
152-
assert(dmt->getAssocType());
153-
return DependentMemberType::get(newBase, dmt->getAssocType());
154-
}
155-
return type;
156-
});
157-
158-
assert(!resolvedType->hasArchetype());
159-
return resolvedType;
160-
}
161-
162-
/// Given an apply expr, returns true if it is expected to have a direct callee
163-
/// overload, resolvable using `getChoiceFor`. Otherwise, returns false.
164-
static bool shouldHaveDirectCalleeOverload(const CallExpr *callExpr) {
165-
auto *fnExpr = callExpr->getDirectCallee();
166-
167-
// An apply of an apply/subscript doesn't have a direct callee.
168-
if (isa<ApplyExpr>(fnExpr) || isa<SubscriptExpr>(fnExpr))
169-
return false;
170-
171-
// Applies of closures don't have callee overloads.
172-
if (isa<ClosureExpr>(fnExpr))
173-
return false;
174-
175-
// No direct callee for a try!/try?.
176-
if (isa<ForceTryExpr>(fnExpr) || isa<OptionalTryExpr>(fnExpr))
177-
return false;
178-
179-
// If we have an intermediate cast, there's no direct callee.
180-
if (isa<ExplicitCastExpr>(fnExpr))
181-
return false;
182-
183-
// No direct callee for an if expr.
184-
if (isa<IfExpr>(fnExpr))
185-
return false;
186-
187-
// Assume that anything else would have a direct callee.
188-
return true;
189-
}
190-
191-
Optional<FunctionArgApplyInfo>
192-
FailureDiagnostic::getFunctionArgApplyInfo(ConstraintSystem &cs,
193-
ConstraintLocator *locator) {
194-
auto *anchor = locator->getAnchor();
195-
auto path = locator->getPath();
196-
197-
// Look for the apply-arg-to-param element in the locator's path. We may
198-
// have to look through other elements that are generated from an argument
199-
// conversion such as GenericArgument for an optional-to-optional conversion,
200-
// and OptionalPayload for a value-to-optional conversion.
201-
auto iter = path.rbegin();
202-
auto applyArgElt = locator->findLast<LocatorPathElt::ApplyArgToParam>(iter);
203-
if (!applyArgElt)
204-
return None;
205-
206-
auto nextIter = iter + 1;
207-
assert(!locator->findLast<LocatorPathElt::ApplyArgToParam>(nextIter) &&
208-
"Multiple ApplyArgToParam components?");
209-
210-
// Form a new locator that ends at the apply-arg-to-param element, and
211-
// simplify it to get the full argument expression.
212-
auto argPath = path.drop_back(iter - path.rbegin());
213-
auto *argLocator = cs.getConstraintLocator(
214-
anchor, argPath, ConstraintLocator::getSummaryFlagsForPath(argPath));
215-
216-
auto *argExpr = simplifyLocatorToAnchor(argLocator);
217-
218-
// If we were unable to simplify down to the argument expression, we don't
219-
// know what this is.
220-
if (!argExpr)
221-
return None;
222-
223-
Optional<OverloadChoice> choice;
224-
Type rawFnType;
225-
auto *calleeLocator = cs.getCalleeLocator(argLocator);
226-
if (auto overload = cs.findSelectedOverloadFor(calleeLocator)) {
227-
// If we have resolved an overload for the callee, then use that to get the
228-
// function type and callee.
229-
choice = overload->choice;
230-
rawFnType = overload->openedType;
231-
} else {
232-
// If we didn't resolve an overload for the callee, we should be dealing
233-
// with a call of an arbitrary function expr.
234-
if (auto *call = dyn_cast<CallExpr>(anchor)) {
235-
assert(!shouldHaveDirectCalleeOverload(call) &&
236-
"Should we have resolved a callee for this?");
237-
rawFnType = cs.getType(call->getFn());
238-
} else {
239-
// FIXME: ArgumentMismatchFailure is currently used from CSDiag, meaning
240-
// we can end up a BinaryExpr here with an unresolved callee. It should be
241-
// possible to remove this once we've gotten rid of the old CSDiag logic
242-
// and just assert that we have a CallExpr.
243-
auto *apply = cast<ApplyExpr>(anchor);
244-
rawFnType = cs.getType(apply->getFn());
245-
}
246-
}
247-
248-
// Try to resolve the function type by loading lvalues and looking through
249-
// optional types, which can occur for expressions like `fn?(5)`.
250-
auto *fnType = cs.simplifyType(rawFnType)
251-
->getRValueType()
252-
->lookThroughAllOptionalTypes()
253-
->getAs<FunctionType>();
254-
if (!fnType)
255-
return None;
256-
257-
// Resolve the interface type for the function. Note that this may not be a
258-
// function type, for example it could be a generic parameter.
259-
Type fnInterfaceType;
260-
auto *callee = choice ? choice->getDeclOrNull() : nullptr;
261-
if (callee && callee->hasInterfaceType()) {
262-
// If we have a callee with an interface type, we can use it. This is
263-
// preferable to resolveInterfaceType, as this will allow us to get a
264-
// GenericFunctionType for generic decls.
265-
//
266-
// Note that it's possible to find a callee without an interface type. This
267-
// can happen for example with closure parameters, where the interface type
268-
// isn't set until the solution is applied. In that case, use
269-
// resolveInterfaceType.
270-
fnInterfaceType = callee->getInterfaceType();
271-
272-
// Strip off the curried self parameter if necessary.
273-
if (hasAppliedSelf(cs, *choice))
274-
fnInterfaceType = fnInterfaceType->castTo<AnyFunctionType>()->getResult();
275-
276-
if (auto *fn = fnInterfaceType->getAs<AnyFunctionType>()) {
277-
assert(fn->getNumParams() == fnType->getNumParams() &&
278-
"Parameter mismatch?");
279-
(void)fn;
280-
}
281-
} else {
282-
fnInterfaceType = resolveInterfaceType(cs, rawFnType);
283-
}
284-
285-
auto argIdx = applyArgElt->getArgIdx();
286-
auto paramIdx = applyArgElt->getParamIdx();
287-
288-
return FunctionArgApplyInfo(cs, argExpr, argIdx,
289-
cs.simplifyType(cs.getType(argExpr)),
290-
paramIdx, fnInterfaceType, fnType, callee);
291-
}
292-
293134
Type FailureDiagnostic::restoreGenericParameters(
294135
Type type,
295136
llvm::function_ref<void(GenericTypeParamType *, Type)> substitution) {
@@ -930,7 +771,7 @@ bool NoEscapeFuncToTypeConversionFailure::diagnoseParameterUse() const {
930771
// as an argument to another function which accepts @escaping
931772
// function at that position.
932773
auto &cs = getConstraintSystem();
933-
if (auto argApplyInfo = getFunctionArgApplyInfo(cs, getLocator())) {
774+
if (auto argApplyInfo = cs.getFunctionArgApplyInfo(getLocator())) {
934775
auto paramInterfaceTy = argApplyInfo->getParamInterfaceType();
935776
if (paramInterfaceTy->isTypeParameter()) {
936777
auto diagnoseGenericParamFailure = [&](GenericTypeParamDecl *decl) {
@@ -1139,7 +980,7 @@ void MissingOptionalUnwrapFailure::offerDefaultValueUnwrapFixIt(
1139980
return;
1140981

1141982
auto &cs = getConstraintSystem();
1142-
if (auto argApplyInfo = getFunctionArgApplyInfo(cs, getLocator()))
983+
if (auto argApplyInfo = cs.getFunctionArgApplyInfo(getLocator()))
1143984
if (argApplyInfo->getParameterFlags().isInOut())
1144985
return;
1145986

@@ -3802,7 +3643,7 @@ bool MissingArgumentsFailure::diagnoseAsError() {
38023643
// foo(bar) // `() -> Void` vs. `(Int) -> Void`
38033644
// ```
38043645
if (locator->isLastElement<LocatorPathElt::ApplyArgToParam>()) {
3805-
auto info = *getFunctionArgApplyInfo(cs, locator);
3646+
auto info = *(cs.getFunctionArgApplyInfo(locator));
38063647

38073648
auto *argExpr = info.getArgExpr();
38083649
emitDiagnostic(argExpr->getLoc(), diag::cannot_convert_argument_value,
@@ -4018,7 +3859,7 @@ bool MissingArgumentsFailure::diagnoseClosure(ClosureExpr *closure) {
40183859
auto *locator = getLocator();
40193860
if (locator->isForContextualType()) {
40203861
funcType = cs.getContextualType()->getAs<FunctionType>();
4021-
} else if (auto info = getFunctionArgApplyInfo(cs, locator)) {
3862+
} else if (auto info = cs.getFunctionArgApplyInfo(locator)) {
40223863
funcType = info->getParamType()->getAs<FunctionType>();
40233864
} else if (locator->isLastElement<LocatorPathElt::ClosureResult>()) {
40243865
// Based on the locator we know this this is something like this:
@@ -4732,7 +4573,7 @@ SourceLoc InvalidUseOfAddressOf::getLoc() const {
47324573

47334574
bool InvalidUseOfAddressOf::diagnoseAsError() {
47344575
auto &cs = getConstraintSystem();
4735-
if (auto argApplyInfo = getFunctionArgApplyInfo(cs, getLocator())) {
4576+
if (auto argApplyInfo = cs.getFunctionArgApplyInfo(getLocator())) {
47364577
if (!argApplyInfo->getParameterFlags().isInOut()) {
47374578
auto anchor = getAnchor();
47384579
emitDiagnostic(anchor->getLoc(), diag::extra_address_of, getToType())
@@ -5259,7 +5100,7 @@ bool InOutConversionFailure::diagnoseAsError() {
52595100

52605101
if (!path.empty() &&
52615102
path.back().getKind() == ConstraintLocator::FunctionArgument) {
5262-
if (auto argApplyInfo = getFunctionArgApplyInfo(cs, locator)) {
5103+
if (auto argApplyInfo = cs.getFunctionArgApplyInfo(locator)) {
52635104
emitDiagnostic(anchor->getLoc(), diag::cannot_convert_argument_value,
52645105
argApplyInfo->getArgType(), argApplyInfo->getParamType());
52655106
} else {

lib/Sema/CSDiagnostics.h

Lines changed: 1 addition & 144 deletions
Original file line numberDiff line numberDiff line change
@@ -91,13 +91,6 @@ class FailureDiagnostic {
9191
Type getType(Expr *expr, bool wantRValue = true) const;
9292
Type getType(const TypeLoc &loc, bool wantRValue = true) const;
9393

94-
/// For a given locator describing a function argument conversion, or a
95-
/// constraint within an argument conversion, returns information about the
96-
/// application of the argument to its parameter. If the locator is not
97-
/// for an argument conversion, returns \c None.
98-
static Optional<FunctionArgApplyInfo>
99-
getFunctionArgApplyInfo(ConstraintSystem &cs, ConstraintLocator *locator);
100-
10194
/// Resolve type variables present in the raw type, if any.
10295
Type resolveType(Type rawType, bool reconstituteSugar = false,
10396
bool wantRValue = true) const {
@@ -191,142 +184,6 @@ class FailureDiagnostic {
191184
std::pair<Expr *, bool> computeAnchor() const;
192185
};
193186

194-
/// Provides information about the application of a function argument to a
195-
/// parameter.
196-
class FunctionArgApplyInfo {
197-
ConstraintSystem &CS;
198-
Expr *ArgExpr;
199-
unsigned ArgIdx;
200-
Type ArgType;
201-
202-
unsigned ParamIdx;
203-
204-
Type FnInterfaceType;
205-
FunctionType *FnType;
206-
const ValueDecl *Callee;
207-
208-
public:
209-
FunctionArgApplyInfo(ConstraintSystem &cs, Expr *argExpr, unsigned argIdx,
210-
Type argType, unsigned paramIdx, Type fnInterfaceType,
211-
FunctionType *fnType, const ValueDecl *callee)
212-
: CS(cs), ArgExpr(argExpr), ArgIdx(argIdx), ArgType(argType),
213-
ParamIdx(paramIdx), FnInterfaceType(fnInterfaceType), FnType(fnType),
214-
Callee(callee) {}
215-
216-
/// \returns The argument being applied.
217-
Expr *getArgExpr() const { return ArgExpr; }
218-
219-
/// \returns The position of the argument, starting at 1.
220-
unsigned getArgPosition() const { return ArgIdx + 1; }
221-
222-
/// \returns The position of the parameter, starting at 1.
223-
unsigned getParamPosition() const { return ParamIdx + 1; }
224-
225-
/// \returns The type of the argument being applied, including any generic
226-
/// substitutions.
227-
///
228-
/// \param withSpecifier Whether to keep the inout or @lvalue specifier of
229-
/// the argument, if any.
230-
Type getArgType(bool withSpecifier = false) const {
231-
return withSpecifier ? ArgType : ArgType->getWithoutSpecifierType();
232-
}
233-
234-
/// \returns The label for the argument being applied.
235-
Identifier getArgLabel() const {
236-
auto *parent = CS.getParentExpr(ArgExpr);
237-
if (auto *te = dyn_cast<TupleExpr>(parent))
238-
return te->getElementName(ArgIdx);
239-
240-
assert(isa<ParenExpr>(parent));
241-
return Identifier();
242-
}
243-
244-
/// \returns A textual description of the argument suitable for diagnostics.
245-
/// For an argument with an unambiguous label, this will the label. Otherwise
246-
/// it will be its position in the argument list.
247-
StringRef getArgDescription(SmallVectorImpl<char> &scratch) const {
248-
llvm::raw_svector_ostream stream(scratch);
249-
250-
// Use the argument label only if it's unique within the argument list.
251-
auto argLabel = getArgLabel();
252-
auto useArgLabel = [&]() -> bool {
253-
if (argLabel.empty())
254-
return false;
255-
256-
if (auto *te = dyn_cast<TupleExpr>(CS.getParentExpr(ArgExpr)))
257-
return llvm::count(te->getElementNames(), argLabel) == 1;
258-
259-
return false;
260-
};
261-
262-
if (useArgLabel()) {
263-
stream << "'";
264-
stream << argLabel;
265-
stream << "'";
266-
} else {
267-
stream << "#";
268-
stream << getArgPosition();
269-
}
270-
return StringRef(scratch.data(), scratch.size());
271-
}
272-
273-
/// \returns The interface type for the function being applied. Note that this
274-
/// may not a function type, for example it could be a generic parameter.
275-
Type getFnInterfaceType() const { return FnInterfaceType; }
276-
277-
/// \returns The function type being applied, including any generic
278-
/// substitutions.
279-
FunctionType *getFnType() const { return FnType; }
280-
281-
/// \returns The callee for the application.
282-
const ValueDecl *getCallee() const { return Callee; }
283-
284-
private:
285-
Type getParamTypeImpl(AnyFunctionType *fnTy,
286-
bool lookThroughAutoclosure) const {
287-
auto param = fnTy->getParams()[ParamIdx];
288-
auto paramTy = param.getPlainType();
289-
if (lookThroughAutoclosure && param.isAutoClosure())
290-
paramTy = paramTy->castTo<FunctionType>()->getResult();
291-
return paramTy;
292-
}
293-
294-
public:
295-
/// \returns The type of the parameter which the argument is being applied to,
296-
/// including any generic substitutions.
297-
///
298-
/// \param lookThroughAutoclosure Whether an @autoclosure () -> T parameter
299-
/// should be treated as being of type T.
300-
Type getParamType(bool lookThroughAutoclosure = true) const {
301-
return getParamTypeImpl(FnType, lookThroughAutoclosure);
302-
}
303-
304-
/// \returns The interface type of the parameter which the argument is being
305-
/// applied to.
306-
///
307-
/// \param lookThroughAutoclosure Whether an @autoclosure () -> T parameter
308-
/// should be treated as being of type T.
309-
Type getParamInterfaceType(bool lookThroughAutoclosure = true) const {
310-
auto interfaceFnTy = FnInterfaceType->getAs<AnyFunctionType>();
311-
if (!interfaceFnTy) {
312-
// If the interface type isn't a function, then just return the resolved
313-
// parameter type.
314-
return getParamType(lookThroughAutoclosure)->mapTypeOutOfContext();
315-
}
316-
return getParamTypeImpl(interfaceFnTy, lookThroughAutoclosure);
317-
}
318-
319-
/// \returns The flags of the parameter which the argument is being applied
320-
/// to.
321-
ParameterTypeFlags getParameterFlags() const {
322-
return FnType->getParams()[ParamIdx].getParameterFlags();
323-
}
324-
325-
ParameterTypeFlags getParameterFlagsAtIndex(unsigned idx) const {
326-
return FnType->getParams()[idx].getParameterFlags();
327-
}
328-
};
329-
330187
/// Base class for all of the diagnostics related to generic requirement
331188
/// failures, provides common information like failed requirement,
332189
/// declaration where such requirement comes from, etc.
@@ -1816,7 +1673,7 @@ class ArgumentMismatchFailure : public ContextualFailure {
18161673
ArgumentMismatchFailure(ConstraintSystem &cs, Type argType,
18171674
Type paramType, ConstraintLocator *locator)
18181675
: ContextualFailure(cs, argType, paramType, locator),
1819-
Info(getFunctionArgApplyInfo(cs, getLocator())) {}
1676+
Info(cs.getFunctionArgApplyInfo(getLocator())) {}
18201677

18211678
bool diagnoseAsError() override;
18221679
bool diagnoseAsNote() override;

lib/Sema/CSFix.cpp

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -272,8 +272,7 @@ bool AllowTupleTypeMismatch::coalesceAndDiagnose(
272272
return false;
273273
fromType = cs.getType(tupleExpr);
274274
toType = contextualType;
275-
} else if (auto argApplyInfo =
276-
FailureDiagnostic::getFunctionArgApplyInfo(cs, locator)) {
275+
} else if (auto argApplyInfo = cs.getFunctionArgApplyInfo(locator)) {
277276
purpose = CTP_CallArgument;
278277
fromType = argApplyInfo->getArgType();
279278
toType = argApplyInfo->getParamType();

0 commit comments

Comments
 (0)