extern crate rustc_errors;
extern crate rustc_hir;
extern crate rustc_hir_analysis;
+ extern crate rustc_index;
extern crate rustc_infer;
extern crate rustc_lexer;
extern crate rustc_lint;
extern crate rustc_middle;
+ extern crate rustc_mir_dataflow;
extern crate rustc_parse_format;
extern crate rustc_session;
extern crate rustc_span;
pub mod higher;
mod hir_utils;
pub mod macros;
+ pub mod mir;
pub mod msrvs;
pub mod numeric_literal;
pub mod paths;
return Some(version);
} else if let Some(sess) = sess {
if let Some(span) = span {
- sess.span_err(span, &format!("`{msrv}` is not a valid Rust version"));
+ sess.span_err(span, format!("`{msrv}` is not a valid Rust version"));
}
}
None
false
}
},
- ExprKind::Call(repl_func, _) => is_default_equivalent_call(cx, repl_func),
+ ExprKind::Call(repl_func, []) => is_default_equivalent_call(cx, repl_func),
+ ExprKind::Call(from_func, [ref arg]) => is_default_equivalent_from(cx, from_func, arg),
ExprKind::Path(qpath) => is_res_lang_ctor(cx, cx.qpath_res(qpath, e.hir_id), OptionNone),
ExprKind::AddrOf(rustc_hir::BorrowKind::Ref, _, expr) => matches!(expr.kind, ExprKind::Array([])),
_ => false,
}
}
+fn is_default_equivalent_from(cx: &LateContext<'_>, from_func: &Expr<'_>, arg: &Expr<'_>) -> bool {
+ if let ExprKind::Path(QPath::TypeRelative(ty, seg)) = from_func.kind &&
+ seg.ident.name == sym::from
+ {
+ match arg.kind {
+ ExprKind::Lit(hir::Lit {
+ node: LitKind::Str(ref sym, _),
+ ..
+ }) => return sym.is_empty() && is_path_diagnostic_item(cx, ty, sym::String),
+ ExprKind::Array([]) => return is_path_diagnostic_item(cx, ty, sym::Vec),
+ ExprKind::Repeat(_, ArrayLen::Body(len)) => {
+ if let ExprKind::Lit(ref const_lit) = cx.tcx.hir().body(len.body).value.kind &&
+ let LitKind::Int(v, _) = const_lit.node
+ {
+ return v == 0 && is_path_diagnostic_item(cx, ty, sym::Vec);
+ }
+ }
+ _ => (),
+ }
+ }
+ false
+}
+
/// Checks if the top level expression can be moved into a closure as is.
/// Currently checks for:
/// * Break/Continue outside the given loop HIR ids.