Skip to content

Commit e28e5be

Browse files
committed
[TypeChecker] Rework type-checking of for-in statements
Change the way how `for-in` statements are type-checked, where a lot of information has to be recorded in a statement in order for SILGen to generate appropriate calls to `makeIterator` and `next` witnesses. Instead of just finding a witness, solver would now: - Synthesize: - Iterator variable with its initializer - `$generator = <sequence>.makeIterator()`; - Call to `$generator.next()` which is called by each loop iteration; - Verify that type of pattern is convertible to type of `next()` Doing so significantly simplifies SILGen, removes the need to carry type information in `ForEachStmt` and enables iterating over existential types. Resolves: rdar://92177656
1 parent 38d3169 commit e28e5be

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

41 files changed

+730
-1044
lines changed

include/swift/AST/Stmt.h

Lines changed: 12 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -743,8 +743,8 @@ class ForEachStmt : public LabeledStmt {
743743

744744
// Set by Sema:
745745
ProtocolConformanceRef sequenceConformance = ProtocolConformanceRef();
746-
VarDecl *iteratorVar = nullptr;
747-
Expr *iteratorVarRef = nullptr;
746+
PatternBindingDecl *iteratorVar = nullptr;
747+
Expr *nextCall = nullptr;
748748
OpaqueValueExpr *elementExpr = nullptr;
749749
Expr *convertElementExpr = nullptr;
750750

@@ -759,11 +759,11 @@ class ForEachStmt : public LabeledStmt {
759759
setPattern(Pat);
760760
}
761761

762-
void setIteratorVar(VarDecl *var) { iteratorVar = var; }
763-
VarDecl *getIteratorVar() const { return iteratorVar; }
762+
void setIteratorVar(PatternBindingDecl *var) { iteratorVar = var; }
763+
PatternBindingDecl *getIteratorVar() const { return iteratorVar; }
764764

765-
void setIteratorVarRef(Expr *var) { iteratorVarRef = var; }
766-
Expr *getIteratorVarRef() const { return iteratorVarRef; }
765+
void setNextCall(Expr *next) { nextCall = next; }
766+
Expr *getNextCall() const { return nextCall; }
767767

768768
void setElementExpr(OpaqueValueExpr *expr) { elementExpr = expr; }
769769
OpaqueValueExpr *getElementExpr() const { return elementExpr; }
@@ -802,8 +802,12 @@ class ForEachStmt : public LabeledStmt {
802802
/// by this foreach loop, as it was written in the source code and
803803
/// subsequently type-checked. To determine the semantic behavior of this
804804
/// expression to extract a range, use \c getRangeInit().
805-
Expr *getSequence() const { return Sequence; }
806-
void setSequence(Expr *S) { Sequence = S; }
805+
Expr *getParsedSequence() const { return Sequence; }
806+
void setParsedSequence(Expr *S) { Sequence = S; }
807+
808+
/// Type-checked version of the sequence or nullptr if this statement
809+
/// yet to be type-checked.
810+
Expr *getTypeCheckedSequence() const;
807811

808812
/// getBody - Retrieve the body of the loop.
809813
BraceStmt *getBody() const { return Body; }

include/swift/Sema/Constraint.h

Lines changed: 8 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -137,11 +137,6 @@ enum class ConstraintKind : char {
137137
/// name, and the type of that member, when referenced as a value, is the
138138
/// second type.
139139
UnresolvedValueMember,
140-
/// The first type conforms to the protocol in which the member requirement
141-
/// resides. Once the conformance is resolved, the value witness will be
142-
/// determined, and the type of that witness, when referenced as a value,
143-
/// will be bound to the second type.
144-
ValueWitness,
145140
/// The first type can be defaulted to the second (which currently
146141
/// cannot be dependent). This is more like a type property than a
147142
/// relational constraint.
@@ -411,18 +406,11 @@ class Constraint final : public llvm::ilist_node<Constraint>,
411406
/// The type of the member.
412407
Type Second;
413408

414-
union {
415-
/// If non-null, the name of a member of the first type is that
416-
/// being related to the second type.
417-
///
418-
/// Used for ValueMember an UnresolvedValueMember constraints.
419-
DeclNameRef Name;
420-
421-
/// If non-null, the member being referenced.
422-
///
423-
/// Used for ValueWitness constraints.
424-
ValueDecl *Ref;
425-
} Member;
409+
/// If non-null, the name of a member of the first type is that
410+
/// being related to the second type.
411+
///
412+
/// Used for ValueMember an UnresolvedValueMember constraints.
413+
DeclNameRef Name;
426414

427415
/// The DC in which the use appears.
428416
DeclContext *UseDC;
@@ -537,12 +525,6 @@ class Constraint final : public llvm::ilist_node<Constraint>,
537525
FunctionRefKind functionRefKind,
538526
ConstraintLocator *locator);
539527

540-
/// Create a new value witness constraint.
541-
static Constraint *createValueWitness(
542-
ConstraintSystem &cs, ConstraintKind kind, Type first, Type second,
543-
ValueDecl *requirement, DeclContext *useDC,
544-
FunctionRefKind functionRefKind, ConstraintLocator *locator);
545-
546528
/// Create an overload-binding constraint.
547529
static Constraint *createBindOverload(ConstraintSystem &cs, Type type,
548530
OverloadChoice choice,
@@ -690,7 +672,6 @@ class Constraint final : public llvm::ilist_node<Constraint>,
690672

691673
case ConstraintKind::ValueMember:
692674
case ConstraintKind::UnresolvedValueMember:
693-
case ConstraintKind::ValueWitness:
694675
case ConstraintKind::PropertyWrapper:
695676
return ConstraintClassification::Member;
696677

@@ -730,7 +711,6 @@ class Constraint final : public llvm::ilist_node<Constraint>,
730711

731712
case ConstraintKind::ValueMember:
732713
case ConstraintKind::UnresolvedValueMember:
733-
case ConstraintKind::ValueWitness:
734714
return Member.First;
735715

736716
case ConstraintKind::SyntacticElement:
@@ -752,7 +732,6 @@ class Constraint final : public llvm::ilist_node<Constraint>,
752732

753733
case ConstraintKind::ValueMember:
754734
case ConstraintKind::UnresolvedValueMember:
755-
case ConstraintKind::ValueWitness:
756735
return Member.Second;
757736

758737
default:
@@ -778,20 +757,13 @@ class Constraint final : public llvm::ilist_node<Constraint>,
778757
DeclNameRef getMember() const {
779758
assert(Kind == ConstraintKind::ValueMember ||
780759
Kind == ConstraintKind::UnresolvedValueMember);
781-
return Member.Member.Name;
782-
}
783-
784-
/// Retrieve the requirement being referenced by a value witness constraint.
785-
ValueDecl *getRequirement() const {
786-
assert(Kind == ConstraintKind::ValueWitness);
787-
return Member.Member.Ref;
760+
return Member.Name;
788761
}
789762

790763
/// Determine the kind of function reference we have for a member reference.
791764
FunctionRefKind getFunctionRefKind() const {
792765
if (Kind == ConstraintKind::ValueMember ||
793-
Kind == ConstraintKind::UnresolvedValueMember ||
794-
Kind == ConstraintKind::ValueWitness)
766+
Kind == ConstraintKind::UnresolvedValueMember)
795767
return static_cast<FunctionRefKind>(TheFunctionRefKind);
796768

797769
// Conservative answer: drop all of the labels.
@@ -851,8 +823,7 @@ class Constraint final : public llvm::ilist_node<Constraint>,
851823
/// Retrieve the DC in which the member was used.
852824
DeclContext *getMemberUseDC() const {
853825
assert(Kind == ConstraintKind::ValueMember ||
854-
Kind == ConstraintKind::UnresolvedValueMember ||
855-
Kind == ConstraintKind::ValueWitness);
826+
Kind == ConstraintKind::UnresolvedValueMember);
856827
return Member.UseDC;
857828
}
858829

0 commit comments

Comments
 (0)