Dealing with recursive constraints #1216
Replies: 4 comments 14 replies
-
In the interest of completeness, I'll mention that we could get some of the capability back by creating an overloaded slicing subscript on |
Beta Was this translation helpful? Give feedback.
-
If the above technique works, we'll want to think about how to hide from the user the kludgey parts that are only there for the sake of the technique, such as |
Beta Was this translation helpful? Give feedback.
-
@slavapestov points out this Swift example, which illustrates another source of undecidability that doesn't involve recursive constraints. That strongly suggests to me that undecidability is inevitable, and the best we can do is to put computational limits on typechecking. He also points out that the requirements machine can be implemented in a few hundred lines of code so maybe we should just bite the bullet. protocol MyIterator {
associatedtype Element
}
protocol MySequence {
associatedtype Iterator: MyIterator
}
struct ConcreteIterator<Elements: MySequence>: MyIterator {
typealias Element = Elements.Iterator.Element
} The definition of ConcreteIterator creates an implicit inequality constraint, “where Elements.Iterator != Self” because clearly |
Beta Was this translation helpful? Give feedback.
-
FWIW, this is what I get when I do as you suggested and replace S by a generic function with the same signature func h<T>(_ x: T) {
func s<U: Collection>(_: U.Type) where U.Element: Equatable, U.Element == T {}
} The compiler accepts it, which seems perfectly fine to me. If you add the call |
Beta Was this translation helpful? Give feedback.
-
Recursive protocol constraints cause an enormous amount of complexity in Swift. This thread is about how to deal with that. Obviously we could implement Swift's Requirement Machine, which is complex. Maybe there are lighter-weight approaches, that start by banning recursive constraints.
Is this the minimal example that demonstrates a problematic recursive constraint?
or do we need some other constraints on SubSequence in order to have a problem, e.g.
…which is more like Swift's
SubSequence
constraints. In Swift, theSubSequence
type is the result of the slicing operation on a collection.If we want to ban recursive constraints, and the first example is a minimal problematic example, practically speaking, it means that
SubSequence
could not be an associated type. Well, we could make it an associated type with weaker constraints, but I lived in that world for a long time in Swift and the consequences were really ugly.So that means slicing a
C: Collection
must yield some non-associated type; let's call itSlice<C>
:If we just have the above declaration, here's what Swift allows that Hylo would not:
SubSequence
type for a givenCollection
type. For example, slicing aRange<Int>
yields aRange<Int>
instead of something that stores fourInt
s.String
has a customSubSequence
with a smaller start/end index representation when the slicedString
is stored inline.Slice<Slice<Array<Int>>>
, because slicing aSlice<T>
yieldsSlice<T>
.SubSequence
typeX
also has the property thatX.SubSequence == X
.I consider the last of these completely dispensable. My next question would be, how much of the other capabilities can we claw back for Hylo?
Beta Was this translation helpful? Give feedback.
All reactions