Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
41 changes: 29 additions & 12 deletions lib/Sema/CSGen.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2315,7 +2315,8 @@ namespace {
cast<TypedPattern>(pattern)->getSubPattern(), locator,
Type(), bindPatternVarsOneWay);
CS.addConstraint(
ConstraintKind::Conversion, subPatternType, openedType, locator);
ConstraintKind::Conversion, subPatternType, openedType,
locator.withPathElement(LocatorPathElt::PatternMatch(pattern)));
return setType(openedType);
}

Expand Down Expand Up @@ -2352,7 +2353,7 @@ namespace {

Type eltTy = getTypeForPattern(
tupleElt.getPattern(),
locator.withPathElement(LocatorPathElt::TupleElement(i)),
locator,
externalEltType,
bindPatternVarsOneWay);
tupleTypeElts.push_back(TupleTypeElt(eltTy, tupleElt.getLabel()));
Expand All @@ -2368,7 +2369,8 @@ namespace {
CS.getConstraintLocator(locator), TVO_CanBindToNoEscape);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think in this case we should have locator with points to pattern and ends with OptionalPayload.

CS.addConstraint(
ConstraintKind::OptionalObject, externalPatternType,
objVar, locator);
objVar,
locator.withPathElement(LocatorPathElt::PatternMatch(pattern)));

externalPatternType = objVar;
}
Expand All @@ -2386,7 +2388,9 @@ namespace {

Type castType =
resolveTypeReferenceInExpression(isPattern->getCastTypeLoc());
castType = CS.openUnboundGenericType(castType, locator);
castType = CS.openUnboundGenericType(
castType,
locator.withPathElement(LocatorPathElt::PatternMatch(pattern)));

Type subPatternType =
getTypeForPattern(isPattern->getSubPattern(), locator, castType,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think subPattern should have locator point to a sub-pattern used by a cast?

Expand All @@ -2395,7 +2399,8 @@ namespace {
// Make sure we can cast from the subpattern type to the type we're
// checking; if it's impossible, fail.
CS.addConstraint(
ConstraintKind::CheckedCast, subPatternType, castType, locator);
ConstraintKind::CheckedCast, subPatternType, castType,
locator.withPathElement(LocatorPathElt::PatternMatch(pattern)));

return setType(subPatternType);
}
Expand All @@ -2422,7 +2427,9 @@ namespace {
// Resolve the parent type.
Type parentType =
resolveTypeReferenceInExpression(enumPattern->getParentType());
parentType = CS.openUnboundGenericType(parentType, locator);
parentType = CS.openUnboundGenericType(
parentType,
locator.withPathElement(LocatorPathElt::PatternMatch(pattern)));
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we could use ParentType locator element for this transformation.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Later one where we add a member constraint I think it should either end on regular Member locator or a new one specific for patterns...


// Perform member lookup into the parent's metatype.
Type parentMetaType = MetatypeType::get(parentType);
Expand All @@ -2433,8 +2440,9 @@ namespace {

// Parent type needs to be convertible to the pattern type; this
// accounts for cases where the pattern type is existential.
CS.addConstraint(ConstraintKind::Conversion, parentType, patternType,
locator);
CS.addConstraint(
ConstraintKind::Conversion, parentType, patternType,
locator.withPathElement(LocatorPathElt::PatternMatch(pattern)));

baseType = parentType;
} else {
Expand Down Expand Up @@ -2470,8 +2478,9 @@ namespace {
ConstraintKind::Equal, functionType, memberType,
locator.withPathElement(LocatorPathElt::PatternMatch(pattern)));

CS.addConstraint(ConstraintKind::Conversion, outputType, baseType,
locator);
CS.addConstraint(
ConstraintKind::Conversion, outputType, baseType,
locator.withPathElement(LocatorPathElt::PatternMatch(pattern)));
}

return setType(patternType);
Expand Down Expand Up @@ -4265,10 +4274,18 @@ bool ConstraintSystem::generateConstraints(
// For any pattern variable that has a parent variable (i.e., another
// pattern variable with the same name in the same case), require that
// the types be equivalent.
pattern->forEachVariable([&](VarDecl *var) {
pattern->forEachNode([&](Pattern *pattern) {
auto namedPattern = dyn_cast<NamedPattern>(pattern);
if (!namedPattern)
return;

auto var = namedPattern->getDecl();
if (auto parentVar = var->getParentVarDecl()) {
addConstraint(
ConstraintKind::Equal, getType(parentVar), getType(var), locator);
ConstraintKind::Equal, getType(parentVar), getType(var),
getConstraintLocator(
locator,
LocatorPathElt::PatternMatch(namedPattern)));
}
});
}
Expand Down
14 changes: 14 additions & 0 deletions test/Constraints/function_builder_diags.swift
Original file line number Diff line number Diff line change
Expand Up @@ -466,3 +466,17 @@ func testCaseMutabilityMismatches(e: E3) {
}
}
}

// Check for type equivalence among different case variables with the same name.
func testCaseVarTypes(e: E3) {
// FIXME: Terrible diagnostic
tuplify(true) { c in // expected-error{{type of expression is ambiguous without more context}}
"testSwitch"
switch e {
case .a(let x, let y),
.c(let x, let y):
x
y + "a"
}
}
}