Skip to content

Commit 0b38c9b

Browse files
bors[bot]frewsxcv
andauthored
Merge #593
593: Migrate CoordsIter::T to be an associated type. r=michaelkirk a=frewsxcv - [x] I agree to follow the project's [code of conduct](https://github.com/georust/geo/blob/master/CODE_OF_CONDUCT.md). - [x] I added an entry to `CHANGES.md` if knowledge of this change could be valuable to users. --- # Previously With the previous design, this would compile: ```rust impl<'a> CoordsIter<'a, f32> for Polygon<f32> { ... } impl<'a> CoordsIter<'a, f64> for Polygon<f32> { ... } ``` Even though this is not what our implementations actually look like, to the compiler it's possible for there to be multiple implementations of `CoordsIter` for `Polygon<f32>`. This was problematic when [I started rewriting](#592) our `ExtremeIndices` trait to be generic over any type that implements `CoordsIter`: ```rust impl<'a, T, G> ExtremeIndices for G where T: CoordinateType, G: CoordsIter<'a, T>, { fn extreme_indices(&self) -> Result<Extremes, ()> { ... } } ``` This is the compilation error: ``` the type parameter `T` is not constrained by the impl trait, self type, or predicates ``` The issue is that if someone writes this with this new `ExtremeIndices` implementation: ```rust let p: Polygon<f32> = polygon![...]; p.extreme_indices() ``` The compiler doesn't know which implementation to choose: `impl<'a> CoordsIter<'a, f32> for Polygon<f32>` or `impl<'a> CoordsIter<'a, f64> for Polygon<f32>`. So we need a way to tell the compiler we only have _one_ implementation of `CoordsIter` per type. The root issue being that there is a free generic parameter in the `CoordsIter` definition. # Now To fix this, we will move the `T` type parameter to an associated type. Writing this would be a compiler error: ```rust impl<'a> CoordsIter<'a> for Polygon<f32> { type Scalar = f32; ... } impl<'a> CoordsIter<'a> for Polygon<f32> { type Scalar = f64; ... } ``` ``` conflicting implementations of trait `algorithm::coords_iter::CoordsIter<'_>` for type `geo_types::Polygon<f32>` ``` This unblocks #592 Co-authored-by: Corey Farwell <coreyf@rwell.org>
2 parents ea48807 + 5f4cab6 commit 0b38c9b

File tree

2 files changed

+40
-26
lines changed

2 files changed

+40
-26
lines changed

geo/CHANGES.md

+2
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,8 @@
1717
* <https://github.com/georust/geo/pull/584>
1818
* Performance improvements to `simplify`
1919
* <https://github.com/georust/geo/pull/584>
20+
* The `T` generic parameter for `CoordsIter` is now an associated type
21+
* <https://github.com/georust/geo/pull/593>
2022

2123

2224
## 0.16.0

geo/src/algorithm/coords_iter.rs

+38-26
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,9 @@ use std::{fmt, iter, marker, slice};
1010
type CoordinateChainOnce<T> = iter::Chain<iter::Once<Coordinate<T>>, iter::Once<Coordinate<T>>>;
1111

1212
/// Iterate over geometry coordinates.
13-
pub trait CoordsIter<'a, T: CoordinateType> {
14-
type Iter: Iterator<Item = Coordinate<T>>;
13+
pub trait CoordsIter<'a> {
14+
type Iter: Iterator<Item = Coordinate<Self::Scalar>>;
15+
type Scalar: CoordinateType;
1516

1617
/// Iterate over all exterior and (if any) interior coordinates of a geometry.
1718
///
@@ -57,8 +58,9 @@ pub trait CoordsIter<'a, T: CoordinateType> {
5758
// │ Implementation for Point │
5859
// └──────────────────────────┘
5960

60-
impl<'a, T: CoordinateType> CoordsIter<'a, T> for Point<T> {
61+
impl<'a, T: CoordinateType> CoordsIter<'a> for Point<T> {
6162
type Iter = iter::Once<Coordinate<T>>;
63+
type Scalar = T;
6264

6365
fn coords_iter(&'a self) -> Self::Iter {
6466
iter::once(self.0)
@@ -74,8 +76,9 @@ impl<'a, T: CoordinateType> CoordsIter<'a, T> for Point<T> {
7476
// │ Implementation for Line │
7577
// └─────────────────────────┘
7678

77-
impl<'a, T: CoordinateType> CoordsIter<'a, T> for Line<T> {
79+
impl<'a, T: CoordinateType> CoordsIter<'a> for Line<T> {
7880
type Iter = iter::Chain<iter::Once<Coordinate<T>>, iter::Once<Coordinate<T>>>;
81+
type Scalar = T;
7982

8083
fn coords_iter(&'a self) -> Self::Iter {
8184
iter::once(self.start).chain(iter::once(self.end))
@@ -91,8 +94,9 @@ impl<'a, T: CoordinateType> CoordsIter<'a, T> for Line<T> {
9194
// │ Implementation for LineString │
9295
// └───────────────────────────────┘
9396

94-
impl<'a, T: CoordinateType + 'a> CoordsIter<'a, T> for LineString<T> {
97+
impl<'a, T: CoordinateType + 'a> CoordsIter<'a> for LineString<T> {
9598
type Iter = iter::Copied<slice::Iter<'a, Coordinate<T>>>;
99+
type Scalar = T;
96100

97101
fn coords_iter(&'a self) -> Self::Iter {
98102
self.0.iter().copied()
@@ -108,12 +112,13 @@ impl<'a, T: CoordinateType + 'a> CoordsIter<'a, T> for LineString<T> {
108112
// │ Implementation for Polygon │
109113
// └────────────────────────────┘
110114
type PolygonChainIter<'a, T> = iter::Chain<
111-
<LineString<T> as CoordsIter<'a, T>>::Iter,
115+
<LineString<T> as CoordsIter<'a>>::Iter,
112116
iter::Flatten<MapCoordsIter<'a, T, slice::Iter<'a, LineString<T>>, LineString<T>>>,
113117
>;
114118

115-
impl<'a, T: CoordinateType + 'a> CoordsIter<'a, T> for Polygon<T> {
119+
impl<'a, T: CoordinateType + 'a> CoordsIter<'a> for Polygon<T> {
116120
type Iter = PolygonChainIter<'a, T>;
121+
type Scalar = T;
117122

118123
fn coords_iter(&'a self) -> Self::Iter {
119124
self.exterior()
@@ -136,8 +141,9 @@ impl<'a, T: CoordinateType + 'a> CoordsIter<'a, T> for Polygon<T> {
136141
// │ Implementation for MultiPoint │
137142
// └───────────────────────────────┘
138143

139-
impl<'a, T: CoordinateType + 'a> CoordsIter<'a, T> for MultiPoint<T> {
144+
impl<'a, T: CoordinateType + 'a> CoordsIter<'a> for MultiPoint<T> {
140145
type Iter = iter::Flatten<MapCoordsIter<'a, T, slice::Iter<'a, Point<T>>, Point<T>>>;
146+
type Scalar = T;
141147

142148
fn coords_iter(&'a self) -> Self::Iter {
143149
MapCoordsIter(self.0.iter(), marker::PhantomData).flatten()
@@ -153,8 +159,9 @@ impl<'a, T: CoordinateType + 'a> CoordsIter<'a, T> for MultiPoint<T> {
153159
// │ Implementation for MultiLineString │
154160
// └────────────────────────────────────┘
155161

156-
impl<'a, T: CoordinateType + 'a> CoordsIter<'a, T> for MultiLineString<T> {
162+
impl<'a, T: CoordinateType + 'a> CoordsIter<'a> for MultiLineString<T> {
157163
type Iter = iter::Flatten<MapCoordsIter<'a, T, slice::Iter<'a, LineString<T>>, LineString<T>>>;
164+
type Scalar = T;
158165

159166
fn coords_iter(&'a self) -> Self::Iter {
160167
MapCoordsIter(self.0.iter(), marker::PhantomData).flatten()
@@ -173,8 +180,9 @@ impl<'a, T: CoordinateType + 'a> CoordsIter<'a, T> for MultiLineString<T> {
173180
// │ Implementation for MultiPolygon │
174181
// └─────────────────────────────────┘
175182

176-
impl<'a, T: CoordinateType + 'a> CoordsIter<'a, T> for MultiPolygon<T> {
183+
impl<'a, T: CoordinateType + 'a> CoordsIter<'a> for MultiPolygon<T> {
177184
type Iter = iter::Flatten<MapCoordsIter<'a, T, slice::Iter<'a, Polygon<T>>, Polygon<T>>>;
185+
type Scalar = T;
178186

179187
fn coords_iter(&'a self) -> Self::Iter {
180188
MapCoordsIter(self.0.iter(), marker::PhantomData).flatten()
@@ -190,8 +198,9 @@ impl<'a, T: CoordinateType + 'a> CoordsIter<'a, T> for MultiPolygon<T> {
190198
// │ Implementation for GeometryCollection │
191199
// └───────────────────────────────────────┘
192200

193-
impl<'a, T: CoordinateType + 'a> CoordsIter<'a, T> for GeometryCollection<T> {
201+
impl<'a, T: CoordinateType + 'a> CoordsIter<'a> for GeometryCollection<T> {
194202
type Iter = Box<dyn Iterator<Item = Coordinate<T>> + 'a>;
203+
type Scalar = T;
195204

196205
fn coords_iter(&'a self) -> Self::Iter {
197206
Box::new(self.0.iter().flat_map(|geometry| geometry.coords_iter()))
@@ -212,8 +221,9 @@ type RectChainIter<T> = iter::Chain<
212221
iter::Once<Coordinate<T>>,
213222
>;
214223

215-
impl<'a, T: CoordinateType + 'a> CoordsIter<'a, T> for Rect<T> {
224+
impl<'a, T: CoordinateType + 'a> CoordsIter<'a> for Rect<T> {
216225
type Iter = RectChainIter<T>;
226+
type Scalar = T;
217227

218228
fn coords_iter(&'a self) -> Self::Iter {
219229
iter::once(Coordinate {
@@ -247,8 +257,9 @@ impl<'a, T: CoordinateType + 'a> CoordsIter<'a, T> for Rect<T> {
247257
// │ Implementation for Triangle │
248258
// └─────────────────────────────┘
249259

250-
impl<'a, T: CoordinateType + 'a> CoordsIter<'a, T> for Triangle<T> {
260+
impl<'a, T: CoordinateType + 'a> CoordsIter<'a> for Triangle<T> {
251261
type Iter = iter::Chain<CoordinateChainOnce<T>, iter::Once<Coordinate<T>>>;
262+
type Scalar = T;
252263

253264
fn coords_iter(&'a self) -> Self::Iter {
254265
iter::once(self.0)
@@ -266,8 +277,9 @@ impl<'a, T: CoordinateType + 'a> CoordsIter<'a, T> for Triangle<T> {
266277
// │ Implementation for Geometry │
267278
// └─────────────────────────────┘
268279

269-
impl<'a, T: CoordinateType + 'a> CoordsIter<'a, T> for Geometry<T> {
280+
impl<'a, T: CoordinateType + 'a> CoordsIter<'a> for Geometry<T> {
270281
type Iter = GeometryCoordsIter<'a, T>;
282+
type Scalar = T;
271283

272284
fn coords_iter(&'a self) -> Self::Iter {
273285
match self {
@@ -314,10 +326,10 @@ pub struct MapCoordsIter<
314326
'a,
315327
T: 'a + CoordinateType,
316328
Iter1: Iterator<Item = &'a Iter2>,
317-
Iter2: 'a + CoordsIter<'a, T>,
329+
Iter2: 'a + CoordsIter<'a>,
318330
>(Iter1, marker::PhantomData<T>);
319331

320-
impl<'a, T: 'a + CoordinateType, Iter1: Iterator<Item = &'a Iter2>, Iter2: CoordsIter<'a, T>>
332+
impl<'a, T: 'a + CoordinateType, Iter1: Iterator<Item = &'a Iter2>, Iter2: CoordsIter<'a>>
321333
Iterator for MapCoordsIter<'a, T, Iter1, Iter2>
322334
{
323335
type Item = Iter2::Iter;
@@ -330,16 +342,16 @@ impl<'a, T: 'a + CoordinateType, Iter1: Iterator<Item = &'a Iter2>, Iter2: Coord
330342
// Utility to transform Geometry into Iterator<Coordinate>
331343
#[doc(hidden)]
332344
pub enum GeometryCoordsIter<'a, T: CoordinateType + 'a> {
333-
Point(<Point<T> as CoordsIter<'a, T>>::Iter),
334-
Line(<Line<T> as CoordsIter<'a, T>>::Iter),
335-
LineString(<LineString<T> as CoordsIter<'a, T>>::Iter),
336-
Polygon(<Polygon<T> as CoordsIter<'a, T>>::Iter),
337-
MultiPoint(<MultiPoint<T> as CoordsIter<'a, T>>::Iter),
338-
MultiLineString(<MultiLineString<T> as CoordsIter<'a, T>>::Iter),
339-
MultiPolygon(<MultiPolygon<T> as CoordsIter<'a, T>>::Iter),
340-
GeometryCollection(<GeometryCollection<T> as CoordsIter<'a, T>>::Iter),
341-
Rect(<Rect<T> as CoordsIter<'a, T>>::Iter),
342-
Triangle(<Triangle<T> as CoordsIter<'a, T>>::Iter),
345+
Point(<Point<T> as CoordsIter<'a>>::Iter),
346+
Line(<Line<T> as CoordsIter<'a>>::Iter),
347+
LineString(<LineString<T> as CoordsIter<'a>>::Iter),
348+
Polygon(<Polygon<T> as CoordsIter<'a>>::Iter),
349+
MultiPoint(<MultiPoint<T> as CoordsIter<'a>>::Iter),
350+
MultiLineString(<MultiLineString<T> as CoordsIter<'a>>::Iter),
351+
MultiPolygon(<MultiPolygon<T> as CoordsIter<'a>>::Iter),
352+
GeometryCollection(<GeometryCollection<T> as CoordsIter<'a>>::Iter),
353+
Rect(<Rect<T> as CoordsIter<'a>>::Iter),
354+
Triangle(<Triangle<T> as CoordsIter<'a>>::Iter),
343355
}
344356

345357
impl<'a, T: CoordinateType> Iterator for GeometryCoordsIter<'a, T> {

0 commit comments

Comments
 (0)