mirror of
https://github.com/apple/swift.git
synced 2025-12-14 20:36:38 +01:00
Sema: Result builder inference from dynamically replaced decl should look at getter, not storage
This commit is contained in:
@@ -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 {
|
||||
|
||||
@@ -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 {
|
||||
|
||||
Reference in New Issue
Block a user