1 //! This module contains functions that retrieve specific elements.
3 #![deny(clippy::missing_docs_in_private_items)]
5 use crate::ty
::is_type_diagnostic_item
;
6 use crate::{is_expn_of, last_path_segment, match_def_path, paths}
;
7 use if_chain
::if_chain
;
8 use rustc_ast
::ast
::{self, LitKind}
;
11 Arm
, Block
, BorrowKind
, Expr
, ExprKind
, HirId
, LoopSource
, MatchSource
, Node
, Pat
, QPath
, StmtKind
, UnOp
,
13 use rustc_lint
::LateContext
;
14 use rustc_span
::{sym, symbol, ExpnKind, Span, Symbol}
;
16 /// The essential nodes of a desugared for loop as well as the entire span:
17 /// `for pat in arg { body }` becomes `(pat, arg, body)`. Return `(pat, arg, body, span)`.
18 pub struct ForLoop
<'tcx
> {
20 pub pat
: &'tcx hir
::Pat
<'tcx
>,
21 /// `IntoIterator` argument
22 pub arg
: &'tcx hir
::Expr
<'tcx
>,
24 pub body
: &'tcx hir
::Expr
<'tcx
>,
25 /// Compare this against `hir::Destination.target`
27 /// entire `for` loop span
31 impl<'tcx
> ForLoop
<'tcx
> {
32 /// Parses a desugared `for` loop
33 pub fn hir(expr
: &Expr
<'tcx
>) -> Option
<Self> {
35 if let hir
::ExprKind
::DropTemps(e
) = expr
.kind
;
36 if let hir
::ExprKind
::Match(iterexpr
, [arm
], hir
::MatchSource
::ForLoopDesugar
) = e
.kind
;
37 if let hir
::ExprKind
::Call(_
, [arg
]) = iterexpr
.kind
;
38 if let hir
::ExprKind
::Loop(block
, ..) = arm
.body
.kind
;
39 if let [stmt
] = &*block
.stmts
;
40 if let hir
::StmtKind
::Expr(e
) = stmt
.kind
;
41 if let hir
::ExprKind
::Match(_
, [_
, some_arm
], _
) = e
.kind
;
42 if let hir
::PatKind
::Struct(_
, [field
], _
) = some_arm
.pat
.kind
;
48 loop_id
: arm
.body
.hir_id
,
49 span
: expr
.span
.ctxt().outer_expn_data().call_site
,
57 /// An `if` expression without `DropTemps`
60 pub cond
: &'hir Expr
<'hir
>,
61 /// `if` then expression
62 pub then
: &'hir Expr
<'hir
>,
64 pub r
#else: Option<&'hir Expr<'hir>>,
69 /// Parses an `if` expression
70 pub const fn hir(expr
: &Expr
<'hir
>) -> Option
<Self> {
73 kind
: ExprKind
::DropTemps(cond
),
80 Some(Self { cond, then, r#else }
)
87 /// An `if let` expression
88 pub struct IfLet
<'hir
> {
90 pub let_pat
: &'hir Pat
<'hir
>,
91 /// `if let` scrutinee
92 pub let_expr
: &'hir Expr
<'hir
>,
93 /// `if let` then expression
94 pub if_then
: &'hir Expr
<'hir
>,
95 /// `if let` else expression
96 pub if_else
: Option
<&'hir Expr
<'hir
>>,
99 impl<'hir
> IfLet
<'hir
> {
100 /// Parses an `if let` expression
101 pub fn hir(cx
: &LateContext
<'_
>, expr
: &Expr
<'hir
>) -> Option
<Self> {
105 ExprKind
::Let(hir
::Let
{
116 let mut iter
= cx
.tcx
.hir().parent_iter(expr
.hir_id
);
117 if let Some((_
, Node
::Block(Block { stmts: [], .. }
))) = iter
.next() {
121 kind
: ExprKind
::Loop(_
, _
, LoopSource
::While
, _
),
126 // while loop desugar
141 /// An `if let` or `match` expression. Useful for lints that trigger on one or the other.
142 pub enum IfLetOrMatch
<'hir
> {
143 /// Any `match` expression
144 Match(&'hir Expr
<'hir
>, &'hir
[Arm
<'hir
>], MatchSource
),
145 /// scrutinee, pattern, then block, else block
150 Option
<&'hir Expr
<'hir
>>,
154 impl<'hir
> IfLetOrMatch
<'hir
> {
155 /// Parses an `if let` or `match` expression
156 pub fn parse(cx
: &LateContext
<'_
>, expr
: &Expr
<'hir
>) -> Option
<Self> {
158 ExprKind
::Match(expr
, arms
, source
) => Some(Self::Match(expr
, arms
, source
)),
159 _
=> IfLet
::hir(cx
, expr
).map(
165 }| { Self::IfLet(let_expr, let_pat, if_then, if_else) }
,
171 /// An `if` or `if let` expression
172 pub struct IfOrIfLet
<'hir
> {
173 /// `if` condition that is maybe a `let` expression
174 pub cond
: &'hir Expr
<'hir
>,
175 /// `if` then expression
176 pub then
: &'hir Expr
<'hir
>,
177 /// `else` expression
178 pub r
#else: Option<&'hir Expr<'hir>>,
181 impl<'hir
> IfOrIfLet
<'hir
> {
183 /// Parses an `if` or `if let` expression
184 pub const fn hir(expr
: &Expr
<'hir
>) -> Option
<Self> {
185 if let ExprKind
::If(cond
, then
, r
#else) = expr.kind {
186 if let ExprKind
::DropTemps(new_cond
) = cond
.kind
{
193 if let ExprKind
::Let(..) = cond
.kind
{
194 return Some(Self { cond, then, r#else }
);
201 /// Represent a range akin to `ast::ExprKind::Range`.
202 #[derive(Debug, Copy, Clone)]
203 pub struct Range
<'a
> {
204 /// The lower bound of the range, or `None` for ranges such as `..X`.
205 pub start
: Option
<&'a hir
::Expr
<'a
>>,
206 /// The upper bound of the range, or `None` for ranges such as `X..`.
207 pub end
: Option
<&'a hir
::Expr
<'a
>>,
208 /// Whether the interval is open or closed.
209 pub limits
: ast
::RangeLimits
,
213 /// Higher a `hir` range to something similar to `ast::ExprKind::Range`.
214 pub fn hir(expr
: &'a hir
::Expr
<'_
>) -> Option
<Range
<'a
>> {
215 /// Finds the field named `name` in the field. Always return `Some` for
217 fn get_field
<'c
>(name
: &str, fields
: &'c
[hir
::ExprField
<'_
>]) -> Option
<&'c hir
::Expr
<'c
>> {
218 let expr
= &fields
.iter().find(|field
| field
.ident
.name
.as_str() == name
)?
.expr
;
223 hir
::ExprKind
::Call(path
, args
)
226 hir
::ExprKind
::Path(hir
::QPath
::LangItem(hir
::LangItem
::RangeInclusiveNew
, ..))
230 start
: Some(&args
[0]),
232 limits
: ast
::RangeLimits
::Closed
,
235 hir
::ExprKind
::Struct(path
, fields
, None
) => match &path
{
236 hir
::QPath
::LangItem(hir
::LangItem
::RangeFull
, ..) => Some(Range
{
239 limits
: ast
::RangeLimits
::HalfOpen
,
241 hir
::QPath
::LangItem(hir
::LangItem
::RangeFrom
, ..) => Some(Range
{
242 start
: Some(get_field("start", fields
)?
),
244 limits
: ast
::RangeLimits
::HalfOpen
,
246 hir
::QPath
::LangItem(hir
::LangItem
::Range
, ..) => Some(Range
{
247 start
: Some(get_field("start", fields
)?
),
248 end
: Some(get_field("end", fields
)?
),
249 limits
: ast
::RangeLimits
::HalfOpen
,
251 hir
::QPath
::LangItem(hir
::LangItem
::RangeToInclusive
, ..) => Some(Range
{
253 end
: Some(get_field("end", fields
)?
),
254 limits
: ast
::RangeLimits
::Closed
,
256 hir
::QPath
::LangItem(hir
::LangItem
::RangeTo
, ..) => Some(Range
{
258 end
: Some(get_field("end", fields
)?
),
259 limits
: ast
::RangeLimits
::HalfOpen
,
268 /// Represent the pre-expansion arguments of a `vec!` invocation.
269 pub enum VecArgs
<'a
> {
270 /// `vec![elem; len]`
271 Repeat(&'a hir
::Expr
<'a
>, &'a hir
::Expr
<'a
>),
273 Vec(&'a
[hir
::Expr
<'a
>]),
276 impl<'a
> VecArgs
<'a
> {
277 /// Returns the arguments of the `vec!` macro if this expression was expanded
279 pub fn hir(cx
: &LateContext
<'_
>, expr
: &'a hir
::Expr
<'_
>) -> Option
<VecArgs
<'a
>> {
281 if let hir
::ExprKind
::Call(fun
, args
) = expr
.kind
;
282 if let hir
::ExprKind
::Path(ref qpath
) = fun
.kind
;
283 if is_expn_of(fun
.span
, "vec").is_some();
284 if let Some(fun_def_id
) = cx
.qpath_res(qpath
, fun
.hir_id
).opt_def_id();
286 return if match_def_path(cx
, fun_def_id
, &paths
::VEC_FROM_ELEM
) && args
.len() == 2 {
287 // `vec![elem; size]` case
288 Some(VecArgs
::Repeat(&args
[0], &args
[1]))
290 else if match_def_path(cx
, fun_def_id
, &paths
::SLICE_INTO_VEC
) && args
.len() == 1 {
291 // `vec![a, b, c]` case
293 if let hir
::ExprKind
::Box(boxed
) = args
[0].kind
;
294 if let hir
::ExprKind
::Array(args
) = boxed
.kind
;
296 return Some(VecArgs
::Vec(args
));
302 else if match_def_path(cx
, fun_def_id
, &paths
::VEC_NEW
) && args
.is_empty() {
303 Some(VecArgs
::Vec(&[]))
315 /// A desugared `while` loop
316 pub struct While
<'hir
> {
317 /// `while` loop condition
318 pub condition
: &'hir Expr
<'hir
>,
319 /// `while` loop body
320 pub body
: &'hir Expr
<'hir
>,
323 impl<'hir
> While
<'hir
> {
325 /// Parses a desugared `while` loop
326 pub const fn hir(expr
: &Expr
<'hir
>) -> Option
<Self> {
327 if let ExprKind
::Loop(
334 kind
: ExprKind
::DropTemps(condition
),
349 return Some(Self { condition, body }
);
355 /// A desugared `while let` loop
356 pub struct WhileLet
<'hir
> {
357 /// `while let` loop item pattern
358 pub let_pat
: &'hir Pat
<'hir
>,
359 /// `while let` loop scrutinee
360 pub let_expr
: &'hir Expr
<'hir
>,
361 /// `while let` loop body
362 pub if_then
: &'hir Expr
<'hir
>,
365 impl<'hir
> WhileLet
<'hir
> {
367 /// Parses a desugared `while let` loop
368 pub const fn hir(expr
: &Expr
<'hir
>) -> Option
<Self> {
369 if let ExprKind
::Loop(
377 ExprKind
::Let(hir
::Let
{
406 /// Converts a hir binary operator to the corresponding `ast` type.
408 pub fn binop(op
: hir
::BinOpKind
) -> ast
::BinOpKind
{
410 hir
::BinOpKind
::Eq
=> ast
::BinOpKind
::Eq
,
411 hir
::BinOpKind
::Ge
=> ast
::BinOpKind
::Ge
,
412 hir
::BinOpKind
::Gt
=> ast
::BinOpKind
::Gt
,
413 hir
::BinOpKind
::Le
=> ast
::BinOpKind
::Le
,
414 hir
::BinOpKind
::Lt
=> ast
::BinOpKind
::Lt
,
415 hir
::BinOpKind
::Ne
=> ast
::BinOpKind
::Ne
,
416 hir
::BinOpKind
::Or
=> ast
::BinOpKind
::Or
,
417 hir
::BinOpKind
::Add
=> ast
::BinOpKind
::Add
,
418 hir
::BinOpKind
::And
=> ast
::BinOpKind
::And
,
419 hir
::BinOpKind
::BitAnd
=> ast
::BinOpKind
::BitAnd
,
420 hir
::BinOpKind
::BitOr
=> ast
::BinOpKind
::BitOr
,
421 hir
::BinOpKind
::BitXor
=> ast
::BinOpKind
::BitXor
,
422 hir
::BinOpKind
::Div
=> ast
::BinOpKind
::Div
,
423 hir
::BinOpKind
::Mul
=> ast
::BinOpKind
::Mul
,
424 hir
::BinOpKind
::Rem
=> ast
::BinOpKind
::Rem
,
425 hir
::BinOpKind
::Shl
=> ast
::BinOpKind
::Shl
,
426 hir
::BinOpKind
::Shr
=> ast
::BinOpKind
::Shr
,
427 hir
::BinOpKind
::Sub
=> ast
::BinOpKind
::Sub
,
431 /// Extract args from an assert-like macro.
432 /// Currently working with:
433 /// - `assert!`, `assert_eq!` and `assert_ne!`
434 /// - `debug_assert!`, `debug_assert_eq!` and `debug_assert_ne!`
436 /// `assert!(expr)` will return `Some([expr])`
437 /// `debug_assert_eq!(a, b)` will return `Some([a, b])`
438 pub fn extract_assert_macro_args
<'tcx
>(e
: &'tcx Expr
<'tcx
>) -> Option
<Vec
<&'tcx Expr
<'tcx
>>> {
439 /// Try to match the AST for a pattern that contains a match, for example when two args are
441 fn ast_matchblock(matchblock_expr
: &'tcx Expr
<'tcx
>) -> Option
<Vec
<&Expr
<'_
>>> {
443 if let ExprKind
::Match(headerexpr
, _
, _
) = &matchblock_expr
.kind
;
444 if let ExprKind
::Tup([lhs
, rhs
]) = &headerexpr
.kind
;
445 if let ExprKind
::AddrOf(BorrowKind
::Ref
, _
, lhs
) = lhs
.kind
;
446 if let ExprKind
::AddrOf(BorrowKind
::Ref
, _
, rhs
) = rhs
.kind
;
448 return Some(vec
![lhs
, rhs
]);
454 if let ExprKind
::Block(block
, _
) = e
.kind
{
455 if block
.stmts
.len() == 1 {
456 if let StmtKind
::Semi(matchexpr
) = block
.stmts
.get(0)?
.kind
{
457 // macros with unique arg: `{debug_}assert!` (e.g., `debug_assert!(some_condition)`)
459 if let Some(If { cond, .. }
) = If
::hir(matchexpr
);
460 if let ExprKind
::Unary(UnOp
::Not
, condition
) = cond
.kind
;
462 return Some(vec
![condition
]);
466 // debug macros with two args: `debug_assert_{ne, eq}` (e.g., `assert_ne!(a, b)`)
468 if let ExprKind
::Block(matchblock
,_
) = matchexpr
.kind
;
469 if let Some(matchblock_expr
) = matchblock
.expr
;
471 return ast_matchblock(matchblock_expr
);
475 } else if let Some(matchblock_expr
) = block
.expr
{
476 // macros with two args: `assert_{ne, eq}` (e.g., `assert_ne!(a, b)`)
477 return ast_matchblock(matchblock_expr
);
483 /// A parsed `format!` expansion
484 pub struct FormatExpn
<'tcx
> {
485 /// Span of `format!(..)`
487 /// Inner `format_args!` expansion
488 pub format_args
: FormatArgsExpn
<'tcx
>,
491 impl FormatExpn
<'tcx
> {
492 /// Parses an expanded `format!` invocation
493 pub fn parse(expr
: &'tcx Expr
<'tcx
>) -> Option
<Self> {
495 if let ExprKind
::Block(block
, _
) = expr
.kind
;
496 if let [stmt
] = block
.stmts
;
497 if let StmtKind
::Local(local
) = stmt
.kind
;
498 if let Some(init
) = local
.init
;
499 if let ExprKind
::Call(_
, [format_args
]) = init
.kind
;
500 let expn_data
= expr
.span
.ctxt().outer_expn_data();
501 if let ExpnKind
::Macro(_
, sym
::format
) = expn_data
.kind
;
502 if let Some(format_args
) = FormatArgsExpn
::parse(format_args
);
505 call_site
: expn_data
.call_site
,
515 /// A parsed `format_args!` expansion
516 pub struct FormatArgsExpn
<'tcx
> {
517 /// Span of the first argument, the format string
518 pub format_string_span
: Span
,
519 /// Values passed after the format string
520 pub value_args
: Vec
<&'tcx Expr
<'tcx
>>,
522 /// String literal expressions which represent the format string split by "{}"
523 pub format_string_parts
: &'tcx
[Expr
<'tcx
>],
524 /// Symbols corresponding to [`Self::format_string_parts`]
525 pub format_string_symbols
: Vec
<Symbol
>,
526 /// Expressions like `ArgumentV1::new(arg0, Debug::fmt)`
527 pub args
: &'tcx
[Expr
<'tcx
>],
528 /// The final argument passed to `Arguments::new_v1_formatted`, if applicable
529 pub fmt_expr
: Option
<&'tcx Expr
<'tcx
>>,
532 impl FormatArgsExpn
<'tcx
> {
533 /// Parses an expanded `format_args!` or `format_args_nl!` invocation
534 pub fn parse(expr
: &'tcx Expr
<'tcx
>) -> Option
<Self> {
536 if let ExpnKind
::Macro(_
, name
) = expr
.span
.ctxt().outer_expn_data().kind
;
537 let name
= name
.as_str();
538 if name
.ends_with("format_args") || name
.ends_with("format_args_nl");
539 if let ExprKind
::Call(_
, args
) = expr
.kind
;
540 if let Some((strs_ref
, args
, fmt_expr
)) = match args
{
542 [strs_ref
, args
] => Some((strs_ref
, args
, None
)),
543 // Arguments::new_v1_formatted
544 [strs_ref
, args
, fmt_expr
, _unsafe_arg
] => Some((strs_ref
, args
, Some(fmt_expr
))),
547 if let ExprKind
::AddrOf(BorrowKind
::Ref
, _
, strs_arr
) = strs_ref
.kind
;
548 if let ExprKind
::Array(format_string_parts
) = strs_arr
.kind
;
549 if let Some(format_string_symbols
) = format_string_parts
552 if let ExprKind
::Lit(lit
) = &e
.kind
{
553 if let LitKind
::Str(symbol
, _style
) = lit
.node
{
560 if let ExprKind
::AddrOf(BorrowKind
::Ref
, _
, args
) = args
.kind
;
561 if let ExprKind
::Match(args
, [arm
], _
) = args
.kind
;
562 if let ExprKind
::Tup(value_args
) = args
.kind
;
563 if let Some(value_args
) = value_args
565 .map(|e
| match e
.kind
{
566 ExprKind
::AddrOf(_
, _
, e
) => Some(e
),
570 if let ExprKind
::Array(args
) = arm
.body
.kind
;
572 Some(FormatArgsExpn
{
573 format_string_span
: strs_ref
.span
,
576 format_string_symbols
,
586 /// Returns a vector of `FormatArgsArg`.
587 pub fn args(&self) -> Option
<Vec
<FormatArgsArg
<'tcx
>>> {
588 if let Some(expr
) = self.fmt_expr
{
590 if let ExprKind
::AddrOf(BorrowKind
::Ref
, _
, expr
) = expr
.kind
;
591 if let ExprKind
::Array(exprs
) = expr
.kind
;
593 exprs
.iter().map(|fmt
| {
595 // struct `core::fmt::rt::v1::Argument`
596 if let ExprKind
::Struct(_
, fields
, _
) = fmt
.kind
;
597 if let Some(position_field
) = fields
.iter().find(|f
| f
.ident
.name
== sym
::position
);
598 if let ExprKind
::Lit(lit
) = &position_field
.expr
.kind
;
599 if let LitKind
::Int(position
, _
) = lit
.node
;
600 if let Ok(i
) = usize::try_from(position
);
601 let arg
= &self.args
[i
];
602 if let ExprKind
::Call(_
, [arg_name
, _
]) = arg
.kind
;
603 if let ExprKind
::Field(_
, j
) = arg_name
.kind
;
604 if let Ok(j
) = j
.name
.as_str().parse
::<usize>();
606 Some(FormatArgsArg { value: self.value_args[j], arg, fmt: Some(fmt) }
)
620 .zip(self.args
.iter())
621 .map(|(value
, arg
)| FormatArgsArg { value, arg, fmt: None }
)
628 /// Type representing a `FormatArgsExpn`'s format arguments
629 pub struct FormatArgsArg
<'tcx
> {
630 /// An element of `value_args` according to `position`
631 pub value
: &'tcx Expr
<'tcx
>,
632 /// An element of `args` according to `position`
633 pub arg
: &'tcx Expr
<'tcx
>,
634 /// An element of `fmt_expn`
635 pub fmt
: Option
<&'tcx Expr
<'tcx
>>,
638 impl<'tcx
> FormatArgsArg
<'tcx
> {
639 /// Returns true if any formatting parameters are used that would have an effect on strings,
640 /// like `{:+2}` instead of just `{}`.
641 pub fn has_string_formatting(&self) -> bool
{
642 self.fmt
.map_or(false, |fmt
| {
643 // `!` because these conditions check that `self` is unformatted.
645 // struct `core::fmt::rt::v1::Argument`
646 if let ExprKind
::Struct(_
, fields
, _
) = fmt
.kind
;
647 if let Some(format_field
) = fields
.iter().find(|f
| f
.ident
.name
== sym
::format
);
648 // struct `core::fmt::rt::v1::FormatSpec`
649 if let ExprKind
::Struct(_
, subfields
, _
) = format_field
.expr
.kind
;
650 let mut precision_found
= false;
651 let mut width_found
= false;
652 if subfields
.iter().all(|field
| {
653 match field
.ident
.name
{
655 precision_found
= true;
656 if let ExprKind
::Path(ref precision_path
) = field
.expr
.kind
{
657 last_path_segment(precision_path
).ident
.name
== sym
::Implied
664 if let ExprKind
::Path(ref width_qpath
) = field
.expr
.kind
{
665 last_path_segment(width_qpath
).ident
.name
== sym
::Implied
673 if precision_found
&& width_found
;
674 then { true }
else { false }
679 /// Returns true if the argument is formatted using `Display::fmt`.
680 pub fn is_display(&self) -> bool
{
682 if let ExprKind
::Call(_
, [_
, format_field
]) = self.arg
.kind
;
683 if let ExprKind
::Path(QPath
::Resolved(_
, path
)) = format_field
.kind
;
684 if let [.., t
, _
] = path
.segments
;
685 if t
.ident
.name
== sym
::Display
;
686 then { true }
else { false }
691 /// A parsed `panic!` expansion
692 pub struct PanicExpn
<'tcx
> {
693 /// Span of `panic!(..)`
695 /// Inner `format_args!` expansion
696 pub format_args
: FormatArgsExpn
<'tcx
>,
699 impl PanicExpn
<'tcx
> {
700 /// Parses an expanded `panic!` invocation
701 pub fn parse(expr
: &'tcx Expr
<'tcx
>) -> Option
<Self> {
703 if let ExprKind
::Call(_
, [format_args
]) = expr
.kind
;
704 let expn_data
= expr
.span
.ctxt().outer_expn_data();
705 if let Some(format_args
) = FormatArgsExpn
::parse(format_args
);
708 call_site
: expn_data
.call_site
,
718 /// A parsed `Vec` initialization expression
719 #[derive(Clone, Copy)]
720 pub enum VecInitKind
{
723 /// `Vec::default()` or `Default::default()`
725 /// `Vec::with_capacity(123)`
726 WithLiteralCapacity(u64),
727 /// `Vec::with_capacity(slice.len())`
728 WithExprCapacity(HirId
),
731 /// Checks if given expression is an initialization of `Vec` and returns its kind.
732 pub fn get_vec_init_kind
<'tcx
>(cx
: &LateContext
<'tcx
>, expr
: &'tcx Expr
<'tcx
>) -> Option
<VecInitKind
> {
733 if let ExprKind
::Call(func
, args
) = expr
.kind
{
735 ExprKind
::Path(QPath
::TypeRelative(ty
, name
))
736 if is_type_diagnostic_item(cx
, cx
.typeck_results().node_type(ty
.hir_id
), sym
::Vec
) =>
738 if name
.ident
.name
== sym
::new
{
739 return Some(VecInitKind
::New
);
740 } else if name
.ident
.name
== symbol
::kw
::Default
{
741 return Some(VecInitKind
::Default
);
742 } else if name
.ident
.name
.as_str() == "with_capacity" {
743 let arg
= args
.get(0)?
;
745 if let ExprKind
::Lit(lit
) = &arg
.kind
;
746 if let LitKind
::Int(num
, _
) = lit
.node
;
748 return Some(VecInitKind
::WithLiteralCapacity(num
.try_into().ok()?
))
751 return Some(VecInitKind
::WithExprCapacity(arg
.hir_id
));
754 ExprKind
::Path(QPath
::Resolved(_
, path
))
755 if match_def_path(cx
, path
.res
.opt_def_id()?
, &paths
::DEFAULT_TRAIT_METHOD
)
756 && is_type_diagnostic_item(cx
, cx
.typeck_results().expr_ty(expr
), sym
::Vec
) =>
758 return Some(VecInitKind
::Default
);