Skip to content

Commit 84182ff

Browse files
committed
Check for 'static lifetime in return type
1 parent 9529d2b commit 84182ff

File tree

3 files changed

+21
-18
lines changed

3 files changed

+21
-18
lines changed

clippy_lints/src/eta_reduction.rs

Lines changed: 18 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,7 @@ use rustc_hir::{BindingMode, Expr, ExprKind, FnRetTy, Param, PatKind, QPath, Saf
99
use rustc_infer::infer::TyCtxtInferExt;
1010
use rustc_lint::{LateContext, LateLintPass};
1111
use rustc_middle::ty::{
12-
self, Binder, ClosureKind, FnSig, GenericArg, GenericArgKind, List, Region, RegionKind, Ty, TypeVisitableExt,
13-
TypeckResults,
12+
self, Binder, ClosureKind, FnSig, GenericArg, GenericArgKind, List, Region, Ty, TypeVisitableExt, TypeckResults,
1413
};
1514
use rustc_session::declare_lint_pass;
1615
use rustc_span::symbol::sym;
@@ -176,6 +175,17 @@ fn check_clousure<'tcx>(cx: &LateContext<'tcx>, outer_receiver: Option<&Expr<'tc
176175
}
177176
},
178177
};
178+
if let Some(outer) = outer_receiver
179+
&& ty_has_static(sig.output())
180+
&& let generic_args = typeck.node_args(outer.hir_id)
181+
// Given a closure in `T.method(|| f())`, where `fn f() -> U where U: 'static`, `T.method(f)`
182+
// will succeed iff `T: 'static`.
183+
// But the region of `T` is always erased by `typeck.expr_ty()`. So we have a hack like this.
184+
// && dbg!(generic_args).len() > 0
185+
&& generic_args.len() > 0
186+
{
187+
return;
188+
}
179189
if check_sig(closure_sig, sig)
180190
&& let generic_args = typeck.node_args(callee.hir_id)
181191
// Given some trait fn `fn f() -> ()` and some type `T: Trait`, `T::f` is not
@@ -275,7 +285,7 @@ fn check_sig<'tcx>(closure_sig: FnSig<'tcx>, call_sig: FnSig<'tcx>) -> bool {
275285
/// This is needed because rustc is unable to late bind early-bound regions in a function signature.
276286
fn has_late_bound_to_non_late_bound_regions(from_sig: FnSig<'_>, to_sig: FnSig<'_>) -> bool {
277287
fn check_region(from_region: Region<'_>, to_region: Region<'_>) -> bool {
278-
matches!(from_region.kind(), RegionKind::ReBound(..)) && !matches!(to_region.kind(), RegionKind::ReBound(..))
288+
from_region.is_bound() && !to_region.is_bound()
279289
}
280290

281291
fn check_subs(from_subs: &[GenericArg<'_>], to_subs: &[GenericArg<'_>]) -> bool {
@@ -328,3 +338,8 @@ fn has_late_bound_to_non_late_bound_regions(from_sig: FnSig<'_>, to_sig: FnSig<'
328338
.zip(to_sig.inputs_and_output)
329339
.any(|(from_ty, to_ty)| check_ty(from_ty, to_ty))
330340
}
341+
342+
fn ty_has_static(ty: Ty<'_>) -> bool {
343+
ty.walk()
344+
.any(|arg| matches!(arg.unpack(), GenericArgKind::Lifetime(re) if re.is_static()))
345+
}

tests/ui/eta.fixed

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -492,9 +492,9 @@ mod issue_13073 {
492492
pub fn foo() {
493493
// shouldn't lint
494494
let bind: Option<String> = None;
495-
let _field = bind.as_deref().or_else(get_default).unwrap();
495+
let _field = bind.as_deref().or_else(|| get_default()).unwrap();
496496
let bind: Option<&'static str> = None;
497-
let _field = bind.as_deref().or_else(get_default).unwrap();
497+
let _field = bind.as_deref().or_else(|| get_default()).unwrap();
498498
// should lint
499499
let _field = bind.or_else(get_default).unwrap();
500500
}

tests/ui/eta.stderr

Lines changed: 1 addition & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -202,23 +202,11 @@ error: redundant closure
202202
LL | let x = Box::new(|| None.map(|x| f(x)));
203203
| ^^^^^^^^ help: replace the closure with the function itself: `f`
204204

205-
error: redundant closure
206-
--> tests/ui/eta.rs:495:46
207-
|
208-
LL | let _field = bind.as_deref().or_else(|| get_default()).unwrap();
209-
| ^^^^^^^^^^^^^^^^ help: replace the closure with the function itself: `get_default`
210-
211-
error: redundant closure
212-
--> tests/ui/eta.rs:497:46
213-
|
214-
LL | let _field = bind.as_deref().or_else(|| get_default()).unwrap();
215-
| ^^^^^^^^^^^^^^^^ help: replace the closure with the function itself: `get_default`
216-
217205
error: redundant closure
218206
--> tests/ui/eta.rs:499:35
219207
|
220208
LL | let _field = bind.or_else(|| get_default()).unwrap();
221209
| ^^^^^^^^^^^^^^^^ help: replace the closure with the function itself: `get_default`
222210

223-
error: aborting due to 36 previous errors
211+
error: aborting due to 34 previous errors
224212

0 commit comments

Comments
 (0)