Skip to content

Commit

Permalink
Merge pull request #542 from swiftwasm/master
Browse files Browse the repository at this point in the history
[pull] swiftwasm from master
  • Loading branch information
pull[bot] authored Mar 31, 2020
2 parents f8be843 + 7e359d1 commit 31b9fca
Show file tree
Hide file tree
Showing 5 changed files with 47 additions and 30 deletions.
3 changes: 3 additions & 0 deletions include/swift/AST/DiagnosticsSema.def
Original file line number Diff line number Diff line change
Expand Up @@ -184,6 +184,9 @@ ERROR(value_type_comparison_with_nil_illegal,none,
ERROR(cannot_match_expr_pattern_with_value,none,
"expression pattern of type %0 cannot match values of type %1",
(Type, Type))
ERROR(cannot_match_expr_tuple_pattern_with_nontuple_value,none,
"tuple pattern cannot match values of non-tuple type %0",
(Type))
ERROR(cannot_match_unresolved_expr_pattern_with_value,none,
"pattern cannot match values of type %0",
(Type))
Expand Down
27 changes: 21 additions & 6 deletions lib/Sema/CSDiagnostics.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4865,12 +4865,27 @@ bool CollectionElementContextualFailure::diagnoseAsError() {
}

if (locator->isForSequenceElementType()) {
diagnostic.emplace(
emitDiagnostic(anchor->getLoc(),
contextualType->isExistentialType()
? diag::cannot_convert_sequence_element_protocol
: diag::cannot_convert_sequence_element_value,
eltType, contextualType));
auto &cs = getConstraintSystem();
// If this is a conversion failure related to binding of `for-each`
// statement it has to be diagnosed as pattern match if there are
// holes present in the contextual type.
if (cs.getContextualTypePurpose(anchor) ==
ContextualTypePurpose::CTP_ForEachStmt &&
contextualType->hasHole()) {
diagnostic.emplace(emitDiagnostic(
anchor->getLoc(),
(contextualType->is<TupleType>() && !eltType->is<TupleType>())
? diag::cannot_match_expr_tuple_pattern_with_nontuple_value
: diag::cannot_match_unresolved_expr_pattern_with_value,
eltType));
} else {
diagnostic.emplace(
emitDiagnostic(anchor->getLoc(),
contextualType->isExistentialType()
? diag::cannot_convert_sequence_element_protocol
: diag::cannot_convert_sequence_element_value,
eltType, contextualType));
}
}

if (!diagnostic)
Expand Down
9 changes: 9 additions & 0 deletions lib/Sema/CSSimplify.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3908,6 +3908,15 @@ bool ConstraintSystem::repairFailures(
if (rhs->isExistentialType())
break;

// If the types didn't line up, let's allow right-hand side
// of the conversion (or pattern match) to have holes. This
// helps when conversion if between a type and a tuple e.g.
// `Int` vs. `(_, _)`.
rhs.visit([&](Type type) {
if (auto *typeVar = type->getAs<TypeVariableType>())
recordPotentialHole(typeVar);
});

conversionsOrFixes.push_back(CollectionElementContextualMismatch::create(
*this, lhs, rhs, getConstraintLocator(locator)));
break;
Expand Down
29 changes: 5 additions & 24 deletions test/Prototypes/PatternMatching.swift
Original file line number Diff line number Diff line change
Expand Up @@ -35,15 +35,11 @@ protocol Pattern {

func matched<C: Collection>(atStartOf c: C) -> MatchResult<Index, MatchData>
where C.Index == Index, C.Element == Element
// The following requirements go away with upcoming generics features
, C.SubSequence : Collection
}

extension Pattern {
func found<C: Collection>(in c: C) -> (extent: Range<Index>, data: MatchData)?
where C.Index == Index, C.Element == Element
// The following requirements go away with upcoming generics features
, C.SubSequence : Collection
{
var i = c.startIndex
while i != c.endIndex {
Expand Down Expand Up @@ -72,8 +68,6 @@ where T.Element : Equatable {

func matched<C: Collection>(atStartOf c: C) -> MatchResult<Index, ()>
where C.Index == Index, C.Element == Element
// The following requirements go away with upcoming generics features
, C.SubSequence : Collection
{
var i = c.startIndex
for p in pattern {
Expand All @@ -93,8 +87,6 @@ struct MatchAnyOne<T : Equatable, Index : Comparable> : Pattern {

func matched<C: Collection>(atStartOf c: C) -> MatchResult<Index, ()>
where C.Index == Index, C.Element == Element
// The following requirements go away with upcoming generics features
, C.SubSequence : Collection
{
return c.isEmpty
? .notFound(resumeAt: c.endIndex)
Expand Down Expand Up @@ -126,8 +118,6 @@ where M0.Element == M1.Element, M0.Index == M1.Index {

func matched<C: Collection>(atStartOf c: C) -> MatchResult<Index, MatchData>
where C.Index == Index, C.Element == Element
// The following requirements go away with upcoming generics features
, C.SubSequence : Collection
{
var src0 = c[c.startIndex..<c.endIndex]
while true {
Expand Down Expand Up @@ -166,8 +156,6 @@ struct RepeatMatch<M0: Pattern> : Pattern {

func matched<C: Collection>(atStartOf c: C) -> MatchResult<M0.Index, MatchData>
where C.Index == M0.Index, C.Element == M0.Element
// The following requirements go away with upcoming generics features
, C.SubSequence : Collection
{
var lastEnd = c.startIndex
var rest = c.dropFirst(0)
Expand All @@ -176,11 +164,11 @@ struct RepeatMatch<M0: Pattern> : Pattern {
searchLoop:
while !rest.isEmpty {
switch singlePattern.matched(atStartOf: rest) {
case .found(let x):
data.append(x)
lastEnd = x.end
case .found(let end1, let data1):
data.append((end1, data1))
lastEnd = end1
if data.count == repeatLimits.upperBound { break }
rest = rest[x.end..<rest.endIndex]
rest = rest[end1..<rest.endIndex]
case .notFound(let r):
if !repeatLimits.contains(data.count) {
return .notFound(resumeAt: r)
Expand Down Expand Up @@ -236,8 +224,6 @@ where M0.Element == M1.Element, M0.Index == M1.Index {

func matched<C: Collection>(atStartOf c: C) -> MatchResult<Index, MatchData>
where C.Index == Index, C.Element == Element
// The following requirements go away with upcoming generics features
, C.SubSequence : Collection
{
switch matchers.0.matched(atStartOf: c) {
case .found(let end, let data):
Expand Down Expand Up @@ -292,8 +278,6 @@ struct MatchStaticString : Pattern {

func matched<C: Collection>(atStartOf c: C) -> MatchResult<Index, ()>
where C.Index == Index, C.Element == Element
// The following requirements go away with upcoming generics features
, C.SubSequence : Collection
{
return content.withUTF8Buffer {
LiteralMatch<Buffer, Index>($0).matched(atStartOf: c)
Expand Down Expand Up @@ -327,8 +311,7 @@ extension Pattern where Element == UTF8.CodeUnit {
in c: C,
format: (MatchData)->String = { String(reflecting: $0) })
where C.Index == Index, C.Element == Element
// The following requirements go away with upcoming generics features
, C.SubSequence : Collection {
{
print("searching for /\(self)/ in \(c.u8str)...", terminator: "")
if let (extent, data) = self.found(in: c) {
print(
Expand Down Expand Up @@ -382,8 +365,6 @@ struct Paired<T: Hashable, I: Comparable> : Pattern {

func matched<C: Collection>(atStartOf c: C) -> MatchResult<Index, MatchData>
where C.Index == Index, C.Element == Element
// The following requirements go away with upcoming generics features
, C.SubSequence : Collection
{
guard let closer = c.first.flatMap({ pairs[$0] }) else {
return .notFound(resumeAt: nil)
Expand Down
9 changes: 9 additions & 0 deletions test/stmt/foreach.swift
Original file line number Diff line number Diff line change
Expand Up @@ -220,3 +220,12 @@ extension Int : P { }
func testRepeated(ri: RepeatedSequence<Int>) {
for x in ri { _ = x }
}

// SR-12398: Poor pattern matching diagnostic: "for-in loop requires '[Int]' to conform to 'Sequence'"
func sr_12398(arr1: [Int], arr2: [(a: Int, b: String)]) {
for (x, y) in arr1 {}
// expected-error@-1 {{tuple pattern cannot match values of non-tuple type 'Int'}}

for (x, y, _) in arr2 {}
// expected-error@-1 {{pattern cannot match values of type '(a: Int, b: String)'}}
}

0 comments on commit 31b9fca

Please sign in to comment.