diff options
| author | Dylan DPC <99973273+Dylan-DPC@users.noreply.github.com> | 2022-07-14 14:14:19 +0530 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2022-07-14 14:14:19 +0530 |
| commit | 5a6fe3ff588d2164520a06ef0d27ff6396f5245b (patch) | |
| tree | 1dc36f9f4cbca27370c89917f1a42b3db2aa93c8 | |
| parent | eee0bf459dcdf8ff159e3c8d11600cb73f4519de (diff) | |
| parent | dcd248465ee871bfb5798b8491dfb179fbe4a307 (diff) | |
| download | rust-5a6fe3ff588d2164520a06ef0d27ff6396f5245b.tar.gz rust-5a6fe3ff588d2164520a06ef0d27ff6396f5245b.zip | |
Rollup merge of #97720 - cjgillot:all-fresh, r=petrochenkov
Always create elided lifetime parameters for functions
Anonymous and elided lifetimes in functions are sometimes (async fns) --and sometimes not (regular fns)-- desugared to implicit generic parameters.
This difference of treatment makes it some downstream analyses more complicated to handle. This step is a pre-requisite to perform lifetime elision resolution on AST.
There is currently an inconsistency in the treatment of argument-position impl-trait for functions and async fns:
```rust
trait Foo<'a> {}
fn foo(t: impl Foo<'_>) {} //~ ERROR missing lifetime specifier
async fn async_foo(t: impl Foo<'_>) {} //~ OK
fn bar(t: impl Iterator<Item = &'_ u8>) {} //~ ERROR missing lifetime specifier
async fn async_bar(t: impl Iterator<Item = &'_ u8>) {} //~ OK
```
The current implementation reports "missing lifetime specifier" on `foo`, but **accepts it** in `async_foo`.
This PR **proposes to accept** the anonymous lifetime in both cases as an extra generic lifetime parameter.
This change would be insta-stable, so let's ping t-lang.
Anonymous lifetimes in GAT bindings keep being forbidden:
```rust
fn foo(t: impl Foo<Assoc<'_> = Bar<'_>>) {}
^^ ^^
forbidden ok
```
I started a discussion here: https://rust-lang.zulipchat.com/#narrow/stream/213817-t-lang/topic/Anonymous.20lifetimes.20in.20universal.20impl-trait/near/284968606
r? ``@petrochenkov``
| -rw-r--r-- | clippy_lints/src/inherent_to_string.rs | 4 | ||||
| -rw-r--r-- | clippy_lints/src/lifetimes.rs | 10 | ||||
| -rw-r--r-- | clippy_lints/src/ptr.rs | 3 | ||||
| -rw-r--r-- | clippy_lints/src/types/borrowed_box.rs | 2 |
4 files changed, 12 insertions, 7 deletions
diff --git a/clippy_lints/src/inherent_to_string.rs b/clippy_lints/src/inherent_to_string.rs index 39f68a8a1b4..94db1773fda 100644 --- a/clippy_lints/src/inherent_to_string.rs +++ b/clippy_lints/src/inherent_to_string.rs @@ -2,7 +2,7 @@ use clippy_utils::diagnostics::span_lint_and_help; use clippy_utils::ty::{implements_trait, is_type_diagnostic_item}; use clippy_utils::{get_trait_def_id, paths, return_ty, trait_ref_of_method}; use if_chain::if_chain; -use rustc_hir::{ImplItem, ImplItemKind}; +use rustc_hir::{GenericParamKind, ImplItem, ImplItemKind}; use rustc_lint::{LateContext, LateLintPass}; use rustc_session::{declare_lint_pass, declare_tool_lint}; use rustc_span::sym; @@ -102,7 +102,7 @@ impl<'tcx> LateLintPass<'tcx> for InherentToString { let decl = &signature.decl; if decl.implicit_self.has_implicit_self(); if decl.inputs.len() == 1; - if impl_item.generics.params.is_empty(); + if impl_item.generics.params.iter().all(|p| matches!(p.kind, GenericParamKind::Lifetime { .. })); // Check if return type is String if is_type_diagnostic_item(cx, return_ty(cx, impl_item.hir_id()), sym::String); diff --git a/clippy_lints/src/lifetimes.rs b/clippy_lints/src/lifetimes.rs index 5c0bd57ac50..083c437a293 100644 --- a/clippy_lints/src/lifetimes.rs +++ b/clippy_lints/src/lifetimes.rs @@ -9,8 +9,8 @@ use rustc_hir::intravisit::{ use rustc_hir::FnRetTy::Return; use rustc_hir::{ BareFnTy, BodyId, FnDecl, GenericArg, GenericBound, GenericParam, GenericParamKind, Generics, Impl, ImplItem, - ImplItemKind, Item, ItemKind, LangItem, Lifetime, LifetimeName, ParamName, PolyTraitRef, PredicateOrigin, - TraitBoundModifier, TraitFn, TraitItem, TraitItemKind, Ty, TyKind, WherePredicate, + ImplItemKind, Item, ItemKind, LangItem, Lifetime, LifetimeName, LifetimeParamKind, ParamName, PolyTraitRef, + PredicateOrigin, TraitBoundModifier, TraitFn, TraitItem, TraitItemKind, Ty, TyKind, WherePredicate, }; use rustc_lint::{LateContext, LateLintPass}; use rustc_middle::hir::nested_filter as middle_nested_filter; @@ -338,7 +338,10 @@ fn could_use_elision<'tcx>( fn allowed_lts_from(named_generics: &[GenericParam<'_>]) -> FxHashSet<RefLt> { let mut allowed_lts = FxHashSet::default(); for par in named_generics.iter() { - if let GenericParamKind::Lifetime { .. } = par.kind { + if let GenericParamKind::Lifetime { + kind: LifetimeParamKind::Explicit, + } = par.kind + { allowed_lts.insert(RefLt::Named(par.name.ident().name)); } } @@ -379,6 +382,7 @@ impl<'a, 'tcx> RefVisitor<'a, 'tcx> { self.lts.push(RefLt::Static); } else if let LifetimeName::Param(_, ParamName::Fresh) = lt.name { // Fresh lifetimes generated should be ignored. + self.lts.push(RefLt::Unnamed); } else if lt.is_elided() { self.lts.push(RefLt::Unnamed); } else { diff --git a/clippy_lints/src/ptr.rs b/clippy_lints/src/ptr.rs index 25b73918c0a..8571607054a 100644 --- a/clippy_lints/src/ptr.rs +++ b/clippy_lints/src/ptr.rs @@ -495,12 +495,13 @@ fn check_mut_from_ref<'tcx>(cx: &LateContext<'tcx>, sig: &FnSig<'_>, body: Optio if let FnRetTy::Return(ty) = sig.decl.output && let Some((out, Mutability::Mut, _)) = get_rptr_lm(ty) { + let out_region = cx.tcx.named_region(out.hir_id); let args: Option<Vec<_>> = sig .decl .inputs .iter() .filter_map(get_rptr_lm) - .filter(|&(lt, _, _)| lt.name == out.name) + .filter(|&(lt, _, _)| cx.tcx.named_region(lt.hir_id) == out_region) .map(|(_, mutability, span)| (mutability == Mutability::Not).then(|| span)) .collect(); if let Some(args) = args diff --git a/clippy_lints/src/types/borrowed_box.rs b/clippy_lints/src/types/borrowed_box.rs index f35f44eda56..94945b2e1a9 100644 --- a/clippy_lints/src/types/borrowed_box.rs +++ b/clippy_lints/src/types/borrowed_box.rs @@ -31,7 +31,7 @@ pub(super) fn check(cx: &LateContext<'_>, hir_ty: &hir::Ty<'_>, lt: &Lifetime, m return false; } - let ltopt = if lt.is_elided() { + let ltopt = if lt.name.is_anonymous() { String::new() } else { format!("{} ", lt.name.ident().as_str()) |
