Skip to content

Commit 6aa0ea5

Browse files
authored
Merge pull request #38199 from xedin/rdar-65667992
[ConstraintSystem] Bind missing member in pattern match to a hole early
2 parents e41656d + c1d0036 commit 6aa0ea5

File tree

2 files changed

+50
-4
lines changed

2 files changed

+50
-4
lines changed

lib/Sema/CSSimplify.cpp

Lines changed: 21 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4887,14 +4887,24 @@ bool ConstraintSystem::repairFailures(
48874887
}
48884888

48894889
case ConstraintLocator::PatternMatch: {
4890+
auto *pattern = elt.castTo<LocatorPathElt::PatternMatch>().getPattern();
4891+
bool isMemberMatch =
4892+
lhs->is<FunctionType>() && isa<EnumElementPattern>(pattern);
4893+
4894+
// If member reference couldn't be resolved, let's allow pattern
4895+
// to have holes.
4896+
if (rhs->isPlaceholder() && isMemberMatch) {
4897+
recordAnyTypeVarAsPotentialHole(lhs);
4898+
return true;
4899+
}
4900+
48904901
// If either type is a placeholder, consider this fixed.
48914902
if (lhs->isPlaceholder() || rhs->isPlaceholder())
48924903
return true;
48934904

4894-
// If the left-hand side is a function type and the pattern is an enum
4895-
// element pattern, call it a contextual mismatch.
4896-
auto pattern = elt.castTo<LocatorPathElt::PatternMatch>().getPattern();
4897-
if (lhs->is<FunctionType>() && isa<EnumElementPattern>(pattern)) {
4905+
// If member reference didn't match expected pattern,
4906+
// let's consider that a contextual mismatch.
4907+
if (isMemberMatch) {
48984908
recordAnyTypeVarAsPotentialHole(lhs);
48994909
recordAnyTypeVarAsPotentialHole(rhs);
49004910

@@ -8207,6 +8217,13 @@ ConstraintSystem::SolutionKind ConstraintSystem::simplifyMemberConstraint(
82078217
// `key path` constraint can't be retired until all components
82088218
// are simplified.
82098219
addTypeVariableConstraintsToWorkList(memberTypeVar);
8220+
} else if (locator->isLastElement<LocatorPathElt::PatternMatch>()) {
8221+
// Let's handle member patterns specifically because they use
8222+
// equality instead of argument application constraint, so allowing
8223+
// them to bind member could mean missing valid hole positions in
8224+
// the pattern.
8225+
assignFixedType(memberTypeVar,
8226+
PlaceholderType::get(getASTContext(), memberTypeVar));
82108227
} else {
82118228
recordPotentialHole(memberTypeVar);
82128229
}

test/Constraints/result_builder_diags.swift

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -737,3 +737,32 @@ struct TuplifiedStructWithInvalidClosure {
737737
}
738738
}
739739
}
740+
741+
// rdar://65667992 - invalid case in enum causes fallback diagnostic
742+
func test_rdar65667992() {
743+
@resultBuilder
744+
struct Builder {
745+
static func buildBlock<T>(_ t: T) -> T { t }
746+
static func buildEither<T>(first: T) -> T { first }
747+
static func buildEither<T>(second: T) -> T { second }
748+
}
749+
750+
struct S {}
751+
752+
enum E {
753+
case set(v: Int, choices: [Int])
754+
case notSet(choices: [Int])
755+
}
756+
757+
struct MyView {
758+
var entry: E
759+
760+
@Builder var body: S {
761+
switch entry { // expected-error {{type 'E' has no member 'unset'}}
762+
case .set(_, _): S()
763+
case .unset(_): S()
764+
default: S()
765+
}
766+
}
767+
}
768+
}

0 commit comments

Comments
 (0)