@@ -9,10 +9,11 @@ use rustc_data_structures::fx::{FxHashMap, FxHashSet};
99use rustc_hir as hir;
1010use rustc_hir:: def:: { CtorKind , CtorOf , DefKind , Res } ;
1111use rustc_hir:: def_id:: DefId ;
12- use rustc_hir:: { Expr , FnDecl , LangItem , find_attr } ;
12+ use rustc_hir:: { Expr , ExprKind , FnDecl , HirId , LangItem } ;
1313use rustc_hir_analysis:: lower_ty;
1414use rustc_infer:: infer:: TyCtxtInferExt ;
1515use rustc_lint:: LateContext ;
16+ use rustc_lint:: unused:: must_use:: { IsTyMustUse , is_ty_must_use} ;
1617use rustc_middle:: mir:: ConstValue ;
1718use rustc_middle:: mir:: interpret:: Scalar ;
1819use rustc_middle:: traits:: EvaluationResult ;
@@ -310,46 +311,13 @@ pub fn has_drop<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>) -> bool {
310311// Returns whether the `ty` has `#[must_use]` attribute. If `ty` is a `Result`/`ControlFlow`
311312// whose `Err`/`Break` payload is an uninhabited type, the `Ok`/`Continue` payload type
312313// will be used instead. See <https://github.com/rust-lang/rust/pull/148214>.
313- pub fn is_must_use_ty < ' tcx > ( cx : & LateContext < ' tcx > , ty : Ty < ' tcx > ) -> bool {
314- match ty. kind ( ) {
315- ty:: Adt ( adt, args) => match cx. tcx . get_diagnostic_name ( adt. did ( ) ) {
316- Some ( sym:: Result ) if args. type_at ( 1 ) . is_privately_uninhabited ( cx. tcx , cx. typing_env ( ) ) => {
317- is_must_use_ty ( cx, args. type_at ( 0 ) )
318- } ,
319- Some ( sym:: ControlFlow ) if args. type_at ( 0 ) . is_privately_uninhabited ( cx. tcx , cx. typing_env ( ) ) => {
320- is_must_use_ty ( cx, args. type_at ( 1 ) )
321- } ,
322- _ => find_attr ! ( cx. tcx, adt. did( ) , MustUse { .. } ) ,
323- } ,
324- ty:: Foreign ( did) => find_attr ! ( cx. tcx, * did, MustUse { .. } ) ,
325- ty:: Slice ( ty) | ty:: Array ( ty, _) | ty:: RawPtr ( ty, _) | ty:: Ref ( _, ty, _) => {
326- // for the Array case we don't need to care for the len == 0 case
327- // because we don't want to lint functions returning empty arrays
328- is_must_use_ty ( cx, * ty)
329- } ,
330- ty:: Tuple ( args) => args. iter ( ) . any ( |ty| is_must_use_ty ( cx, ty) ) ,
331- ty:: Alias ( ty:: Opaque , AliasTy { def_id, .. } ) => {
332- for ( predicate, _) in cx. tcx . explicit_item_self_bounds ( * def_id) . skip_binder ( ) {
333- if let ty:: ClauseKind :: Trait ( trait_predicate) = predicate. kind ( ) . skip_binder ( )
334- && find_attr ! ( cx. tcx, trait_predicate. trait_ref. def_id, MustUse { .. } )
335- {
336- return true ;
337- }
338- }
339- false
340- } ,
341- ty:: Dynamic ( binder, _) => {
342- for predicate in * binder {
343- if let ty:: ExistentialPredicate :: Trait ( ref trait_ref) = predicate. skip_binder ( )
344- && find_attr ! ( cx. tcx, trait_ref. def_id, MustUse { .. } )
345- {
346- return true ;
347- }
348- }
349- false
350- } ,
351- _ => false ,
352- }
314+ pub fn is_must_use_ty < ' tcx > ( cx : & LateContext < ' tcx > , ty : Ty < ' tcx > , hir_id : HirId ) -> bool {
315+ let dummy_expr = Expr {
316+ hir_id,
317+ span : DUMMY_SP ,
318+ kind : ExprKind :: Ret ( None ) ,
319+ } ;
320+ matches ! ( is_ty_must_use( cx, ty, & dummy_expr, true ) , IsTyMustUse :: Yes ( _) )
353321}
354322
355323/// Returns `true` if the given type is a non aggregate primitive (a `bool` or `char`, any
0 commit comments