rus*_*ell 1 types rust rust-clippy
Clippy 发出以下警告:
warning: very complex type used. Consider factoring parts into `type` definitions
--> src/regexp/mod.rs:845:56
|
845 | pub fn get_by_name<'b>(&'b self, name: &'b str) -> Vec<(&'b String, (usize, usize), (usize, usize))> {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#type_complexity
= note: `#[warn(clippy::type_complexity)]` on by default
Run Code Online (Sandbox Code Playgroud)
我同意这个警告。当我输入这段代码时,我不喜欢它,但我似乎不知道在哪里以及如何放置该type语句。我查过这本书,按照 Clippy 给出的参考链接进行搜索,似乎无法找到有关使用来type简化函数签名或如何处理参数生命周期的参考String。定义一个新的结构来保存返回值是可行的,但除了简化函数定义之外,实际上没有任何理由需要这样的结构。
这是代码。您可以看到我通过使用现有的 Report 结构来修复它 - 它有一些额外的字段不在我的返回设计中,但该结构已经存在,并且实际上使额外的字段可用可能会更好。但谢谢你的回答,我应该知道这里是否使用它。
pub struct Report {
/// The string found matching the RE pattern
pub found: String,
/// The position in chars of the string. This cannot be used for slices, except for ASCII chars. To get a slice use **pos**
pub pos: (usize, usize),
/// The position in bytes of the string: that is, found[pos.0..pos.1] is a valid unicode substring containing the match
pub bytes: (usize, usize),
/// The name of the field: if None then the field should not be included in the Report tree, if Some("") it is included but
/// unnamed, otherwise it is recorded with the given name
pub name: Option<String>,
/// Array of child Report structs, only non-empty for And and Or nodes. OrNodes will have only a single child node, AndNodes can have many.
pub subreports: Vec<Report>,
}
impl Report {
/// Constructor: creates a new report from a successful Path
pub fn new(root: &crate::regexp::walk::Path, char_start: usize, byte_start: usize) -> Report {
let (reports, _char_end) = root.gather_reports(char_start, byte_start);
reports[0].clone()
}
/// Pretty-prints a report with indentation to help make it easier to read
pub fn display(&self, indent: isize) {
let name_str = { if let Some(name) = &self.name { format!("<{}>", name) } else { "".to_string() }};
println!("{}\"{}\" char position [{}, {}] byte position [{}, {}] {}",
pad(indent), self.found, self.pos.0, self.pos.1, self.bytes.0, self.bytes.1, name_str);
self.subreports.iter().for_each(move |r| r.display(indent + 1));
}
/// Gets **Report** nodes representing matches for named Nodes. The return is a *Vec* because named matches can occur multiple
/// times - for example, _\?\<name\>abc\)*_
pub fn get_by_name<'b>(&'b self, name: &'b str) -> Vec<&Report> {
let mut v = Vec::<&Report>::new();
if let Some(n) = &self.name {
if n == name { v.push(self); }
}
for r in &self.subreports {
let mut x = r.get_by_name(name);
v.append(&mut x);
}
v
}
/// Gets a hash of **Report** nodes grouped by name. This just sets things up and calls **get_named_internal()** to do the work
pub fn get_named(& self) -> HashMap<&str, Vec<&Report>> {
let hash = HashMap::new();
self.get_named_internal(hash)
}
/// internal function that does the work for **get_named()**
fn get_named_internal<'b>(&'b self, mut hash: HashMap<&'b str, Vec<&'b Report>>) -> HashMap<&'b str, Vec<&Report>> {
if let Some(name) = &self.name {
if let Some(mut_v) = hash.get_mut(&name.as_str()) {
mut_v.push(self);
} else {
hash.insert(name.as_str(), vec![self]);
}
for r in self.subreports.iter() {
hash = r.get_named_internal(hash);
}
}
hash
}
}
Run Code Online (Sandbox Code Playgroud)
有几种方法可以简化这个过程。一种方法是为整个类型起别名(选择一个适当的描述性名称而不是Foo):
type Foo<'a> = Vec<(&'a String, (usize, usize), (usize, usize))>;
Run Code Online (Sandbox Code Playgroud)
那么你的返回类型是Foo<'b>.
如果此元组类型出现很多,您可以将其排除:
type Foo<'a> = (&'a String, (usize, usize), (usize, usize));
Run Code Online (Sandbox Code Playgroud)
然后你就会回来Vec<Foo<'b>>。
在没有看到其余代码的情况下很难提出替代方案。
我似乎不知道在哪里以及如何放置类型声明
您可以将type声明放在可以放置其他类型声明的任何位置,例如struct、enum等。
| 归档时间: |
|
| 查看次数: |
272 次 |
| 最近记录: |