From ec6fe74682bb289d8e494f69bc71b867c03054f4 Mon Sep 17 00:00:00 2001 From: Mieszko Grodzicki Date: Sun, 1 Jan 2023 19:32:55 +0100 Subject: [PATCH 01/14] Extract choosing baseline version --- src/baseline.rs | 61 ++++++++++++++++++++++++++++++------------------- 1 file changed, 38 insertions(+), 23 deletions(-) diff --git a/src/baseline.rs b/src/baseline.rs index ba58ef62..00b192c6 100644 --- a/src/baseline.rs +++ b/src/baseline.rs @@ -1,4 +1,5 @@ use anyhow::Context as _; +use crates_index::Crate; use crate::dump::RustDocCommand; use crate::util::slugify; @@ -242,6 +243,42 @@ fn create_rustdoc_manifest_for_crate_version( } } +fn choose_baseline_version( + crate_: &Crate, + version_current: Option<&semver::Version>, +) -> anyhow::Result { + if let Some(current) = version_current { + let mut instances = crate_ + .versions() + .iter() + .filter_map(|i| semver::Version::parse(i.version()).ok()) + // For unpublished changes when the user doesn't increment the version + // post-release, allow using the current version as a baseline. + .filter(|v| v <= current) + .collect::>(); + instances.sort(); + instances + .iter() + .rev() + .find(|v| v.pre.is_empty()) + .or_else(|| instances.last()) + .map(|v| v.to_string()) + .with_context(|| { + anyhow::format_err!( + "No available baseline versions for {}@{}", + crate_.name(), + current + ) + }) + } else { + let instance = crate_ + .highest_normal_version() + .unwrap_or_else(|| crate_.highest_version()) + .version(); + Ok(instance.to_owned()) + } +} + impl BaselineLoader for RegistryBaseline { fn load_rustdoc( &self, @@ -259,30 +296,8 @@ impl BaselineLoader for RegistryBaseline { // - Most likely the user cares about the last official release let base_version = if let Some(base) = self.version.as_ref() { base.to_string() - } else if let Some(current) = version_current { - let mut instances = crate_ - .versions() - .iter() - .filter_map(|i| semver::Version::parse(i.version()).ok()) - // For unpublished changes when the user doesn't increment the version - // post-release, allow using the current version as a baseline. - .filter(|v| v <= current) - .collect::>(); - instances.sort(); - let instance = instances - .iter() - .rev() - .find(|v| v.pre.is_empty()) - .or_else(|| instances.last()) - .with_context(|| { - anyhow::format_err!("No available baseline versions for {}@{}", name, current) - })?; - instance.to_string() } else { - let instance = crate_ - .highest_normal_version() - .unwrap_or_else(|| crate_.highest_version()); - instance.version().to_owned() + choose_baseline_version(&crate_, version_current)? }; let base_root = self.target_root.join(format!( From 3f3c58313b4725f72f9c57945d584846c4e8a0a5 Mon Sep 17 00:00:00 2001 From: Mieszko Grodzicki Date: Sun, 1 Jan 2023 19:38:26 +0100 Subject: [PATCH 02/14] Stop choosing yanked versions, add tests --- src/baseline.rs | 37 +++++++++++++++++++++++++++++++++++++ 1 file changed, 37 insertions(+) diff --git a/src/baseline.rs b/src/baseline.rs index 00b192c6..e4fc81de 100644 --- a/src/baseline.rs +++ b/src/baseline.rs @@ -251,6 +251,7 @@ fn choose_baseline_version( let mut instances = crate_ .versions() .iter() + .filter(|i| !i.is_yanked()) .filter_map(|i| semver::Version::parse(i.version()).ok()) // For unpublished changes when the user doesn't increment the version // post-release, allow using the current version as a baseline. @@ -355,3 +356,39 @@ fn need_retry(res: Result<(), crates_index::Error>) -> anyhow::Result { Err(err) => Err(err.into()), } } + +#[cfg(test)] +mod tests { + use crates_index::{Crate, Version}; + + use super::choose_baseline_version; + + fn new_mock_version(version_name: &str, yanked: bool) -> Version { + serde_json::from_value(serde_json::json!({ + "name": "test-crate", + "vers": version_name, + "deps": [], + "features": {}, + "yanked": yanked, + "cksum": "00".repeat(32), + })) + .unwrap() + } + + fn new_crate(versions: &[Version]) -> Crate { + serde_json::from_value(serde_json::json!({ "versions": versions })).unwrap() + } + + #[test] + fn choose_baseline_version_yanked() { + let crate_ = new_crate(&[ + new_mock_version("1.2.0", false), + new_mock_version("1.2.1", true), + ]); + let current_version = semver::Version::new(1, 2, 2); + assert_eq!( + choose_baseline_version(&crate_, Some(¤t_version)).unwrap(), + "1.2.0".to_string() + ); + } +} From edcbf0ad8d658f59643b9d8796a4e9c856702119 Mon Sep 17 00:00:00 2001 From: Mieszko Grodzicki Date: Sun, 1 Jan 2023 20:01:12 +0100 Subject: [PATCH 03/14] More tests --- src/baseline.rs | 39 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 39 insertions(+) diff --git a/src/baseline.rs b/src/baseline.rs index e4fc81de..74e6106a 100644 --- a/src/baseline.rs +++ b/src/baseline.rs @@ -391,4 +391,43 @@ mod tests { "1.2.0".to_string() ); } + + #[test] + fn choose_baseline_version_not_latest() { + let crate_ = new_crate(&[ + new_mock_version("1.2.0", false), + new_mock_version("1.2.1", false), + ]); + let current_version = semver::Version::new(1, 2, 0); + assert_eq!( + choose_baseline_version(&crate_, Some(¤t_version)).unwrap(), + "1.2.0".to_string() + ); + } + + #[test] + fn choose_baseline_version_pre_release() { + let crate_ = new_crate(&[ + new_mock_version("1.2.0", false), + new_mock_version("1.2.1-rc1", false), + ]); + let current_version = semver::Version::parse("1.2.1-rc2").unwrap(); + assert_eq!( + choose_baseline_version(&crate_, Some(¤t_version)).unwrap(), + "1.2.0".to_string() + ); + } + + #[test] + fn choose_baseline_version_no_current() { + let crate_ = new_crate(&[ + new_mock_version("1.2.0", false), + new_mock_version("1.2.1-rc1", false), + new_mock_version("1.3.1", true), + ]); + assert_eq!( + choose_baseline_version(&crate_, None).unwrap(), + "1.2.0".to_string() + ); + } } From 6b065b9d3f38fc4ff52c7ff40a8f37b1bf096021 Mon Sep 17 00:00:00 2001 From: Mieszko Grodzicki Date: Sun, 1 Jan 2023 22:35:10 +0100 Subject: [PATCH 04/14] Justify using serde_json in tests. --- src/baseline.rs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/baseline.rs b/src/baseline.rs index 74e6106a..3fc6d167 100644 --- a/src/baseline.rs +++ b/src/baseline.rs @@ -364,6 +364,8 @@ mod tests { use super::choose_baseline_version; fn new_mock_version(version_name: &str, yanked: bool) -> Version { + // `crates_index::Version` cannot be created explicitly, as all its fields + // are private, so we use the fact that it can be deserialized. serde_json::from_value(serde_json::json!({ "name": "test-crate", "vers": version_name, @@ -376,6 +378,8 @@ mod tests { } fn new_crate(versions: &[Version]) -> Crate { + // `crates_index::Crate` cannot be created explicitly, as its field + // is private, so we use the fact that it can be deserialized. serde_json::from_value(serde_json::json!({ "versions": versions })).unwrap() } From c7965115dbfb6720c00994c1e66434b3de484525 Mon Sep 17 00:00:00 2001 From: Mieszko Grodzicki Date: Mon, 2 Jan 2023 12:44:12 +0100 Subject: [PATCH 05/14] Tests refactoring --- src/baseline.rs | 74 ++++++++++++++++++++++++++----------------------- 1 file changed, 39 insertions(+), 35 deletions(-) diff --git a/src/baseline.rs b/src/baseline.rs index 3fc6d167..2ef95162 100644 --- a/src/baseline.rs +++ b/src/baseline.rs @@ -374,64 +374,68 @@ mod tests { "yanked": yanked, "cksum": "00".repeat(32), })) - .unwrap() + .expect("Parsing JSON as crates_index::Version should not result in any errors.") } - fn new_crate(versions: &[Version]) -> Crate { + fn new_crate(versions: Vec) -> Crate { // `crates_index::Crate` cannot be created explicitly, as its field // is private, so we use the fact that it can be deserialized. - serde_json::from_value(serde_json::json!({ "versions": versions })).unwrap() + serde_json::from_value(serde_json::json!({ "versions": versions })) + .expect("Parsing JSON as crates_index::Crate should not result in any errors.") + } + + fn test_choose_baseline_version( + versions: Vec<(&str, bool)>, + current_version_name: Option<&str>, + expected: &str, + ) { + let crate_ = new_crate( + versions + .into_iter() + .map(|(version, yanked)| new_mock_version(version, yanked)) + .collect(), + ); + let current_version = current_version_name.map(|version_name| { + semver::Version::parse(version_name).expect("current_version_name should be valid") + }); + let choosen_baseline = choose_baseline_version(&crate_, current_version.as_ref()) + .expect("choose_baseline_version should not return any error"); + assert_eq!(choosen_baseline, expected.to_owned()); } #[test] fn choose_baseline_version_yanked() { - let crate_ = new_crate(&[ - new_mock_version("1.2.0", false), - new_mock_version("1.2.1", true), - ]); - let current_version = semver::Version::new(1, 2, 2); - assert_eq!( - choose_baseline_version(&crate_, Some(¤t_version)).unwrap(), - "1.2.0".to_string() + test_choose_baseline_version( + vec![("1.2.0", false), ("1.2.1", true)], + Some("1.2.2"), + "1.2.0", ); } #[test] fn choose_baseline_version_not_latest() { - let crate_ = new_crate(&[ - new_mock_version("1.2.0", false), - new_mock_version("1.2.1", false), - ]); - let current_version = semver::Version::new(1, 2, 0); - assert_eq!( - choose_baseline_version(&crate_, Some(¤t_version)).unwrap(), - "1.2.0".to_string() + test_choose_baseline_version( + vec![("1.2.0", false), ("1.2.1", false)], + Some("1.2.0"), + "1.2.0", ); } #[test] fn choose_baseline_version_pre_release() { - let crate_ = new_crate(&[ - new_mock_version("1.2.0", false), - new_mock_version("1.2.1-rc1", false), - ]); - let current_version = semver::Version::parse("1.2.1-rc2").unwrap(); - assert_eq!( - choose_baseline_version(&crate_, Some(¤t_version)).unwrap(), - "1.2.0".to_string() + test_choose_baseline_version( + vec![("1.2.0", false), ("1.2.1-rc1", false)], + Some("1.2.1-rc2"), + "1.2.0", ); } #[test] fn choose_baseline_version_no_current() { - let crate_ = new_crate(&[ - new_mock_version("1.2.0", false), - new_mock_version("1.2.1-rc1", false), - new_mock_version("1.3.1", true), - ]); - assert_eq!( - choose_baseline_version(&crate_, None).unwrap(), - "1.2.0".to_string() + test_choose_baseline_version( + vec![("1.2.0", false), ("1.2.1-rc1", false), ("1.3.1", true)], + None, + "1.2.0", ); } } From aef36cba0c612e08d190378ea167607975f46e73 Mon Sep 17 00:00:00 2001 From: Mieszko Grodzicki Date: Mon, 2 Jan 2023 12:44:31 +0100 Subject: [PATCH 06/14] Move the comment --- src/baseline.rs | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/baseline.rs b/src/baseline.rs index 2ef95162..12e8ccdd 100644 --- a/src/baseline.rs +++ b/src/baseline.rs @@ -247,6 +247,9 @@ fn choose_baseline_version( crate_: &Crate, version_current: Option<&semver::Version>, ) -> anyhow::Result { + // Try to avoid pre-releases + // - Breaking changes are allowed between them + // - Most likely the user cares about the last official release if let Some(current) = version_current { let mut instances = crate_ .versions() @@ -292,9 +295,7 @@ impl BaselineLoader for RegistryBaseline { .index .crate_(name) .with_context(|| anyhow::format_err!("{} not found in registry", name))?; - // Try to avoid pre-releases - // - Breaking changes are allowed between them - // - Most likely the user cares about the last official release + let base_version = if let Some(base) = self.version.as_ref() { base.to_string() } else { From 2ef8599128627fe582a27bf0c457a5b4aa0dfe3c Mon Sep 17 00:00:00 2001 From: Mieszko Grodzicki Date: Mon, 2 Jan 2023 13:02:46 +0100 Subject: [PATCH 07/14] Fix handling of yanked releases, add tests --- src/baseline.rs | 31 ++++++++++++++++++++++++++----- 1 file changed, 26 insertions(+), 5 deletions(-) diff --git a/src/baseline.rs b/src/baseline.rs index 12e8ccdd..b1e16a15 100644 --- a/src/baseline.rs +++ b/src/baseline.rs @@ -254,19 +254,22 @@ fn choose_baseline_version( let mut instances = crate_ .versions() .iter() - .filter(|i| !i.is_yanked()) - .filter_map(|i| semver::Version::parse(i.version()).ok()) + .filter_map(|i| { + semver::Version::parse(i.version()) + .map(|v| (v, i.is_yanked())) + .ok() + }) // For unpublished changes when the user doesn't increment the version // post-release, allow using the current version as a baseline. - .filter(|v| v <= current) + .filter(|(v, _)| v <= current) .collect::>(); instances.sort(); instances .iter() .rev() - .find(|v| v.pre.is_empty()) + .find(|(v, yanked)| v.pre.is_empty() && !yanked) .or_else(|| instances.last()) - .map(|v| v.to_string()) + .map(|(v, _)| v.to_string()) .with_context(|| { anyhow::format_err!( "No available baseline versions for {}@{}", @@ -439,4 +442,22 @@ mod tests { "1.2.0", ); } + + #[test] + fn choose_baseline_version_no_normal_largest_yanked() { + test_choose_baseline_version( + vec![("1.2.0", true), ("1.2.1-rc1", false)], + Some("1.2.1"), + "1.2.1-rc1", + ); + } + + #[test] + fn choose_baseline_version_no_normal_largest_pre_release() { + test_choose_baseline_version( + vec![("1.2.1-rc1", false), ("1.2.1", true)], + Some("1.2.1"), + "1.2.1", + ); + } } From bf534bbacefdcc26b50e42e535d7e0756cb96652 Mon Sep 17 00:00:00 2001 From: Mieszko Grodzicki Date: Mon, 2 Jan 2023 18:04:21 +0100 Subject: [PATCH 08/14] Renaming --- src/baseline.rs | 30 +++++++++++++++--------------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/src/baseline.rs b/src/baseline.rs index b1e16a15..5a28c2b3 100644 --- a/src/baseline.rs +++ b/src/baseline.rs @@ -378,17 +378,17 @@ mod tests { "yanked": yanked, "cksum": "00".repeat(32), })) - .expect("Parsing JSON as crates_index::Version should not result in any errors.") + .expect("Failed to create crates_index::Version from a hand-written JSON.") } fn new_crate(versions: Vec) -> Crate { // `crates_index::Crate` cannot be created explicitly, as its field // is private, so we use the fact that it can be deserialized. serde_json::from_value(serde_json::json!({ "versions": versions })) - .expect("Parsing JSON as crates_index::Crate should not result in any errors.") + .expect("Failed to create crates_index::Crate from a hand-written JSON.") } - fn test_choose_baseline_version( + fn assert_correctly_picks_baseline_version( versions: Vec<(&str, bool)>, current_version_name: Option<&str>, expected: &str, @@ -408,8 +408,8 @@ mod tests { } #[test] - fn choose_baseline_version_yanked() { - test_choose_baseline_version( + fn baseline_choosing_logic_skips_yanked() { + assert_correctly_picks_baseline_version( vec![("1.2.0", false), ("1.2.1", true)], Some("1.2.2"), "1.2.0", @@ -417,8 +417,8 @@ mod tests { } #[test] - fn choose_baseline_version_not_latest() { - test_choose_baseline_version( + fn baseline_choosing_logic_skips_greater_than_current() { + assert_correctly_picks_baseline_version( vec![("1.2.0", false), ("1.2.1", false)], Some("1.2.0"), "1.2.0", @@ -426,8 +426,8 @@ mod tests { } #[test] - fn choose_baseline_version_pre_release() { - test_choose_baseline_version( + fn baseline_choosing_logic_skips_pre_releases() { + assert_correctly_picks_baseline_version( vec![("1.2.0", false), ("1.2.1-rc1", false)], Some("1.2.1-rc2"), "1.2.0", @@ -435,8 +435,8 @@ mod tests { } #[test] - fn choose_baseline_version_no_current() { - test_choose_baseline_version( + fn baseline_choosing_logic_without_current_picks_latest_normal() { + assert_correctly_picks_baseline_version( vec![("1.2.0", false), ("1.2.1-rc1", false), ("1.3.1", true)], None, "1.2.0", @@ -444,8 +444,8 @@ mod tests { } #[test] - fn choose_baseline_version_no_normal_largest_yanked() { - test_choose_baseline_version( + fn baseline_choosing_logic_picks_pre_release_if_there_is_no_normal() { + assert_correctly_picks_baseline_version( vec![("1.2.0", true), ("1.2.1-rc1", false)], Some("1.2.1"), "1.2.1-rc1", @@ -453,8 +453,8 @@ mod tests { } #[test] - fn choose_baseline_version_no_normal_largest_pre_release() { - test_choose_baseline_version( + fn baseline_choosing_logic_picks_yanked_if_there_is_no_normal() { + assert_correctly_picks_baseline_version( vec![("1.2.1-rc1", false), ("1.2.1", true)], Some("1.2.1"), "1.2.1", From e0426792574725a64d6e4cafdc7004bf924b75c7 Mon Sep 17 00:00:00 2001 From: Mieszko Grodzicki Date: Mon, 2 Jan 2023 18:14:53 +0100 Subject: [PATCH 09/14] Add a comment --- src/baseline.rs | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/src/baseline.rs b/src/baseline.rs index 5a28c2b3..0c6b3c1a 100644 --- a/src/baseline.rs +++ b/src/baseline.rs @@ -278,6 +278,9 @@ fn choose_baseline_version( ) }) } else { + // If there is no normal version (not yanked and not a pre-release) + // choosing the latest one anyway is more reasonable than throwing an + // error, as there is still a chance that it is what the user expects. let instance = crate_ .highest_normal_version() .unwrap_or_else(|| crate_.highest_version()) @@ -460,4 +463,13 @@ mod tests { "1.2.1", ); } + + #[test] + fn baseline_choosing_logic_picks_yanked_if_there_is_no_normal2() { + assert_correctly_picks_baseline_version( + vec![("1.2.2", true), ("1.2.3", true)], + Some("1.2.1"), + "1.2.3", + ); + } } From c720e5fd289768f98d806fdc3aa1516625af51ab Mon Sep 17 00:00:00 2001 From: Mieszko Grodzicki Date: Mon, 2 Jan 2023 19:50:39 +0100 Subject: [PATCH 10/14] Remove accidentally added test --- src/baseline.rs | 9 --------- 1 file changed, 9 deletions(-) diff --git a/src/baseline.rs b/src/baseline.rs index 0c6b3c1a..de76399c 100644 --- a/src/baseline.rs +++ b/src/baseline.rs @@ -463,13 +463,4 @@ mod tests { "1.2.1", ); } - - #[test] - fn baseline_choosing_logic_picks_yanked_if_there_is_no_normal2() { - assert_correctly_picks_baseline_version( - vec![("1.2.2", true), ("1.2.3", true)], - Some("1.2.1"), - "1.2.3", - ); - } } From d5da35bb5136caefde99d5b94056ba840675a76f Mon Sep 17 00:00:00 2001 From: Mieszko Grodzicki Date: Mon, 2 Jan 2023 19:52:42 +0100 Subject: [PATCH 11/14] Improve assert_correctly_picks_baseline_version --- src/baseline.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/baseline.rs b/src/baseline.rs index de76399c..b0464ac7 100644 --- a/src/baseline.rs +++ b/src/baseline.rs @@ -403,11 +403,11 @@ mod tests { .collect(), ); let current_version = current_version_name.map(|version_name| { - semver::Version::parse(version_name).expect("current_version_name should be valid") + semver::Version::parse(version_name).expect("Failed to parse hand-written string as a valid version name.") }); - let choosen_baseline = choose_baseline_version(&crate_, current_version.as_ref()) + let chosen_baseline = choose_baseline_version(&crate_, current_version.as_ref()) .expect("choose_baseline_version should not return any error"); - assert_eq!(choosen_baseline, expected.to_owned()); + assert_eq!(chosen_baseline, expected.to_owned()); } #[test] From e3c2e104309a73c14f710b65536ae9c0a0dc671a Mon Sep 17 00:00:00 2001 From: Mieszko Grodzicki Date: Mon, 2 Jan 2023 19:53:17 +0100 Subject: [PATCH 12/14] fmt --- src/baseline.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/baseline.rs b/src/baseline.rs index b0464ac7..19bc0323 100644 --- a/src/baseline.rs +++ b/src/baseline.rs @@ -403,7 +403,8 @@ mod tests { .collect(), ); let current_version = current_version_name.map(|version_name| { - semver::Version::parse(version_name).expect("Failed to parse hand-written string as a valid version name.") + semver::Version::parse(version_name) + .expect("Failed to parse hand-written string as a valid version name.") }); let chosen_baseline = choose_baseline_version(&crate_, current_version.as_ref()) .expect("choose_baseline_version should not return any error"); From 8d70beb68aa4a22bdc835555748a5386379d565f Mon Sep 17 00:00:00 2001 From: Mieszko Grodzicki Date: Tue, 3 Jan 2023 01:36:44 +0100 Subject: [PATCH 13/14] Improve expect messages --- src/baseline.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/baseline.rs b/src/baseline.rs index 19bc0323..f7f101e0 100644 --- a/src/baseline.rs +++ b/src/baseline.rs @@ -381,14 +381,14 @@ mod tests { "yanked": yanked, "cksum": "00".repeat(32), })) - .expect("Failed to create crates_index::Version from a hand-written JSON.") + .expect("hand-written JSON used to create mock crates_index::Version should be valid") } fn new_crate(versions: Vec) -> Crate { // `crates_index::Crate` cannot be created explicitly, as its field // is private, so we use the fact that it can be deserialized. serde_json::from_value(serde_json::json!({ "versions": versions })) - .expect("Failed to create crates_index::Crate from a hand-written JSON.") + .expect("hand-written JSON used to create mock crates_index::Crate should be valid") } fn assert_correctly_picks_baseline_version( @@ -404,10 +404,10 @@ mod tests { ); let current_version = current_version_name.map(|version_name| { semver::Version::parse(version_name) - .expect("Failed to parse hand-written string as a valid version name.") + .expect("current_version_name used in assertion should encode a valid version") }); let chosen_baseline = choose_baseline_version(&crate_, current_version.as_ref()) - .expect("choose_baseline_version should not return any error"); + .expect("choose_baseline_version should not return any error in the test case"); assert_eq!(chosen_baseline, expected.to_owned()); } From f9dd9484eb6be9459fca15406bd0782e130b5311 Mon Sep 17 00:00:00 2001 From: Mieszko Grodzicki Date: Tue, 3 Jan 2023 09:31:31 +0100 Subject: [PATCH 14/14] Move the comment --- src/baseline.rs | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/src/baseline.rs b/src/baseline.rs index f7f101e0..b7138057 100644 --- a/src/baseline.rs +++ b/src/baseline.rs @@ -278,12 +278,14 @@ fn choose_baseline_version( ) }) } else { - // If there is no normal version (not yanked and not a pre-release) - // choosing the latest one anyway is more reasonable than throwing an - // error, as there is still a chance that it is what the user expects. let instance = crate_ .highest_normal_version() - .unwrap_or_else(|| crate_.highest_version()) + .unwrap_or_else(|| { + // If there is no normal version (not yanked and not a pre-release) + // choosing the latest one anyway is more reasonable than throwing an + // error, as there is still a chance that it is what the user expects. + crate_.highest_version() + }) .version(); Ok(instance.to_owned()) }