11use clippy_utils:: diagnostics:: span_lint_and_sugg;
22use clippy_utils:: numeric_literal:: NumericLiteral ;
3- use clippy_utils:: res:: MaybeResPath ;
3+ use clippy_utils:: res:: MaybeResPath as _ ;
44use clippy_utils:: source:: { SpanRangeExt , snippet_opt} ;
55use clippy_utils:: visitors:: { Visitable , for_each_expr_without_closures} ;
66use clippy_utils:: { get_parent_expr, is_hir_ty_cfg_dependant, is_ty_alias} ;
77use rustc_ast:: { LitFloatType , LitIntType , LitKind } ;
88use rustc_errors:: Applicability ;
99use rustc_hir:: def:: { DefKind , Res } ;
10- use rustc_hir:: { Expr , ExprKind , Lit , Node , Path , QPath , TyKind , UnOp } ;
10+ use rustc_hir:: { Expr , ExprKind , FnRetTy , Lit , Node , Path , QPath , TyKind , UnOp } ;
1111use rustc_lint:: { LateContext , LintContext } ;
1212use rustc_middle:: ty:: adjustment:: Adjust ;
1313use rustc_middle:: ty:: { self , FloatTy , InferTy , Ty } ;
@@ -97,7 +97,7 @@ pub(super) fn check<'tcx>(
9797
9898 // skip cast of fn call that returns type alias
9999 if let ExprKind :: Cast ( inner, ..) = expr. kind
100- && is_cast_from_ty_alias ( cx, inner, cast_from )
100+ && is_cast_from_ty_alias ( cx, inner)
101101 {
102102 return false ;
103103 }
@@ -270,42 +270,33 @@ fn fp_ty_mantissa_nbits(typ: Ty<'_>) -> u32 {
270270
271271/// Finds whether an `Expr` returns a type alias.
272272///
273- /// TODO: Maybe we should move this to `clippy_utils` so others won't need to go down this dark,
274- /// dark path reimplementing this (or something similar) .
275- fn is_cast_from_ty_alias < ' tcx > ( cx : & LateContext < ' tcx > , expr : impl Visitable < ' tcx > , cast_from : Ty < ' tcx > ) -> bool {
273+ /// When in doubt, for example because it calls a non-local function that we don't have the
274+ /// declaration for, assume if might be a type alias .
275+ fn is_cast_from_ty_alias < ' tcx > ( cx : & LateContext < ' tcx > , expr : impl Visitable < ' tcx > ) -> bool {
276276 for_each_expr_without_closures ( expr, |expr| {
277277 // Calls are a `Path`, and usage of locals are a `Path`. So, this checks
278278 // - call() as i32
279279 // - local as i32
280280 if let ExprKind :: Path ( qpath) = expr. kind {
281281 let res = cx. qpath_res ( & qpath, expr. hir_id ) ;
282- // Function call
283282 if let Res :: Def ( DefKind :: Fn , def_id) = res {
284- let Some ( snippet) = cx. tcx . def_span ( def_id) . get_source_text ( cx) else {
285- return ControlFlow :: Continue ( ( ) ) ;
283+ let Some ( def_id) = def_id. as_local ( ) else {
284+ // External function, we can't know, better be safe
285+ return ControlFlow :: Break ( ( ) ) ;
286286 } ;
287- // This is the worst part of this entire function. This is the only way I know of to
288- // check whether a function returns a type alias. Sure, you can get the return type
289- // from a function in the current crate as an hir ty, but how do you get it for
290- // external functions?? Simple: It's impossible. So, we check whether a part of the
291- // function's declaration snippet is exactly equal to the `Ty`. That way, we can
292- // see whether it's a type alias.
293- //
294- // FIXME: This won't work if the type is given an alias through `use`, should we
295- // consider this a type alias as well?
296- if !snippet
297- . split ( "->" )
298- . skip ( 1 )
299- . any ( |s| snippet_eq_ty ( s, cast_from) || s. split ( "where" ) . any ( |ty| snippet_eq_ty ( ty, cast_from) ) )
287+ if let Some ( FnRetTy :: Return ( ty) ) = cx. tcx . hir_get_fn_output ( def_id)
288+ && let TyKind :: Path ( qpath) = ty. kind
289+ && is_ty_alias ( & qpath)
300290 {
291+ // Function call to a local function returning a type alias
301292 return ControlFlow :: Break ( ( ) ) ;
302293 }
303294 // Local usage
304295 } else if let Res :: Local ( hir_id) = res
305296 && let Node :: LetStmt ( l) = cx. tcx . parent_hir_node ( hir_id)
306297 {
307298 if let Some ( e) = l. init
308- && is_cast_from_ty_alias ( cx, e, cast_from )
299+ && is_cast_from_ty_alias ( cx, e)
309300 {
310301 return ControlFlow :: Break :: < ( ) > ( ( ) ) ;
311302 }
@@ -323,7 +314,3 @@ fn is_cast_from_ty_alias<'tcx>(cx: &LateContext<'tcx>, expr: impl Visitable<'tcx
323314 } )
324315 . is_some ( )
325316}
326-
327- fn snippet_eq_ty ( snippet : & str , ty : Ty < ' _ > ) -> bool {
328- snippet. trim ( ) == ty. to_string ( ) || snippet. trim ( ) . contains ( & format ! ( "::{ty}" ) )
329- }
0 commit comments