about summary refs log tree commit diff
diff options
context:
space:
mode:
authorMatthias Krüger <matthias.krueger@famsik.de>2024-06-14 08:35:48 +0200
committerGitHub <noreply@github.com>2024-06-14 08:35:48 +0200
commit74e82328cefb8ff7e4c4f32e319e60b7ed70ccf7 (patch)
treeea2ec8865d3a4370b7f3cdcec0123222a326bdf1
parentbfa098eae0b5667a8cb5bbbe990a2d7e8445571f (diff)
parent417460027e544b7f034c4d79678b5088279eeb7b (diff)
downloadrust-74e82328cefb8ff7e4c4f32e319e60b7ed70ccf7.tar.gz
rust-74e82328cefb8ff7e4c4f32e319e60b7ed70ccf7.zip
Rollup merge of #124884 - bvanjoi:fix-124785, r=estebank
place explicit lifetime bound after generic param

Fixes #124785

An easy fix.
-rw-r--r--compiler/rustc_infer/src/infer/error_reporting/mod.rs18
-rw-r--r--tests/ui/generic-associated-types/static-lifetime-tip-with-default-type.rs26
-rw-r--r--tests/ui/generic-associated-types/static-lifetime-tip-with-default-type.stderr110
3 files changed, 151 insertions, 3 deletions
diff --git a/compiler/rustc_infer/src/infer/error_reporting/mod.rs b/compiler/rustc_infer/src/infer/error_reporting/mod.rs
index 7fb07a5d30c..e15866f3f0f 100644
--- a/compiler/rustc_infer/src/infer/error_reporting/mod.rs
+++ b/compiler/rustc_infer/src/infer/error_reporting/mod.rs
@@ -64,11 +64,11 @@ use rustc_errors::{
     codes::*, pluralize, struct_span_code_err, Applicability, Diag, DiagCtxt, DiagStyledString,
     ErrorGuaranteed, IntoDiagArg, StringPart,
 };
-use rustc_hir as hir;
 use rustc_hir::def::DefKind;
 use rustc_hir::def_id::{DefId, LocalDefId};
 use rustc_hir::intravisit::Visitor;
 use rustc_hir::lang_items::LangItem;
+use rustc_hir::{self as hir, ParamName};
 use rustc_macros::extension;
 use rustc_middle::bug;
 use rustc_middle::dep_graph::DepContext;
@@ -2429,7 +2429,8 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
             let (type_scope, type_param_sugg_span) = match bound_kind {
                 GenericKind::Param(param) => {
                     let generics = self.tcx.generics_of(generic_param_scope);
-                    let def_id = generics.type_param(param, self.tcx).def_id.expect_local();
+                    let type_param = generics.type_param(param, self.tcx);
+                    let def_id = type_param.def_id.expect_local();
                     let scope = self.tcx.local_def_id_to_hir_id(def_id).owner.def_id;
                     // Get the `hir::Param` to verify whether it already has any bounds.
                     // We do this to avoid suggesting code that ends up as `T: 'a'b`,
@@ -2439,7 +2440,18 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
                         Some((span, open_paren_sp)) => Some((span, true, open_paren_sp)),
                         // If `param` corresponds to `Self`, no usable suggestion span.
                         None if generics.has_self && param.index == 0 => None,
-                        None => Some((self.tcx.def_span(def_id).shrink_to_hi(), false, None)),
+                        None => {
+                            let span = if let Some(param) =
+                                hir_generics.params.iter().find(|param| param.def_id == def_id)
+                                && let ParamName::Plain(ident) = param.name
+                            {
+                                ident.span.shrink_to_hi()
+                            } else {
+                                let span = self.tcx.def_span(def_id);
+                                span.shrink_to_hi()
+                            };
+                            Some((span, false, None))
+                        }
                     };
                     (scope, sugg_span)
                 }
diff --git a/tests/ui/generic-associated-types/static-lifetime-tip-with-default-type.rs b/tests/ui/generic-associated-types/static-lifetime-tip-with-default-type.rs
new file mode 100644
index 00000000000..68879a0af29
--- /dev/null
+++ b/tests/ui/generic-associated-types/static-lifetime-tip-with-default-type.rs
@@ -0,0 +1,26 @@
+//@ error-pattern: r#T: 'static
+//@ error-pattern: r#K: 'static
+//@ error-pattern: T: 'static=
+
+// https://github.com/rust-lang/rust/issues/124785
+
+struct Foo<T, K = i32>(&'static T, &'static K);
+//~^ ERROR: the parameter type `T` may not live long enough
+//~| ERROR: the parameter type `K` may not live long enough
+
+struct Bar<r#T, r#K = i32>(&'static r#T, &'static r#K);
+//~^ ERROR: the parameter type `T` may not live long enough
+//~| ERROR: the parameter type `K` may not live long enough
+
+struct Boo<T= i32>(&'static T);
+//~^ ERROR: the parameter type `T` may not live long enough
+
+struct Far<T
+= i32>(&'static T);
+//~^ ERROR: the parameter type `T` may not live long enough
+
+struct S<'a, K: 'a = i32>(&'static K);
+//~^ ERROR: lifetime parameter `'a` is never used
+//~| ERROR: the parameter type `K` may not live long enough
+
+fn main() {}
diff --git a/tests/ui/generic-associated-types/static-lifetime-tip-with-default-type.stderr b/tests/ui/generic-associated-types/static-lifetime-tip-with-default-type.stderr
new file mode 100644
index 00000000000..7d985a9013f
--- /dev/null
+++ b/tests/ui/generic-associated-types/static-lifetime-tip-with-default-type.stderr
@@ -0,0 +1,110 @@
+error[E0310]: the parameter type `T` may not live long enough
+  --> $DIR/static-lifetime-tip-with-default-type.rs:7:24
+   |
+LL | struct Foo<T, K = i32>(&'static T, &'static K);
+   |                        ^^^^^^^^^^
+   |                        |
+   |                        the parameter type `T` must be valid for the static lifetime...
+   |                        ...so that the reference type `&'static T` does not outlive the data it points at
+   |
+help: consider adding an explicit lifetime bound
+   |
+LL | struct Foo<T: 'static, K = i32>(&'static T, &'static K);
+   |             +++++++++
+
+error[E0310]: the parameter type `K` may not live long enough
+  --> $DIR/static-lifetime-tip-with-default-type.rs:7:36
+   |
+LL | struct Foo<T, K = i32>(&'static T, &'static K);
+   |                                    ^^^^^^^^^^
+   |                                    |
+   |                                    the parameter type `K` must be valid for the static lifetime...
+   |                                    ...so that the reference type `&'static K` does not outlive the data it points at
+   |
+help: consider adding an explicit lifetime bound
+   |
+LL | struct Foo<T, K: 'static = i32>(&'static T, &'static K);
+   |                +++++++++
+
+error[E0310]: the parameter type `T` may not live long enough
+  --> $DIR/static-lifetime-tip-with-default-type.rs:11:28
+   |
+LL | struct Bar<r#T, r#K = i32>(&'static r#T, &'static r#K);
+   |                            ^^^^^^^^^^^^
+   |                            |
+   |                            the parameter type `T` must be valid for the static lifetime...
+   |                            ...so that the reference type `&'static T` does not outlive the data it points at
+   |
+help: consider adding an explicit lifetime bound
+   |
+LL | struct Bar<r#T: 'static, r#K = i32>(&'static r#T, &'static r#K);
+   |               +++++++++
+
+error[E0310]: the parameter type `K` may not live long enough
+  --> $DIR/static-lifetime-tip-with-default-type.rs:11:42
+   |
+LL | struct Bar<r#T, r#K = i32>(&'static r#T, &'static r#K);
+   |                                          ^^^^^^^^^^^^
+   |                                          |
+   |                                          the parameter type `K` must be valid for the static lifetime...
+   |                                          ...so that the reference type `&'static K` does not outlive the data it points at
+   |
+help: consider adding an explicit lifetime bound
+   |
+LL | struct Bar<r#T, r#K: 'static = i32>(&'static r#T, &'static r#K);
+   |                    +++++++++
+
+error[E0310]: the parameter type `T` may not live long enough
+  --> $DIR/static-lifetime-tip-with-default-type.rs:15:20
+   |
+LL | struct Boo<T= i32>(&'static T);
+   |                    ^^^^^^^^^^
+   |                    |
+   |                    the parameter type `T` must be valid for the static lifetime...
+   |                    ...so that the reference type `&'static T` does not outlive the data it points at
+   |
+help: consider adding an explicit lifetime bound
+   |
+LL | struct Boo<T: 'static= i32>(&'static T);
+   |             +++++++++
+
+error[E0310]: the parameter type `T` may not live long enough
+  --> $DIR/static-lifetime-tip-with-default-type.rs:19:8
+   |
+LL | = i32>(&'static T);
+   |        ^^^^^^^^^^
+   |        |
+   |        the parameter type `T` must be valid for the static lifetime...
+   |        ...so that the reference type `&'static T` does not outlive the data it points at
+   |
+help: consider adding an explicit lifetime bound
+   |
+LL | struct Far<T: 'static
+   |             +++++++++
+
+error[E0310]: the parameter type `K` may not live long enough
+  --> $DIR/static-lifetime-tip-with-default-type.rs:22:27
+   |
+LL | struct S<'a, K: 'a = i32>(&'static K);
+   |                           ^^^^^^^^^^
+   |                           |
+   |                           the parameter type `K` must be valid for the static lifetime...
+   |                           ...so that the reference type `&'static K` does not outlive the data it points at
+   |
+help: consider adding an explicit lifetime bound
+   |
+LL | struct S<'a, K: 'a + 'static = i32>(&'static K);
+   |                    +++++++++
+
+error[E0392]: lifetime parameter `'a` is never used
+  --> $DIR/static-lifetime-tip-with-default-type.rs:22:10
+   |
+LL | struct S<'a, K: 'a = i32>(&'static K);
+   |          ^^ unused lifetime parameter
+   |
+   = help: consider removing `'a`, referring to it in a field, or using a marker such as `PhantomData`
+
+error: aborting due to 8 previous errors
+
+Some errors have detailed explanations: E0310, E0392.
+For more information about an error, try `rustc --explain E0310`.