TL; DR: в заявлении match
возможно ли явно обрабатывать enum
варианты, которые могут не существовать? (из-за различных версий внешней библиотеки)
Я пишу код для библиотеки, которая использует оператор match
для обработки преобразования объекта из другой библиотеки.
Этот объект приходит из библиотеки geo-types
, где geo_types::Geometry
может представлять один из нескольких типов объектов:
pub enum Geometry<T>
where
T: CoordinateType,
{
Point(Point<T>),
Line(Line<T>),
LineString(LineString<T>),
Polygon(Polygon<T>),
[...]
}
(каждая из этих структур определена в другом месте в geo-types
)
Это другая библиотека (shapefile
) реализует черту TryFrom
для преобразования определенных geo_types::Geometry
вариантов в варианты собственного shapefile::Shape
библиотеки, которое является аналогичным перечислением:
pub enum Shape {
Point(Point),
Polyline(Polyline),
Polygon(Polygon),
[...]
}
Преобразование выполнено в других типажах, поэтому функция try_from()
в основном пытается сопоставить совместимые варианты каждого перечисления в блоке сопоставления. Каждый возможный вариант geo_types::Geometry
явно сопоставляется с вариантом Shape
.
match geometry {
geo_types::Geometry::Point(point) => Ok(Shape::Point(point.into())),
geo_types::Geometry::Line(line) => Ok(Shape::Line(line.into())),
[...]
}
Но в версии 0.6.0 из geo-types
добавлено 2 новых варианта перечисления Geometry
: Rect
и Triangle
. Этот оператор match
теперь не будет компилироваться:
error[E0004]: non-exhaustive patterns: `Rect(_)` and `Triangle(_)` not covered
--> src/record/mod.rs:464:15
|
464 | match geometry {
| ^^^^^^^^ patterns `Rect(_)` and `Triangle(_)` not covered
|
::: /home/roger/.cargo/registry/src/github.com-1ecc6299db9ec823/geo-types-0.6.0/src/geometry.rs:39:5
|
39 | Rect(Rect<T>),
| ---- not covered
40 | Triangle(Triangle<T>),
| -------- not covered
|
= help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
= note: the matched value is of type `geo_types::Geometry<f64>`
Я не могу обработать их явно, иначе я нарушу совместимость со старыми версиями geo-types
:
error[E0599]: no variant or associated item named `Rect` found for enum `geo_types::Geometry<_>` in the current scope
--> src/record/mod.rs:479:34
|
479 | geo_types::Geometry::Rect(_) => {
| ^^^^ variant or associated item not found in `geo_types::Geometry<_>`
I может выполнять подстановочный знак _ => { Err("Unrecognized Geometry") }
, который компилируется как для новой, так и для старой версии geo-types
, хотя выдает предупреждение, если вы пытаетесь скомпилировать более старую версию geo-types
:
warning: unreachable pattern
--> src/record/mod.rs:480:13
|
480 | _ => { // New geometries Rect(_) and Triangle(_) added in 0.6.0
| ^
|
= note: `#[warn(unreachable_patterns)]` on by default
Но я могу аннотировать #[allow(unreachable_patterns)]
. На данный момент это работает, но подавление предупреждения кажется неприятным запахом кода. Кроме того, похоже, что для реализации преобразования Rect
или Triangle
потребуется нарушение совместимости с некоторыми версиями geo-types
(что, в свою очередь, нарушает совместимость с другими библиотеками geographi c, которые полагаются на geo-types
).
Есть ли способ дополнительно обработать эти новые варианты перечисления способом, который не зависит от их существования?