Sema: Result builder inference from dynamically replaced decl should look at getter, not storage

This commit is contained in:
Anthony Latsis
2024-09-26 19:24:48 +03:00
parent daf69f221e
commit 3742da743c
2 changed files with 19 additions and 24 deletions

View File

@@ -321,11 +321,25 @@ static Type inferResultBuilderType(ValueDecl *decl) {
// The set of matches from which we can infer result builder types.
SmallVector<Match, 2> matches;
const auto getInferenceSourceResultBuilderType = [](ValueDecl *source) {
// We always infer for either a getter or freestanding function, so if the
// inference source is a storage declaration, inference should draw from
// the getter.
if (auto *storage = dyn_cast<AbstractStorageDecl>(source)) {
if (auto *getter = storage->getAccessor(AccessorKind::Get)) {
source = getter;
}
}
return source->getResultBuilderType();
};
// Determine all of the conformances within the same context as
// this declaration. If this declaration is a witness to any
// requirement within one of those protocols that has a result builder
// attached, use that result builder type.
auto addConformanceMatches = [&matches](ValueDecl *lookupDecl) {
auto addConformanceMatches = [&matches, &getInferenceSourceResultBuilderType](
ValueDecl *lookupDecl) {
DeclContext *dc = lookupDecl->getDeclContext();
auto idc = cast<IterableDeclContext>(dc->getAsDecl());
auto conformances = idc->getLocalConformances(
@@ -341,22 +355,8 @@ static Type inferResultBuilderType(ValueDecl *decl) {
if (!requirement)
continue;
Type resultBuilderType;
{
auto *inferenceSource = requirement;
// If the given declaration is a witness to a storage declaration
// requirement, then we are inferring for a getter and, hence, should
// infer from the getter requirement.
if (auto *storage = dyn_cast<AbstractStorageDecl>(requirement)) {
if (auto *getter = storage->getAccessor(AccessorKind::Get)) {
inferenceSource = getter;
}
}
resultBuilderType = inferenceSource->getResultBuilderType();
}
const Type resultBuilderType =
getInferenceSourceResultBuilderType(requirement);
if (!resultBuilderType)
continue;
@@ -391,7 +391,8 @@ static Type inferResultBuilderType(ValueDecl *decl) {
// Look for result builder types inferred through dynamic replacements.
if (auto replaced = lookupDecl->getDynamicallyReplacedDecl()) {
if (auto resultBuilderType = replaced->getResultBuilderType()) {
if (auto resultBuilderType =
getInferenceSourceResultBuilderType(replaced)) {
matches.push_back(
Match::forDynamicReplacement(replaced, resultBuilderType));
} else {

View File

@@ -113,13 +113,11 @@ extension Test1 {
var replacement_property1: Result { 1 }
@_dynamicReplacement(for: property2)
var replacement_property2: Result { 1 }
// FIXME: expected-error@-1 {{cannot convert return expression}}
@_dynamicReplacement(for: subscript(subscript1:))
subscript(replacement_subscript1 _: Int) -> Result { 1 }
@_dynamicReplacement(for: subscript(subscript2:))
subscript(replacement_subscript2 _: Int) -> Result { 1 }
// FIXME: expected-error@-1 {{cannot convert return expression}}
}
// Edge case: context is a protocol extension.
@@ -498,7 +496,6 @@ extension Test9 {
@_dynamicReplacement(for: property1)
var replacement_property1: Result { 1 }
// FIXME: expected-error@-1 {{cannot convert value of type 'Int' to expected argument type 'String'}}
@_dynamicReplacement(for: property2)
var replacement_property2: Result { 1 }
@@ -506,7 +503,6 @@ extension Test9 {
subscript(replacement_subscript1 _: Int) -> Result { 1 }
@_dynamicReplacement(for: subscript(subscript2:))
subscript(replacement_subscript2 _: Int) -> Result { 1 }
// FIXME: expected-error@-1 {{cannot convert value of type 'Int' to expected argument type 'String'}}
}
struct Test10: P_Builder_Int1, P_Builder_String {
@@ -648,13 +644,11 @@ extension Test13 {
var replacement_property1: Result { 1 }
@_dynamicReplacement(for: property2)
var replacement_property2: Result { 1 }
// FIXME: expected-error@-1 {{cannot convert return expression}}
@_dynamicReplacement(for: subscript(subscript1:))
subscript(replacement_subscript1 _: Int) -> Result { 1 }
@_dynamicReplacement(for: subscript(subscript2:))
subscript(replacement_subscript2 _: Int) -> Result { 1 }
// FIXME: expected-error@-1 {{cannot convert return expression}}
}
struct Test14: P_Builder_Int1 {