about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--compiler/rustc_error_messages/locales/en-US/infer.ftl26
-rw-r--r--compiler/rustc_infer/src/errors/mod.rs2
-rw-r--r--compiler/rustc_infer/src/infer/error_reporting/nice_region_error/static_impl_trait.rs5
-rw-r--r--tests/ui/inference/issue-107090.rs31
-rw-r--r--tests/ui/inference/issue-107090.stderr173
5 files changed, 223 insertions, 14 deletions
diff --git a/compiler/rustc_error_messages/locales/en-US/infer.ftl b/compiler/rustc_error_messages/locales/en-US/infer.ftl
index cc38d71b484..164d6d26d23 100644
--- a/compiler/rustc_error_messages/locales/en-US/infer.ftl
+++ b/compiler/rustc_error_messages/locales/en-US/infer.ftl
@@ -268,28 +268,28 @@ infer_but_calling_introduces = {$has_param_name ->
     [true] `{$param_name}`
     *[false] `fn` parameter
 } has {$lifetime_kind ->
-    [named] lifetime `{$lifetime}`
-    *[anon] an anonymous lifetime `'_`
-} but calling `{assoc_item}` introduces an implicit `'static` lifetime requirement
+    [true] lifetime `{$lifetime}`
+    *[false] an anonymous lifetime `'_`
+} but calling `{$assoc_item}` introduces an implicit `'static` lifetime requirement
     .label1 = {$has_lifetime ->
-        [named] lifetime `{$lifetime}`
-        *[anon] an anonymous lifetime `'_`
+        [true] lifetime `{$lifetime}`
+        *[false] an anonymous lifetime `'_`
     }
     .label2 = ...is used and required to live as long as `'static` here because of an implicit lifetime bound on the {$has_impl_path ->
-        [named] `impl` of `{$impl_path}`
-        *[anon] inherent `impl`
+        [true] `impl` of `{$impl_path}`
+        *[false] inherent `impl`
     }
 
 infer_but_needs_to_satisfy = {$has_param_name ->
     [true] `{$param_name}`
     *[false] `fn` parameter
 } has {$has_lifetime ->
-    [named] lifetime `{$lifetime}`
-    *[anon] an anonymous lifetime `'_`
+    [true] lifetime `{$lifetime}`
+    *[false] an anonymous lifetime `'_`
 } but it needs to satisfy a `'static` lifetime requirement
     .influencer = this data with {$has_lifetime ->
-        [named] lifetime `{$lifetime}`
-        *[anon] an anonymous lifetime `'_`
+        [true] lifetime `{$lifetime}`
+        *[false] an anonymous lifetime `'_`
     }...
     .require = {$spans_empty ->
         *[true] ...is used and required to live as long as `'static` here
@@ -302,8 +302,8 @@ infer_more_targeted = {$has_param_name ->
     [true] `{$param_name}`
     *[false] `fn` parameter
 } has {$has_lifetime ->
-    [named] lifetime `{$lifetime}`
-    *[anon] an anonymous lifetime `'_`
+    [true] lifetime `{$lifetime}`
+    *[false] an anonymous lifetime `'_`
 } but calling `{$ident}` introduces an implicit `'static` lifetime requirement
 
 infer_ril_introduced_here = `'static` requirement introduced here
diff --git a/compiler/rustc_infer/src/errors/mod.rs b/compiler/rustc_infer/src/errors/mod.rs
index 033a1842edb..8bf3a160abb 100644
--- a/compiler/rustc_infer/src/errors/mod.rs
+++ b/compiler/rustc_infer/src/errors/mod.rs
@@ -927,6 +927,8 @@ pub struct ButNeedsToSatisfy {
     #[subdiagnostic]
     pub req_introduces_loc: Option<ReqIntroducedLocations>,
 
+    pub has_param_name: bool,
+    pub param_name: String,
     pub spans_empty: bool,
     pub has_lifetime: bool,
     pub lifetime: String,
diff --git a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/static_impl_trait.rs b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/static_impl_trait.rs
index 49ad3ce50b8..6a463583dfb 100644
--- a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/static_impl_trait.rs
+++ b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/static_impl_trait.rs
@@ -98,6 +98,7 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> {
         let sp = var_origin.span();
         let return_sp = sub_origin.span();
         let param = self.find_param_with_region(*sup_r, *sub_r)?;
+        let simple_ident = param.param.pat.simple_ident();
         let lifetime_name = if sup_r.has_name() { sup_r.to_string() } else { "'_".to_owned() };
 
         let (mention_influencer, influencer_point) =
@@ -187,7 +188,9 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> {
             req_introduces_loc: subdiag,
 
             has_lifetime: sup_r.has_name(),
-            lifetime: sup_r.to_string(),
+            lifetime: lifetime_name.clone(),
+            has_param_name: simple_ident.is_some(),
+            param_name: simple_ident.map(|x| x.to_string()).unwrap_or_default(),
             spans_empty,
             bound,
         };
diff --git a/tests/ui/inference/issue-107090.rs b/tests/ui/inference/issue-107090.rs
new file mode 100644
index 00000000000..9426445656f
--- /dev/null
+++ b/tests/ui/inference/issue-107090.rs
@@ -0,0 +1,31 @@
+use std::marker::PhantomData;
+struct Foo<'a, 'b, T>(PhantomData<(&'a (), &'b (), T)>)
+where
+    Foo<'short, 'out, T>: Convert<'a, 'b>;
+    //~^ ERROR mismatched types
+    //~^^ ERROR mismatched types
+    //~^^^ ERROR use of undeclared lifetime name
+    //~| ERROR use of undeclared lifetime name `'out`
+
+trait Convert<'a, 'b>: Sized {
+    fn cast(&'a self) -> &'b Self;
+}
+impl<'long: 'short, 'short, T> Convert<'long, 'b> for Foo<'short, 'out, T> {
+    //~^ ERROR use of undeclared lifetime name
+    //~^^ ERROR use of undeclared lifetime name `'out`
+    //~| ERROR cannot infer an appropriate lifetime for lifetime parameter
+    fn cast(&'long self) -> &'short Foo<'short, 'out, T> {
+        //~^ ERROR use of undeclared lifetime name
+        //~| ERROR cannot infer an appropriate lifetime for lifetime parameter
+        self
+    }
+}
+
+fn badboi<'in_, 'out, T>(x: Foo<'in_, 'out, T>, sadness: &'in_ Foo<'short, 'out, T>) -> &'out T {
+    //~^ ERROR use of undeclared lifetime name
+    //~^^ ERROR incompatible lifetime on type
+    //~| ERROR `x` has lifetime `'in_` but it needs to satisfy a `'static` lifetime requirement
+    sadness.cast()
+}
+
+fn main() {}
diff --git a/tests/ui/inference/issue-107090.stderr b/tests/ui/inference/issue-107090.stderr
new file mode 100644
index 00000000000..33cb39014ac
--- /dev/null
+++ b/tests/ui/inference/issue-107090.stderr
@@ -0,0 +1,173 @@
+error[E0261]: use of undeclared lifetime name `'short`
+  --> $DIR/issue-107090.rs:4:9
+   |
+LL |     Foo<'short, 'out, T>: Convert<'a, 'b>;
+   |         ^^^^^^ undeclared lifetime
+   |
+   = note: for more information on higher-ranked polymorphism, visit https://doc.rust-lang.org/nomicon/hrtb.html
+help: consider making the bound lifetime-generic with a new `'short` lifetime
+   |
+LL |     for<'short> Foo<'short, 'out, T>: Convert<'a, 'b>;
+   |     +++++++++++
+help: consider introducing lifetime `'short` here
+   |
+LL | struct Foo<'short, 'a, 'b, T>(PhantomData<(&'a (), &'b (), T)>)
+   |            +++++++
+
+error[E0261]: use of undeclared lifetime name `'out`
+  --> $DIR/issue-107090.rs:4:17
+   |
+LL |     Foo<'short, 'out, T>: Convert<'a, 'b>;
+   |                 ^^^^ undeclared lifetime
+   |
+help: consider making the bound lifetime-generic with a new `'out` lifetime
+   |
+LL |     for<'out> Foo<'short, 'out, T>: Convert<'a, 'b>;
+   |     +++++++++
+help: consider introducing lifetime `'out` here
+   |
+LL | struct Foo<'out, 'a, 'b, T>(PhantomData<(&'a (), &'b (), T)>)
+   |            +++++
+
+error[E0261]: use of undeclared lifetime name `'b`
+  --> $DIR/issue-107090.rs:13:47
+   |
+LL | impl<'long: 'short, 'short, T> Convert<'long, 'b> for Foo<'short, 'out, T> {
+   |      -                                        ^^ undeclared lifetime
+   |      |
+   |      help: consider introducing lifetime `'b` here: `'b,`
+
+error[E0261]: use of undeclared lifetime name `'out`
+  --> $DIR/issue-107090.rs:13:67
+   |
+LL | impl<'long: 'short, 'short, T> Convert<'long, 'b> for Foo<'short, 'out, T> {
+   |      - help: consider introducing lifetime `'out` here: `'out,`   ^^^^ undeclared lifetime
+
+error[E0261]: use of undeclared lifetime name `'out`
+  --> $DIR/issue-107090.rs:17:49
+   |
+LL |     fn cast(&'long self) -> &'short Foo<'short, 'out, T> {
+   |                                                 ^^^^ undeclared lifetime
+   |
+help: consider introducing lifetime `'out` here
+   |
+LL |     fn cast<'out>(&'long self) -> &'short Foo<'short, 'out, T> {
+   |            ++++++
+help: consider introducing lifetime `'out` here
+   |
+LL | impl<'out, 'long: 'short, 'short, T> Convert<'long, 'b> for Foo<'short, 'out, T> {
+   |      +++++
+
+error[E0261]: use of undeclared lifetime name `'short`
+  --> $DIR/issue-107090.rs:24:68
+   |
+LL | fn badboi<'in_, 'out, T>(x: Foo<'in_, 'out, T>, sadness: &'in_ Foo<'short, 'out, T>) -> &'out T {
+   |           -                                                        ^^^^^^ undeclared lifetime
+   |           |
+   |           help: consider introducing lifetime `'short` here: `'short,`
+
+error[E0308]: mismatched types
+  --> $DIR/issue-107090.rs:4:27
+   |
+LL |     Foo<'short, 'out, T>: Convert<'a, 'b>;
+   |                           ^^^^^^^^^^^^^^^ lifetime mismatch
+   |
+   = note: expected trait `Convert<'static, 'static>`
+              found trait `Convert<'a, 'b>`
+note: the lifetime `'a` as defined here...
+  --> $DIR/issue-107090.rs:2:12
+   |
+LL | struct Foo<'a, 'b, T>(PhantomData<(&'a (), &'b (), T)>)
+   |            ^^
+   = note: ...does not necessarily outlive the static lifetime
+
+error[E0308]: mismatched types
+  --> $DIR/issue-107090.rs:4:27
+   |
+LL |     Foo<'short, 'out, T>: Convert<'a, 'b>;
+   |                           ^^^^^^^^^^^^^^^ lifetime mismatch
+   |
+   = note: expected trait `Convert<'static, 'static>`
+              found trait `Convert<'a, 'b>`
+note: the lifetime `'b` as defined here...
+  --> $DIR/issue-107090.rs:2:16
+   |
+LL | struct Foo<'a, 'b, T>(PhantomData<(&'a (), &'b (), T)>)
+   |                ^^
+   = note: ...does not necessarily outlive the static lifetime
+
+error[E0495]: cannot infer an appropriate lifetime for lifetime parameter `'long` due to conflicting requirements
+  --> $DIR/issue-107090.rs:13:55
+   |
+LL | impl<'long: 'short, 'short, T> Convert<'long, 'b> for Foo<'short, 'out, T> {
+   |                                                       ^^^^^^^^^^^^^^^^^^^^
+   |
+note: first, the lifetime cannot outlive the lifetime `'short` as defined here...
+  --> $DIR/issue-107090.rs:13:21
+   |
+LL | impl<'long: 'short, 'short, T> Convert<'long, 'b> for Foo<'short, 'out, T> {
+   |                     ^^^^^^
+   = note: ...but the lifetime must also be valid for the static lifetime...
+note: ...so that the types are compatible
+  --> $DIR/issue-107090.rs:13:55
+   |
+LL | impl<'long: 'short, 'short, T> Convert<'long, 'b> for Foo<'short, 'out, T> {
+   |                                                       ^^^^^^^^^^^^^^^^^^^^
+   = note: expected `Convert<'short, 'static>`
+              found `Convert<'_, 'static>`
+
+error: incompatible lifetime on type
+  --> $DIR/issue-107090.rs:24:29
+   |
+LL | fn badboi<'in_, 'out, T>(x: Foo<'in_, 'out, T>, sadness: &'in_ Foo<'short, 'out, T>) -> &'out T {
+   |                             ^^^^^^^^^^^^^^^^^^
+   |
+note: because this has an unmet lifetime requirement
+  --> $DIR/issue-107090.rs:4:27
+   |
+LL |     Foo<'short, 'out, T>: Convert<'a, 'b>;
+   |                           ^^^^^^^^^^^^^^^ introduces a `'static` lifetime requirement
+note: the lifetime `'out` as defined here...
+  --> $DIR/issue-107090.rs:24:17
+   |
+LL | fn badboi<'in_, 'out, T>(x: Foo<'in_, 'out, T>, sadness: &'in_ Foo<'short, 'out, T>) -> &'out T {
+   |                 ^^^^
+note: ...does not necessarily outlive the static lifetime introduced by the compatible `impl`
+  --> $DIR/issue-107090.rs:13:1
+   |
+LL | impl<'long: 'short, 'short, T> Convert<'long, 'b> for Foo<'short, 'out, T> {
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0759]: `x` has lifetime `'in_` but it needs to satisfy a `'static` lifetime requirement
+  --> $DIR/issue-107090.rs:24:29
+   |
+LL | fn badboi<'in_, 'out, T>(x: Foo<'in_, 'out, T>, sadness: &'in_ Foo<'short, 'out, T>) -> &'out T {
+   |                             ^^^^^^^^^^^^^^^^^^
+   |                             |
+   |                             this data with lifetime `'in_`...
+   |                             ...is used and required to live as long as `'static` here
+
+error[E0495]: cannot infer an appropriate lifetime for lifetime parameter `'long` due to conflicting requirements
+  --> $DIR/issue-107090.rs:17:13
+   |
+LL |     fn cast(&'long self) -> &'short Foo<'short, 'out, T> {
+   |             ^^^^^^^^^^^
+   |
+note: first, the lifetime cannot outlive the lifetime `'short` as defined here...
+  --> $DIR/issue-107090.rs:13:21
+   |
+LL | impl<'long: 'short, 'short, T> Convert<'long, 'b> for Foo<'short, 'out, T> {
+   |                     ^^^^^^
+   = note: ...but the lifetime must also be valid for the static lifetime...
+note: ...so that the types are compatible
+  --> $DIR/issue-107090.rs:17:13
+   |
+LL |     fn cast(&'long self) -> &'short Foo<'short, 'out, T> {
+   |             ^^^^^^^^^^^
+   = note: expected `Convert<'short, 'static>`
+              found `Convert<'_, 'static>`
+
+error: aborting due to 12 previous errors
+
+Some errors have detailed explanations: E0261, E0308, E0495, E0759.
+For more information about an error, try `rustc --explain E0261`.