pub struct GBDTModel { /* private fields */ }Expand description
Trained GBDT model
Implementations§
Source§impl GBDTModel
impl GBDTModel
Sourcepub fn train(
features: &[f32],
num_features: usize,
targets: &[f32],
config: GBDTConfig,
feature_names: Option<Vec<String>>,
) -> Result<Self>
pub fn train( features: &[f32], num_features: usize, targets: &[f32], config: GBDTConfig, feature_names: Option<Vec<String>>, ) -> Result<Self>
Train a GBDT model from raw feature data (high-level API)
This is the primary training API that handles binning automatically. Features are discretized using T-Digest quantile binning with parallelization.
§Arguments
features- Row-major feature matrix:features[row * num_features + feature]Shape:(num_rows, num_features)flattened to 1Dnum_features- Number of features (columns)targets- Target values, one per rowconfig- Training configurationfeature_names- Optional feature names (defaults to “feature_0”, “feature_1”, …)
§Example
let features = vec![1.0, 2.0, 3.0, 4.0, 5.0, 6.0]; // 2 rows × 3 features
let targets = vec![0.5, 1.5];
let config = GBDTConfig::new().with_num_rounds(100);
let model = GBDTModel::train(&features, 3, &targets, config, None)?;Sourcepub fn train_with_output(
features: &[f32],
num_features: usize,
targets: &[f32],
config: GBDTConfig,
feature_names: Option<Vec<String>>,
output_dir: impl AsRef<Path>,
formats: &[ModelFormat],
) -> Result<Self>
pub fn train_with_output( features: &[f32], num_features: usize, targets: &[f32], config: GBDTConfig, feature_names: Option<Vec<String>>, output_dir: impl AsRef<Path>, formats: &[ModelFormat], ) -> Result<Self>
Train a GBDT model and save to output directory
This is a convenience method that trains a model and automatically saves:
- The trained model in the specified format(s)
config.jsonwith the training configuration for reproducibility
§Arguments
features- Row-major feature matrix:features[row * num_features + feature]num_features- Number of features (columns)targets- Target values, one per rowconfig- Training configurationfeature_names- Optional feature namesoutput_dir- Directory to save the model and configformats- Model formats to save (e.g.,[ModelFormat::Rkyv])
§Example
let features = vec![1.0, 2.0, 3.0, 4.0, 5.0, 6.0]; // 2 rows × 3 features
let targets = vec![0.5, 1.5];
let config = GBDTConfig::new().with_num_rounds(100);
let model = GBDTModel::train_with_output(
&features, 3, &targets, config, None,
"output/my_model",
&[ModelFormat::Rkyv],
)?;
// Creates: output/my_model/model.rkyv and output/my_model/config.jsonSourcepub fn save_to_directory(
&self,
output_dir: impl AsRef<Path>,
config: &GBDTConfig,
formats: &[ModelFormat],
) -> Result<()>
pub fn save_to_directory( &self, output_dir: impl AsRef<Path>, config: &GBDTConfig, formats: &[ModelFormat], ) -> Result<()>
Save a trained model to a directory
Creates the directory if it doesn’t exist and saves:
- The model in each specified format
config.jsonwith the training configuration
§Arguments
output_dir- Directory to save the modelconfig- Training configuration (for config.json)formats- Model formats to save (must not be empty)
§Errors
Returns an error if formats is empty or if I/O operations fail.
Sourcepub fn train_with_eras(
features: &[f32],
num_features: usize,
targets: &[f32],
era_indices: &[u16],
config: GBDTConfig,
feature_names: Option<Vec<String>>,
) -> Result<Self>
pub fn train_with_eras( features: &[f32], num_features: usize, targets: &[f32], era_indices: &[u16], config: GBDTConfig, feature_names: Option<Vec<String>>, ) -> Result<Self>
Train a GBDT model with Directional Era Splitting (DES)
Era splitting filters out spurious correlations by requiring all eras to agree on split direction. This is useful for time-series or financial data where patterns may not generalize across time periods.
§Arguments
features- Row-major feature matrix:features[row * num_features + feature]num_features- Number of features (columns)targets- Target values, one per rowera_indices- Era index (0-based) for each rowconfig- Training configuration (era_splitting must be enabled)feature_names- Optional feature names
§Example
let features = vec![1.0, 2.0, 3.0, 4.0, 5.0, 6.0]; // 2 rows × 3 features
let targets = vec![0.5, 1.5];
let era_indices = vec![0, 1]; // Row 0 in era 0, row 1 in era 1
let config = GBDTConfig::new()
.with_num_rounds(100)
.with_era_splitting(true);
let model = GBDTModel::train_with_eras(&features, 3, &targets, &era_indices, config, None)?;Sourcepub fn train_binned(dataset: &BinnedDataset, config: GBDTConfig) -> Result<Self>
pub fn train_binned(dataset: &BinnedDataset, config: GBDTConfig) -> Result<Self>
Train a GBDT model from pre-binned data (low-level API)
Use this when you have already binned your data (e.g., for repeated training with different hyperparameters on the same binned dataset).
For most use cases, prefer train() which handles binning automatically.
Sourcepub fn train_binned_with_validation(
train_dataset: &BinnedDataset,
val_dataset: &BinnedDataset,
val_targets: &[f32],
config: GBDTConfig,
) -> Result<Self>
pub fn train_binned_with_validation( train_dataset: &BinnedDataset, val_dataset: &BinnedDataset, val_targets: &[f32], config: GBDTConfig, ) -> Result<Self>
Train a GBDT model with an external validation set for early stopping
Use this when you have a separate validation set that was properly prepared (e.g., encoded separately to avoid target leakage). The external validation set is used for early stopping decisions while training uses the full train set.
§Note on Implementation
This method shares ~90% of logic with train_binned(). The duplication is
intentional due to the complexity of the training loop (CUDA/WGPU backends,
fused gradient paths, GOSS sampling). Extracting shared logic would require
significant refactoring and testing to maintain correctness.
Key differences from train_binned():
- Uses external validation set instead of internal split
- Maintains separate validation predictions array
- No calibration set for conformal prediction
Sourcepub fn predict_row(&self, dataset: &BinnedDataset, row_idx: usize) -> f32
pub fn predict_row(&self, dataset: &BinnedDataset, row_idx: usize) -> f32
Predict for a single row
Sourcepub fn predict(&self, dataset: &BinnedDataset) -> Vec<f32>
pub fn predict(&self, dataset: &BinnedDataset) -> Vec<f32>
Predict for all rows using tree-wise batch prediction
This approach traverses one tree for ALL rows before moving to the next tree, which is more cache-friendly than row-wise traversal.
Routes to parallel or sequential based on config.parallel_prediction
Sourcepub fn predict_sequential(&self, dataset: &BinnedDataset) -> Vec<f32>
pub fn predict_sequential(&self, dataset: &BinnedDataset) -> Vec<f32>
Single-threaded tree-wise batch prediction
Traverses each tree for all rows before moving to the next tree. More cache-friendly than row-wise traversal.
Sourcepub fn predict_parallel(&self, dataset: &BinnedDataset) -> Vec<f32>
pub fn predict_parallel(&self, dataset: &BinnedDataset) -> Vec<f32>
Parallel tree-wise batch prediction
Splits rows into chunks and processes each chunk in parallel. Each chunk uses tree-wise traversal internally.
Sourcepub fn predict_with_intervals(
&self,
dataset: &BinnedDataset,
) -> (Vec<f32>, Vec<f32>, Vec<f32>)
pub fn predict_with_intervals( &self, dataset: &BinnedDataset, ) -> (Vec<f32>, Vec<f32>, Vec<f32>)
Predict with conformal intervals
Returns (predictions, lower_bounds, upper_bounds)
Sourcepub fn predict_proba(&self, dataset: &BinnedDataset) -> Vec<f32>
pub fn predict_proba(&self, dataset: &BinnedDataset) -> Vec<f32>
Predict class probabilities for binary classification
Applies sigmoid to raw predictions to get probabilities in [0, 1].
Only meaningful when trained with with_binary_logloss().
§Returns
Vector of probabilities (probability of class 1)
Sourcepub fn predict_class(&self, dataset: &BinnedDataset, threshold: f32) -> Vec<u32>
pub fn predict_class(&self, dataset: &BinnedDataset, threshold: f32) -> Vec<u32>
Predict class labels for binary classification
Applies sigmoid to raw predictions and thresholds at 0.5 (or custom threshold).
Only meaningful when trained with with_binary_logloss().
§Arguments
dataset- The binned dataset to predict onthreshold- Classification threshold (default 0.5)
§Returns
Vector of class labels (0 or 1)
Sourcepub fn is_multiclass(&self) -> bool
pub fn is_multiclass(&self) -> bool
Check if this is a multi-class model
Sourcepub fn get_num_classes(&self) -> usize
pub fn get_num_classes(&self) -> usize
Get number of classes (0 for regression/binary)
Sourcepub fn predict_proba_multiclass(&self, dataset: &BinnedDataset) -> Vec<Vec<f32>>
pub fn predict_proba_multiclass(&self, dataset: &BinnedDataset) -> Vec<Vec<f32>>
Predict class probabilities for multi-class classification
Applies softmax to raw predictions to get probabilities for each class.
Only meaningful when trained with with_multiclass_logloss().
§Returns
Vector of probability vectors: result[sample][class]
Sourcepub fn predict_class_multiclass(&self, dataset: &BinnedDataset) -> Vec<u32>
pub fn predict_class_multiclass(&self, dataset: &BinnedDataset) -> Vec<u32>
Predict class labels for multi-class classification
Returns the class with highest probability (argmax of softmax).
Only meaningful when trained with with_multiclass_logloss().
§Returns
Vector of class labels (0, 1, 2, …, K-1)
Sourcepub fn predict_raw_multiclass(&self, dataset: &BinnedDataset) -> Vec<Vec<f32>>
pub fn predict_raw_multiclass(&self, dataset: &BinnedDataset) -> Vec<Vec<f32>>
Predict raw scores for multi-class classification (before softmax)
Returns raw predictions for each class (not probabilities). Shape: result[sample][class]
Sourcepub fn predict_raw(&self, features: &[f64]) -> Vec<f32>
pub fn predict_raw(&self, features: &[f64]) -> Vec<f32>
Predict using raw feature values (no binning needed)
This is the primary prediction method for external use (e.g., Python bindings). Uses the split_value stored in tree nodes to compare directly against raw values, avoiding the overhead of binning on every prediction call.
§Arguments
features- Row-major feature matrix: features[row * num_features + feature] Shape: (num_rows, num_features)
§Returns
Vector of predictions for each row
Sourcepub fn predict_raw_with_intervals(
&self,
features: &[f64],
) -> (Vec<f32>, Vec<f32>, Vec<f32>)
pub fn predict_raw_with_intervals( &self, features: &[f64], ) -> (Vec<f32>, Vec<f32>, Vec<f32>)
Predict raw with conformal intervals
Returns (predictions, lower_bounds, upper_bounds)
Sourcepub fn predict_proba_raw(&self, features: &[f64]) -> Vec<f32>
pub fn predict_proba_raw(&self, features: &[f64]) -> Vec<f32>
Predict class probabilities from raw features (for binary classification)
Applies sigmoid to raw predictions to get probabilities in [0, 1].
Only meaningful when trained with with_binary_logloss().
Sourcepub fn predict_class_raw(&self, features: &[f64], threshold: f32) -> Vec<u32>
pub fn predict_class_raw(&self, features: &[f64], threshold: f32) -> Vec<u32>
Predict class labels from raw features (for binary classification)
Applies sigmoid to raw predictions and thresholds.
Only meaningful when trained with with_binary_logloss().
Sourcepub fn predict_proba_multiclass_raw(&self, features: &[f64]) -> Vec<Vec<f32>>
pub fn predict_proba_multiclass_raw(&self, features: &[f64]) -> Vec<Vec<f32>>
Predict class probabilities from raw features (for multi-class classification)
Uses the split_value stored in tree nodes to compare directly against raw values.
Applies softmax to raw predictions to get probabilities for each class.
Only meaningful when trained with with_multiclass_logloss().
§Arguments
features- Row-major feature matrix: features[row * num_features + feature]
§Returns
Vector of probability vectors: result[sample][class]
Sourcepub fn predict_class_multiclass_raw(&self, features: &[f64]) -> Vec<u32>
pub fn predict_class_multiclass_raw(&self, features: &[f64]) -> Vec<u32>
Predict class labels from raw features (for multi-class classification)
Returns the class with highest probability (argmax of softmax).
Only meaningful when trained with with_multiclass_logloss().
§Arguments
features- Row-major feature matrix: features[row * num_features + feature]
§Returns
Vector of class labels (0, 1, 2, …, K-1)
Sourcepub fn config(&self) -> &GBDTConfig
pub fn config(&self) -> &GBDTConfig
Get configuration
Sourcepub fn base_prediction(&self) -> f32
pub fn base_prediction(&self) -> f32
Get base prediction
Sourcepub fn conformal_quantile(&self) -> Option<f32>
pub fn conformal_quantile(&self) -> Option<f32>
Get conformal quantile (if calibrated)
Sourcepub fn feature_info(&self) -> &[FeatureInfo]
pub fn feature_info(&self) -> &[FeatureInfo]
Get feature info (for consistent binning during prediction)
Sourcepub fn num_features(&self) -> usize
pub fn num_features(&self) -> usize
Get number of features
Sourcepub fn column_permutation(&self) -> Option<&ColumnPermutation>
pub fn column_permutation(&self) -> Option<&ColumnPermutation>
Get column permutation (if optimized layout was applied)
Sourcepub fn feature_importance(&self) -> Vec<f32>
pub fn feature_importance(&self) -> Vec<f32>
Compute feature importance (gain-based)
Sourcepub fn optimize_dataset_layout(
&self,
dataset: &BinnedDataset,
) -> (BinnedDataset, ColumnPermutation)
pub fn optimize_dataset_layout( &self, dataset: &BinnedDataset, ) -> (BinnedDataset, ColumnPermutation)
Create a cache-optimized dataset by reordering columns based on feature importance
More frequently used features are placed at the beginning of the dataset for better CPU cache locality during tree traversal.
Returns the reordered dataset and the permutation mapping (new_idx -> original_idx)
Sourcepub fn create_packed_dataset(&self, dataset: &BinnedDataset) -> PackedDataset
pub fn create_packed_dataset(&self, dataset: &BinnedDataset) -> PackedDataset
Create a memory-optimized packed dataset from a BinnedDataset
Uses 4-bit packing for features with ≤16 unique bins, providing up to 50% memory savings for low-cardinality features.
Sourcepub fn num_rounds(&self) -> usize
pub fn num_rounds(&self) -> usize
Get number of completed rounds
For regression/binary: num_rounds == num_trees For multi-class: num_rounds = num_trees / num_classes
Sourcepub fn append_trees(&mut self, new_trees: Vec<Tree>)
pub fn append_trees(&mut self, new_trees: Vec<Tree>)
Append new trees to the ensemble (incremental learning)
§Arguments
new_trees- Trees trained on residuals from current ensemble
§Multi-class Note
For multi-class classification, trees must be provided in round-major order:
[round_n_class_0, round_n_class_1, ..., round_n_class_k, round_n+1_class_0, ...]
§Example
// Get current predictions
let preds = model.predict(&dataset);
// Compute residuals (new_targets - preds)
let residuals: Vec<f32> = targets.iter().zip(&preds)
.map(|(t, p)| t - p).collect();
// Compute gradients/hessians for new trees
// ... train new trees on residuals ...
// Append to model
model.append_trees(new_trees);Sourcepub fn append_tree(&mut self, tree: Tree)
pub fn append_tree(&mut self, tree: Tree)
Append a single tree to the ensemble
Convenience method for adding one tree at a time.
Sourcepub fn compute_residuals(
&self,
dataset: &BinnedDataset,
targets: &[f32],
) -> Vec<f32>
pub fn compute_residuals( &self, dataset: &BinnedDataset, targets: &[f32], ) -> Vec<f32>
Compute residuals from current ensemble predictions
Residuals are target - prediction, which become the training targets
for new trees in incremental learning.
§Arguments
dataset- Binned dataset for predictiontargets- Original target values
§Returns
Residuals (target - prediction) for each sample
Sourcepub fn is_compatible_for_update(&self, num_features: usize) -> bool
pub fn is_compatible_for_update(&self, num_features: usize) -> bool
Check if incremental update is compatible
Verifies that new data has the same number of features as the trained model.
Sourcepub fn trees_mut(&mut self) -> &mut Vec<Tree>
pub fn trees_mut(&mut self) -> &mut Vec<Tree>
Get mutable reference to trees (for advanced manipulation)
Use with caution - modifying trees directly may break model invariants.
Sourcepub fn truncate_to_rounds(&mut self, num_rounds: usize)
pub fn truncate_to_rounds(&mut self, num_rounds: usize)
Trait Implementations§
Source§impl Archive for GBDTModel
impl Archive for GBDTModel
Source§const COPY_OPTIMIZATION: CopyOptimization<Self>
const COPY_OPTIMIZATION: CopyOptimization<Self>
serialize. Read moreSource§impl<'de> Deserialize<'de> for GBDTModel
impl<'de> Deserialize<'de> for GBDTModel
Source§fn deserialize<__D>(__deserializer: __D) -> Result<Self, __D::Error>where
__D: Deserializer<'de>,
fn deserialize<__D>(__deserializer: __D) -> Result<Self, __D::Error>where
__D: Deserializer<'de>,
Source§impl<__D: Fallible + ?Sized> Deserialize<GBDTModel, __D> for Archived<GBDTModel>where
GBDTConfig: Archive,
<GBDTConfig as Archive>::Archived: Deserialize<GBDTConfig, __D>,
f32: Archive,
<f32 as Archive>::Archived: Deserialize<f32, __D>,
Vec<f32>: Archive,
<Vec<f32> as Archive>::Archived: Deserialize<Vec<f32>, __D>,
Vec<Tree>: Archive,
<Vec<Tree> as Archive>::Archived: Deserialize<Vec<Tree>, __D>,
usize: Archive,
<usize as Archive>::Archived: Deserialize<usize, __D>,
Option<f32>: Archive,
<Option<f32> as Archive>::Archived: Deserialize<Option<f32>, __D>,
Vec<FeatureInfo>: Archive,
<Vec<FeatureInfo> as Archive>::Archived: Deserialize<Vec<FeatureInfo>, __D>,
Option<ColumnPermutation>: Archive,
<Option<ColumnPermutation> as Archive>::Archived: Deserialize<Option<ColumnPermutation>, __D>,
impl<__D: Fallible + ?Sized> Deserialize<GBDTModel, __D> for Archived<GBDTModel>where
GBDTConfig: Archive,
<GBDTConfig as Archive>::Archived: Deserialize<GBDTConfig, __D>,
f32: Archive,
<f32 as Archive>::Archived: Deserialize<f32, __D>,
Vec<f32>: Archive,
<Vec<f32> as Archive>::Archived: Deserialize<Vec<f32>, __D>,
Vec<Tree>: Archive,
<Vec<Tree> as Archive>::Archived: Deserialize<Vec<Tree>, __D>,
usize: Archive,
<usize as Archive>::Archived: Deserialize<usize, __D>,
Option<f32>: Archive,
<Option<f32> as Archive>::Archived: Deserialize<Option<f32>, __D>,
Vec<FeatureInfo>: Archive,
<Vec<FeatureInfo> as Archive>::Archived: Deserialize<Vec<FeatureInfo>, __D>,
Option<ColumnPermutation>: Archive,
<Option<ColumnPermutation> as Archive>::Archived: Deserialize<Option<ColumnPermutation>, __D>,
Source§impl TunableModel for GBDTModel
impl TunableModel for GBDTModel
Source§type Config = GBDTConfig
type Config = GBDTConfig
Source§fn train(dataset: &BinnedDataset, config: &Self::Config) -> Result<Self>
fn train(dataset: &BinnedDataset, config: &Self::Config) -> Result<Self>
Source§fn train_with_validation(
train_data: &BinnedDataset,
val_data: &BinnedDataset,
val_targets: &[f32],
config: &Self::Config,
) -> Result<Self>
fn train_with_validation( train_data: &BinnedDataset, val_data: &BinnedDataset, val_targets: &[f32], config: &Self::Config, ) -> Result<Self>
Source§fn apply_params(config: &mut Self::Config, params: &HashMap<String, ParamValue>)
fn apply_params(config: &mut Self::Config, params: &HashMap<String, ParamValue>)
Source§fn valid_params() -> &'static [&'static str]
fn valid_params() -> &'static [&'static str]
Source§fn default_config() -> Self::Config
fn default_config() -> Self::Config
Source§fn is_gpu_config(config: &Self::Config) -> bool
fn is_gpu_config(config: &Self::Config) -> bool
Source§fn get_learning_rate(config: &Self::Config) -> f32
fn get_learning_rate(config: &Self::Config) -> f32
Source§fn configure_validation(
config: &mut Self::Config,
validation_ratio: f32,
early_stopping_rounds: usize,
)
fn configure_validation( config: &mut Self::Config, validation_ratio: f32, early_stopping_rounds: usize, )
Source§fn set_num_rounds(config: &mut Self::Config, num_rounds: usize)
fn set_num_rounds(config: &mut Self::Config, num_rounds: usize)
Source§fn save_rkyv(&self, path: &Path) -> Result<()>
fn save_rkyv(&self, path: &Path) -> Result<()>
Source§fn save_bincode(&self, path: &Path) -> Result<()>
fn save_bincode(&self, path: &Path) -> Result<()>
Source§fn supports_conformal() -> bool
fn supports_conformal() -> bool
Auto Trait Implementations§
impl Freeze for GBDTModel
impl RefUnwindSafe for GBDTModel
impl Send for GBDTModel
impl Sync for GBDTModel
impl Unpin for GBDTModel
impl UnwindSafe for GBDTModel
Blanket Implementations§
Source§impl<T> ArchivePointee for T
impl<T> ArchivePointee for T
Source§type ArchivedMetadata = ()
type ArchivedMetadata = ()
Source§fn pointer_metadata(
_: &<T as ArchivePointee>::ArchivedMetadata,
) -> <T as Pointee>::Metadata
fn pointer_metadata( _: &<T as ArchivePointee>::ArchivedMetadata, ) -> <T as Pointee>::Metadata
Source§impl<T> ArchiveUnsized for Twhere
T: Archive,
impl<T> ArchiveUnsized for Twhere
T: Archive,
Source§type Archived = <T as Archive>::Archived
type Archived = <T as Archive>::Archived
Archive, it may be
unsized. Read moreSource§fn archived_metadata(
&self,
) -> <<T as ArchiveUnsized>::Archived as ArchivePointee>::ArchivedMetadata
fn archived_metadata( &self, ) -> <<T as ArchiveUnsized>::Archived as ArchivePointee>::ArchivedMetadata
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
Source§impl<T> CloneToUninit for Twhere
T: Clone,
impl<T> CloneToUninit for Twhere
T: Clone,
Source§impl<T> Instrument for T
impl<T> Instrument for T
Source§fn instrument(self, span: Span) -> Instrumented<Self>
fn instrument(self, span: Span) -> Instrumented<Self>
Source§fn in_current_span(self) -> Instrumented<Self>
fn in_current_span(self) -> Instrumented<Self>
Source§impl<T> IntoEither for T
impl<T> IntoEither for T
Source§fn into_either(self, into_left: bool) -> Either<Self, Self> ⓘ
fn into_either(self, into_left: bool) -> Either<Self, Self> ⓘ
self into a Left variant of Either<Self, Self>
if into_left is true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read moreSource§fn into_either_with<F>(self, into_left: F) -> Either<Self, Self> ⓘ
fn into_either_with<F>(self, into_left: F) -> Either<Self, Self> ⓘ
self into a Left variant of Either<Self, Self>
if into_left(&self) returns true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read moreSource§impl<T> Key for Twhere
T: Clone,
impl<T> Key for Twhere
T: Clone,
Source§impl<T> LayoutRaw for T
impl<T> LayoutRaw for T
Source§fn layout_raw(_: <T as Pointee>::Metadata) -> Result<Layout, LayoutError>
fn layout_raw(_: <T as Pointee>::Metadata) -> Result<Layout, LayoutError>
Source§impl<T, N1, N2> Niching<NichedOption<T, N1>> for N2
impl<T, N1, N2> Niching<NichedOption<T, N1>> for N2
Source§unsafe fn is_niched(niched: *const NichedOption<T, N1>) -> bool
unsafe fn is_niched(niched: *const NichedOption<T, N1>) -> bool
Source§fn resolve_niched(out: Place<NichedOption<T, N1>>)
fn resolve_niched(out: Place<NichedOption<T, N1>>)
out indicating that a T is niched.