如何让Rust类型推断自动触发解引用强制转换适配参数?
解决Advent of Code框架中的类型推断与强制转换问题
问题背景
我正在开发一款Advent of Code框架,目标是让以下代码无需修改即可运行:
/// Sometimes a string is easier to work with. fn run1(_input: &str) { } /// Sometimes bytes are easier or faster. fn run2(_input: &[u8]) { } fn main() { run1(&input()); run2(&input()); }
其中input函数需从文件加载输入,返回自有类型(如String或Vec<u8>)而非引用。为此定义了Input trait:
/// Type of puzzle input that can be loaded: string or raw bytes. trait Input { fn from_bytes(bytes: Vec<u8>) -> Self; } impl Input for String { fn from_bytes(bytes: Vec<u8>) -> Self { String::from_utf8(bytes).unwrap() } } impl Input for Vec<u8> { fn from_bytes(bytes: Vec<u8>) -> Self { bytes } }
但使用如下input()函数实现时:
/// Imagine this loads some input from a file. fn input<I: Input>() -> I { I::from_bytes(vec![]) }
调用run1(&input())会触发编译错误,错误信息如下:
error[E0277]: the trait bound `str: Input` is not satisfied --> src/main.rs:10:11 | 10 | run1(&input()); | ^^^^^ the trait `Input` is not implemented for `str` | = help: the trait `Input` is implemented for `String` note: required by a bound in `input` --> src/main.rs:32:13 | 32 | fn input<I: Input>() -> I { | ^^^^^ required by this bound in `input`
由于str未实现Sized,无法为其实现Input trait,因此需要让类型推断在需要&str时自动推断I = String,借助Deref trait实现该需求。
解决方案
可以通过调整input函数的泛型约束,结合Deref trait实现自动类型推断,核心思路是让input返回的自有类型可以解引用为目标类型(str或[u8])。
实现代码
use std::ops::Deref; /// Type of puzzle input that can be loaded: string or raw bytes. trait Input { fn from_bytes(bytes: Vec<u8>) -> Self; } impl Input for String { fn from_bytes(bytes: Vec<u8>) -> Self { String::from_utf8(bytes).unwrap() } } impl Input for Vec<u8> { fn from_bytes(bytes: Vec<u8>) -> Self { bytes } } /// 返回可解引用为目标类型的自有输入类型 fn input<I, T>() -> I where I: Input + Deref<Target = T>, T: ?Sized, { // 实际场景中替换为从文件读取的字节 I::from_bytes(vec![]) } /// Sometimes a string is easier to work with. fn run1(_input: &str) { } /// Sometimes bytes are easier or faster. fn run2(_input: &[u8]) { } fn main() { run1(&input()); // 自动推断I=String,String可解引用为str run2(&input()); // 自动推断I=Vec<u8>,Vec<u8>可解引用为[u8] }
原理说明
- 当调用
run1(&input())时,run1期望接收&str参数,因此input()返回值的引用&I需能强制转换为&str。 - 通过
I: Deref<Target = T>的约束,编译器会自动匹配实现了Input且能解引用为str的类型——也就是String。 - 同理,
run2(&input())会自动推断I=Vec<u8>,因为Vec<u8>实现了Deref<Target=[u8]>。
内容的提问来源于stack exchange,提问作者Thomas
相关产品推荐
相关产品推荐

