Skip to content

Commit a30cf9c

Browse files
authored
Merge pull request #33174 from hborla/5.3-function-builder-body-result-diags
[5.3][Function Builders] Teach diagnostics about function builder body result types...
2 parents 50db6e4 + 026b51b commit a30cf9c

File tree

7 files changed

+58
-1
lines changed

7 files changed

+58
-1
lines changed

lib/Sema/BuilderTransform.cpp

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1583,8 +1583,12 @@ ConstraintSystem::matchFunctionBuilder(
15831583
// If builder is applied to the closure expression then
15841584
// `closure body` to `closure result` matching should
15851585
// use special locator.
1586-
if (auto *closure = fn.getAbstractClosureExpr())
1586+
if (auto *closure = fn.getAbstractClosureExpr()) {
15871587
locator = getConstraintLocator(closure, ConstraintLocator::ClosureResult);
1588+
} else {
1589+
locator = getConstraintLocator(locator.getAnchor(),
1590+
ConstraintLocator::FunctionBuilderBodyResult);
1591+
}
15881592

15891593
// Bind the body result type to the type of the transformed expression.
15901594
addConstraint(bodyResultConstraintKind, transformedType, bodyResultType,

lib/Sema/CSDiagnostics.cpp

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -176,6 +176,13 @@ Type FailureDiagnostic::restoreGenericParameters(
176176
});
177177
}
178178

179+
SourceLoc RequirementFailure::getLoc() const {
180+
if (getLocator()->isForFunctionBuilderBodyResult())
181+
return getConstraintSystem().DC->getAsDecl()->getLoc();
182+
183+
return FailureDiagnostic::getLoc();
184+
}
185+
179186
Type RequirementFailure::getOwnerType() const {
180187
auto anchor = getRawAnchor();
181188

@@ -250,6 +257,14 @@ ValueDecl *RequirementFailure::getDeclRef() const {
250257
return type->getAnyGeneric();
251258
};
252259

260+
// If the locator is for a function builder body result type, the requirement
261+
// came from the function's return type.
262+
if (getLocator()->isForFunctionBuilderBodyResult()) {
263+
auto *func = dyn_cast<FuncDecl>(getConstraintSystem().DC->getAsDecl());
264+
assert(getSolution().functionBuilderTransformed.count(func));
265+
return getAffectedDeclFromType(func->getResultInterfaceType());
266+
}
267+
253268
if (isFromContextualType())
254269
return getAffectedDeclFromType(getContextualType(getRawAnchor()));
255270

lib/Sema/CSDiagnostics.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -269,6 +269,8 @@ class RequirementFailure : public FailureDiagnostic {
269269
Apply = dyn_cast<ApplyExpr>(parentExpr);
270270
}
271271

272+
SourceLoc getLoc() const override;
273+
272274
unsigned getRequirementIndex() const {
273275
auto reqElt =
274276
getLocator()->castLastElementTo<LocatorPathElt::AnyRequirement>();

lib/Sema/ConstraintLocator.cpp

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,7 @@ unsigned LocatorPathElt::getNewSummaryFlags() const {
9090
case ConstraintLocator::ClosureResult:
9191
case ConstraintLocator::ClosureBody:
9292
case ConstraintLocator::ConstructorMember:
93+
case ConstraintLocator::FunctionBuilderBodyResult:
9394
case ConstraintLocator::InstanceType:
9495
case ConstraintLocator::AutoclosureResult:
9596
case ConstraintLocator::OptionalPayload:
@@ -247,6 +248,10 @@ bool ConstraintLocator::isForOptionalTry() const {
247248
return directlyAt<OptionalTryExpr>();
248249
}
249250

251+
bool ConstraintLocator::isForFunctionBuilderBodyResult() const {
252+
return isFirstElement<LocatorPathElt::FunctionBuilderBodyResult>();
253+
}
254+
250255
GenericTypeParamType *ConstraintLocator::getGenericParameter() const {
251256
// Check whether we have a path that terminates at a generic parameter.
252257
return isForGenericParameter() ?
@@ -345,6 +350,10 @@ void ConstraintLocator::dump(SourceManager *sm, raw_ostream &out) const {
345350
out << "function result";
346351
break;
347352

353+
case FunctionBuilderBodyResult:
354+
out << "function builder body result";
355+
break;
356+
348357
case SequenceElementType:
349358
out << "sequence element type";
350359
break;

lib/Sema/ConstraintLocator.h

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -375,12 +375,23 @@ class ConstraintLocator : public llvm::FoldingSetNode {
375375
/// Determine whether this locator points to the `try?` expression.
376376
bool isForOptionalTry() const;
377377

378+
/// Determine whether this locator is for a function builder body result type.
379+
bool isForFunctionBuilderBodyResult() const;
380+
378381
/// Determine whether this locator points directly to a given expression.
379382
template <class E> bool directlyAt() const {
380383
auto *anchor = getAnchor();
381384
return anchor && isa<E>(anchor) && getPath().empty();
382385
}
383386

387+
/// Check whether the first element in the path of this locator (if any)
388+
/// is a given \c LocatorPathElt subclass.
389+
template <class T>
390+
bool isFirstElement() const {
391+
auto path = getPath();
392+
return !path.empty() && path.front().is<T>();
393+
}
394+
384395
/// Attempts to cast the first path element of the locator to a specific
385396
/// \c LocatorPathElt subclass, returning \c None if either unsuccessful or
386397
/// the locator has no path elements.

lib/Sema/ConstraintLocatorPathElts.def

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,9 @@ SIMPLE_LOCATOR_PATH_ELT(FunctionArgument)
7575
/// The result type of a function.
7676
SIMPLE_LOCATOR_PATH_ELT(FunctionResult)
7777

78+
/// The result type of a function builder body.
79+
SIMPLE_LOCATOR_PATH_ELT(FunctionBuilderBodyResult)
80+
7881
/// A generic argument.
7982
/// FIXME: Add support for named generic arguments?
8083
CUSTOM_LOCATOR_PATH_ELT(GenericArgument)

test/Constraints/function_builder_diags.swift

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -572,3 +572,16 @@ wrapperifyInfer(true) { x in // expected-error{{unable to infer type of a closur
572572
intValue + x
573573
}
574574

575+
struct DoesNotConform {}
576+
577+
struct MyView {
578+
@TupleBuilder var value: some P { // expected-error {{return type of property 'value' requires that 'DoesNotConform' conform to 'P'}}
579+
// expected-note@-1 {{opaque return type declared here}}
580+
DoesNotConform()
581+
}
582+
583+
@TupleBuilder func test() -> some P { // expected-error {{return type of instance method 'test()' requires that 'DoesNotConform' conform to 'P'}}
584+
// expected-note@-1 {{opaque return type declared here}}
585+
DoesNotConform()
586+
}
587+
}

0 commit comments

Comments
 (0)