2015-07-03 132 views
3

下面的代码编译(特别是MyError被公认为具有性状调试):枚举派生调试

use std::str; 
use std::fmt; 

#[derive(Debug)] 
enum MyError<F> where F: str::FromStr { 
    Parse(F::Err), 
    Space, 
} 

fn my_parse<F>(s: String) -> Result<F,MyError<F>> 
    where F: str::FromStr { 
    match s.len() { 
     0 => Err(MyError::Space), 
     _ => s.parse::<F>().map_err(|err| MyError::Parse(err)), 
    } 
} 

fn my_force_parse<F>(s: String) -> F 
    where F: str::FromStr, MyError<F>: fmt::Debug { 
    my_parse::<F>(s).unwrap() 
} 

fn main() { 
    println!("hi"); 
    let s = "nope".to_string(); 
    println!("{}", my_force_parse::<i64>(s)); 
} 

但是,如果我有

where F: str::FromStr 

然后更换where语句为my_force_parse它不。不应该程序收集MyError从#[派生(调试)]属性实现调试吗?

回答

2

MyError实现Debug ... 无条件。相反,只要所有必需的通用参数实施它,它就实现它。从本质上讲,#[derive(Debug)]属性扩展到东西大致是:

impl<F> MyError<F> where F: Debug { 
    ... 
} 

毕竟,如果F没有实现DebugMyError不能提供一个实现。

此外,看起来好像where F: str::FromStr + fmt::Debug也是不够的。据推测,鲁斯特要么不够聪明,不能认识到F: Debug = MyError<F>: Debug,或者假设有问题。

+2

对'impl'的约束实际上是'F :: Err:Debug',因为枚举变量'Parse'包含'F :: Err',而不是'F'。 (尽管'rustc --pretty = expanded' *也会在'impl'上放一个'F:Debug'约束,但我看不出原因。) –