fix(sampler): return None instead of panicking on parameter type mismatch in CompletedTrial::get()

This commit is contained in:
Manuel Raimann
2026-02-12 16:00:05 +01:00
parent 3d3dcb4c26
commit 12efbaabab
2 changed files with 28 additions and 12 deletions
+6 -12
View File
@@ -121,13 +121,9 @@ impl<V> CompletedTrial<V> {
/// Looks up the parameter by its unique id and casts the stored
/// [`ParamValue`] to the parameter's typed value.
///
/// Returns `None` if the parameter was not used in this trial.
///
/// # Panics
///
/// Panics if the stored value is incompatible with the parameter type
/// (e.g., a `Float` value stored for an `IntParam`). This indicates
/// a bug in the program, not a runtime error.
/// Returns `None` if the parameter was not used in this trial or if
/// the stored value is incompatible with the parameter type (e.g., a
/// `Float` value stored for an `IntParam`).
///
/// # Examples
///
@@ -150,11 +146,9 @@ impl<V> CompletedTrial<V> {
/// assert!((-10.0..=10.0).contains(&x_val));
/// ```
pub fn get<P: Parameter>(&self, param: &P) -> Option<P::Value> {
self.params.get(&param.id()).map(|v| {
param
.cast_param_value(v)
.expect("parameter type mismatch: stored value incompatible with parameter")
})
self.params
.get(&param.id())
.and_then(|v| param.cast_param_value(v).ok())
}
/// Returns `true` if all constraints are satisfied (values <= 0.0).
+22
View File
@@ -258,6 +258,28 @@ fn test_completed_trial_get() {
assert!((1..=10).contains(&n_val));
}
#[test]
fn test_completed_trial_get_type_mismatch_returns_none() {
let study: Study<f64> = Study::new(Direction::Minimize);
let int_param = IntParam::new(1, 10).name("x");
study
.optimize(1, |trial: &mut optimizer::Trial| {
let n = int_param.suggest(trial)?;
Ok::<_, Error>(n as f64)
})
.unwrap();
let best = study.best_trial().unwrap();
// The stored value is ParamValue::Int, but we query with a FloatParam.
let wrong_type = FloatParam::new(0.0, 100.0).name("x");
assert!(
best.get(&wrong_type).is_none(),
"type mismatch should return None, not panic"
);
}
#[test]
fn test_single_value_int_range() {
let param = IntParam::new(5, 5);