@@ -60,18 +60,39 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UnusedResults {
6060 }
6161
6262 let t = cx. tables . expr_ty ( & expr) ;
63- // FIXME(varkor): replace with `t.is_unit() || t.conservative_is_uninhabited()`.
64- let type_permits_no_use = match t. sty {
65- ty:: Tuple ( ref tys) if tys. is_empty ( ) => true ,
66- ty:: Never => true ,
67- ty:: Adt ( def, _) => {
68- if def. variants . is_empty ( ) {
69- true
70- } else {
71- check_must_use ( cx, def. did , s. span , "" )
63+ let type_permits_lack_of_use = if t. is_unit ( )
64+ || cx. tcx . is_ty_uninhabited_from ( cx. tcx . hir . get_module_parent ( expr. id ) , t) {
65+ true
66+ } else {
67+ match t. sty {
68+ ty:: Adt ( def, _) => check_must_use ( cx, def. did , s. span , "" , "" ) ,
69+ ty:: Opaque ( def, _) => {
70+ let mut must_use = false ;
71+ for ( predicate, _) in & cx. tcx . predicates_of ( def) . predicates {
72+ if let ty:: Predicate :: Trait ( ref poly_trait_predicate) = predicate {
73+ let trait_ref = poly_trait_predicate. skip_binder ( ) . trait_ref ;
74+ if check_must_use ( cx, trait_ref. def_id , s. span , "implementer of " , "" ) {
75+ must_use = true ;
76+ break ;
77+ }
78+ }
79+ }
80+ must_use
81+ }
82+ ty:: Dynamic ( binder, _) => {
83+ let mut must_use = false ;
84+ for predicate in binder. skip_binder ( ) . iter ( ) {
85+ if let ty:: ExistentialPredicate :: Trait ( ref trait_ref) = predicate {
86+ if check_must_use ( cx, trait_ref. def_id , s. span , "" , " trait object" ) {
87+ must_use = true ;
88+ break ;
89+ }
90+ }
91+ }
92+ must_use
7293 }
94+ _ => false ,
7395 }
74- _ => false ,
7596 } ;
7697
7798 let mut fn_warned = false ;
@@ -98,8 +119,8 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UnusedResults {
98119 } ;
99120 if let Some ( def) = maybe_def {
100121 let def_id = def. def_id ( ) ;
101- fn_warned = check_must_use ( cx, def_id, s. span , "return value of " ) ;
102- } else if type_permits_no_use {
122+ fn_warned = check_must_use ( cx, def_id, s. span , "return value of " , "" ) ;
123+ } else if type_permits_lack_of_use {
103124 // We don't warn about unused unit or uninhabited types.
104125 // (See https://github.com/rust-lang/rust/issues/43806 for details.)
105126 return ;
@@ -148,15 +169,21 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UnusedResults {
148169 op_warned = true ;
149170 }
150171
151- if !( type_permits_no_use || fn_warned || op_warned) {
172+ if !( type_permits_lack_of_use || fn_warned || op_warned) {
152173 cx. span_lint ( UNUSED_RESULTS , s. span , "unused result" ) ;
153174 }
154175
155- fn check_must_use ( cx : & LateContext , def_id : DefId , sp : Span , describe_path : & str ) -> bool {
176+ fn check_must_use (
177+ cx : & LateContext ,
178+ def_id : DefId ,
179+ sp : Span ,
180+ descr_pre_path : & str ,
181+ descr_post_path : & str ,
182+ ) -> bool {
156183 for attr in cx. tcx . get_attrs ( def_id) . iter ( ) {
157184 if attr. check_name ( "must_use" ) {
158- let msg = format ! ( "unused {}`{}` that must be used" ,
159- describe_path , cx. tcx. item_path_str( def_id) ) ;
185+ let msg = format ! ( "unused {}`{}`{} that must be used" ,
186+ descr_pre_path , cx. tcx. item_path_str( def_id) , descr_post_path ) ;
160187 let mut err = cx. struct_span_lint ( UNUSED_MUST_USE , sp, & msg) ;
161188 // check for #[must_use = "..."]
162189 if let Some ( note) = attr. value_str ( ) {
0 commit comments