about summary refs log tree commit diff
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2023-11-15 04:03:44 +0000
committerbors <bors@rust-lang.org>2023-11-15 04:03:44 +0000
commit783b914fae9c61cdb4c3549e5df7fcbf0caf99e5 (patch)
tree5f253f940da9c1725b6b0a2a31a11bf315a5917e
parentabf01e469b9f9a49fdf96eddb3537f9ab6ae2e4a (diff)
parent3f6b29ad32680d15f878ac89b80402ea447ed306 (diff)
downloadrust-783b914fae9c61cdb4c3549e5df7fcbf0caf99e5.tar.gz
rust-783b914fae9c61cdb4c3549e5df7fcbf0caf99e5.zip
Auto merge of #11804 - y21:issue-11803, r=dswij
[`impl_trait_in_params`]: avoid ICE when function with `impl Trait` type has no parameters

Fixes #11803

If I'm reading the old code correctly, it was taking the span of the first parameter (without checking that it exists, which caused the ICE) and uses that to figure out where the generic parameter to insert should go (cc `@blyxyas` you wrote the lint, is that correct?).
This seemed equivalent to just `generics.span`, which doesn't require calculating the spans like that and simplifies it a fair bit

changelog: don't ICE when function has no parameters but generics have an `impl Trait` type
-rw-r--r--clippy_lints/src/functions/impl_trait_in_params.rs26
-rw-r--r--tests/ui/crashes/ice-11803.rs9
-rw-r--r--tests/ui/crashes/ice-11803.stderr26
3 files changed, 41 insertions, 20 deletions
diff --git a/clippy_lints/src/functions/impl_trait_in_params.rs b/clippy_lints/src/functions/impl_trait_in_params.rs
index 4afff8a2434..8fba41c0e24 100644
--- a/clippy_lints/src/functions/impl_trait_in_params.rs
+++ b/clippy_lints/src/functions/impl_trait_in_params.rs
@@ -5,18 +5,10 @@ use rustc_hir as hir;
 use rustc_hir::intravisit::FnKind;
 use rustc_hir::{Body, GenericParam, Generics, HirId, ImplItem, ImplItemKind, TraitItem, TraitItemKind};
 use rustc_lint::LateContext;
-use rustc_span::symbol::Ident;
-use rustc_span::{BytePos, Span};
 
 use super::IMPL_TRAIT_IN_PARAMS;
 
-fn report(
-    cx: &LateContext<'_>,
-    param: &GenericParam<'_>,
-    ident: &Ident,
-    generics: &Generics<'_>,
-    first_param_span: Span,
-) {
+fn report(cx: &LateContext<'_>, param: &GenericParam<'_>, generics: &Generics<'_>) {
     // No generics with nested generics, and no generics like FnMut(x)
     span_lint_and_then(
         cx,
@@ -35,12 +27,7 @@ fn report(
                 );
             } else {
                 diag.span_suggestion_with_style(
-                    Span::new(
-                        first_param_span.lo() - rustc_span::BytePos(1),
-                        ident.span.hi(),
-                        ident.span.ctxt(),
-                        ident.span.parent(),
-                    ),
+                    generics.span,
                     "add a type parameter",
                     format!("<{{ /* Generic name */ }}: {}>", &param.name.ident().as_str()[5..]),
                     rustc_errors::Applicability::HasPlaceholders,
@@ -52,13 +39,13 @@ fn report(
 }
 
 pub(super) fn check_fn<'tcx>(cx: &LateContext<'_>, kind: &'tcx FnKind<'_>, body: &'tcx Body<'_>, hir_id: HirId) {
-    if let FnKind::ItemFn(ident, generics, _) = kind
+    if let FnKind::ItemFn(_, generics, _) = kind
         && cx.tcx.visibility(cx.tcx.hir().body_owner_def_id(body.id())).is_public()
         && !is_in_test_function(cx.tcx, hir_id)
     {
         for param in generics.params {
             if param.is_impl_trait() {
-                report(cx, param, ident, generics, body.params[0].span);
+                report(cx, param, generics);
             };
         }
     }
@@ -76,7 +63,7 @@ pub(super) fn check_impl_item(cx: &LateContext<'_>, impl_item: &ImplItem<'_>) {
     {
         for param in impl_item.generics.params {
             if param.is_impl_trait() {
-                report(cx, param, &impl_item.ident, impl_item.generics, body.params[0].span);
+                report(cx, param, impl_item.generics);
             }
         }
     }
@@ -92,8 +79,7 @@ pub(super) fn check_trait_item(cx: &LateContext<'_>, trait_item: &TraitItem<'_>,
     {
         for param in trait_item.generics.params {
             if param.is_impl_trait() {
-                let sp = trait_item.ident.span.with_hi(trait_item.ident.span.hi() + BytePos(1));
-                report(cx, param, &trait_item.ident, trait_item.generics, sp.shrink_to_hi());
+                report(cx, param, trait_item.generics);
             }
         }
     }
diff --git a/tests/ui/crashes/ice-11803.rs b/tests/ui/crashes/ice-11803.rs
new file mode 100644
index 00000000000..1bb8bf0c746
--- /dev/null
+++ b/tests/ui/crashes/ice-11803.rs
@@ -0,0 +1,9 @@
+//@no-rustfix
+
+#![warn(clippy::impl_trait_in_params)]
+
+pub fn g<T: IntoIterator<Item = impl Iterator<Item = impl Clone>>>() {
+    extern "C" fn implementation_detail() {}
+}
+
+fn main() {}
diff --git a/tests/ui/crashes/ice-11803.stderr b/tests/ui/crashes/ice-11803.stderr
new file mode 100644
index 00000000000..b8289048a8b
--- /dev/null
+++ b/tests/ui/crashes/ice-11803.stderr
@@ -0,0 +1,26 @@
+error: `impl Trait` used as a function parameter
+  --> $DIR/ice-11803.rs:5:54
+   |
+LL | pub fn g<T: IntoIterator<Item = impl Iterator<Item = impl Clone>>>() {
+   |                                                      ^^^^^^^^^^
+   |
+   = note: `-D clippy::impl-trait-in-params` implied by `-D warnings`
+   = help: to override `-D warnings` add `#[allow(clippy::impl_trait_in_params)]`
+help: add a type parameter
+   |
+LL | pub fn g<T: IntoIterator<Item = impl Iterator<Item = impl Clone>>, { /* Generic name */ }: Clone>() {
+   |                                                                  +++++++++++++++++++++++++++++++
+
+error: `impl Trait` used as a function parameter
+  --> $DIR/ice-11803.rs:5:33
+   |
+LL | pub fn g<T: IntoIterator<Item = impl Iterator<Item = impl Clone>>>() {
+   |                                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+help: add a type parameter
+   |
+LL | pub fn g<T: IntoIterator<Item = impl Iterator<Item = impl Clone>>, { /* Generic name */ }: Iterator<Item = impl Clone>>() {
+   |                                                                  +++++++++++++++++++++++++++++++++++++++++++++++++++++
+
+error: aborting due to 2 previous errors
+