@@ -47,42 +47,14 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UnusedResults {
4747 return ;
4848 }
4949
50- let t = cx. tables . expr_ty ( & expr) ;
51- let type_permits_lack_of_use = if t . is_unit ( )
50+ let ty = cx. tables . expr_ty ( & expr) ;
51+ let type_permits_lack_of_use = if ty . is_unit ( )
5252 || cx. tcx . is_ty_uninhabited_from (
53- cx. tcx . hir ( ) . get_module_parent_by_hir_id ( expr. hir_id ) , t )
53+ cx. tcx . hir ( ) . get_module_parent_by_hir_id ( expr. hir_id ) , ty )
5454 {
5555 true
5656 } else {
57- match t. sty {
58- ty:: Adt ( def, _) => check_must_use ( cx, def. did , s. span , "" , "" ) ,
59- ty:: Opaque ( def, _) => {
60- let mut must_use = false ;
61- for ( predicate, _) in & cx. tcx . predicates_of ( def) . predicates {
62- if let ty:: Predicate :: Trait ( ref poly_trait_predicate) = predicate {
63- let trait_ref = poly_trait_predicate. skip_binder ( ) . trait_ref ;
64- if check_must_use ( cx, trait_ref. def_id , s. span , "implementer of " , "" ) {
65- must_use = true ;
66- break ;
67- }
68- }
69- }
70- must_use
71- }
72- ty:: Dynamic ( binder, _) => {
73- let mut must_use = false ;
74- for predicate in binder. skip_binder ( ) . iter ( ) {
75- if let ty:: ExistentialPredicate :: Trait ( ref trait_ref) = predicate {
76- if check_must_use ( cx, trait_ref. def_id , s. span , "" , " trait object" ) {
77- must_use = true ;
78- break ;
79- }
80- }
81- }
82- must_use
83- }
84- _ => false ,
85- }
57+ check_must_use_ty ( cx, ty, s. span )
8658 } ;
8759
8860 let mut fn_warned = false ;
@@ -108,7 +80,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UnusedResults {
10880 _ => None
10981 } ;
11082 if let Some ( def_id) = maybe_def_id {
111- fn_warned = check_must_use ( cx, def_id, s. span , "return value of " , "" ) ;
83+ fn_warned = check_must_use_def ( cx, def_id, s. span , "return value of " , "" ) ;
11284 } else if type_permits_lack_of_use {
11385 // We don't warn about unused unit or uninhabited types.
11486 // (See https://github.com/rust-lang/rust/issues/43806 for details.)
@@ -162,18 +134,63 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UnusedResults {
162134 cx. span_lint ( UNUSED_RESULTS , s. span , "unused result" ) ;
163135 }
164136
165- fn check_must_use (
137+ // Returns whether an error has been emitted (and thus another does not need to be later).
138+ fn check_must_use_ty (
139+ cx : & LateContext < ' _ , ' _ > ,
140+ ty : ty:: Ty < ' _ > ,
141+ span : Span ,
142+ ) -> bool {
143+ match ty. sty {
144+ ty:: Adt ( def, _) => check_must_use_def ( cx, def. did , span, "" , "" ) ,
145+ ty:: Opaque ( def, _) => {
146+ let mut has_emitted = false ;
147+ for ( predicate, _) in & cx. tcx . predicates_of ( def) . predicates {
148+ if let ty:: Predicate :: Trait ( ref poly_trait_predicate) = predicate {
149+ let trait_ref = poly_trait_predicate. skip_binder ( ) . trait_ref ;
150+ let def_id = trait_ref. def_id ;
151+ if check_must_use_def ( cx, def_id, span, "implementer of " , "" ) {
152+ has_emitted = true ;
153+ break ;
154+ }
155+ }
156+ }
157+ has_emitted
158+ }
159+ ty:: Dynamic ( binder, _) => {
160+ let mut has_emitted = false ;
161+ for predicate in binder. skip_binder ( ) . iter ( ) {
162+ if let ty:: ExistentialPredicate :: Trait ( ref trait_ref) = predicate {
163+ let def_id = trait_ref. def_id ;
164+ if check_must_use_def ( cx, def_id, span, "" , " trait object" ) {
165+ has_emitted = true ;
166+ break ;
167+ }
168+ }
169+ }
170+ has_emitted
171+ }
172+ ty:: Tuple ( ref tys) => {
173+ tys. iter ( ) . map ( |k| k. expect_ty ( ) ) . any ( |ty| {
174+ check_must_use_ty ( cx, ty, span)
175+ } )
176+ }
177+ _ => false ,
178+ }
179+ }
180+
181+ // Returns whether an error has been emitted (and thus another does not need to be later).
182+ fn check_must_use_def (
166183 cx : & LateContext < ' _ , ' _ > ,
167184 def_id : DefId ,
168- sp : Span ,
185+ span : Span ,
169186 descr_pre_path : & str ,
170187 descr_post_path : & str ,
171188 ) -> bool {
172189 for attr in cx. tcx . get_attrs ( def_id) . iter ( ) {
173190 if attr. check_name ( sym:: must_use) {
174191 let msg = format ! ( "unused {}`{}`{} that must be used" ,
175192 descr_pre_path, cx. tcx. def_path_str( def_id) , descr_post_path) ;
176- let mut err = cx. struct_span_lint ( UNUSED_MUST_USE , sp , & msg) ;
193+ let mut err = cx. struct_span_lint ( UNUSED_MUST_USE , span , & msg) ;
177194 // check for #[must_use = "..."]
178195 if let Some ( note) = attr. value_str ( ) {
179196 err. note ( & note. as_str ( ) ) ;
0 commit comments