about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs34
-rw-r--r--tests/crashes/121816.rs12
-rw-r--r--tests/ui/borrowck/ice-on-non-ref-sig-ty.rs19
-rw-r--r--tests/ui/borrowck/ice-on-non-ref-sig-ty.stderr36
4 files changed, 81 insertions, 20 deletions
diff --git a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs
index b147567001d..2d9bc45ebc8 100644
--- a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs
+++ b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs
@@ -4304,17 +4304,35 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, '_, 'infcx, 'tcx> {
                 // search for relevant arguments.
                 let mut arguments = Vec::new();
                 for (index, argument) in sig.inputs().skip_binder().iter().enumerate() {
-                    if let ty::Ref(argument_region, _, _) = argument.kind() {
-                        if argument_region == return_region {
-                            // Need to use the `rustc_middle::ty` types to compare against the
-                            // `return_region`. Then use the `rustc_hir` type to get only
-                            // the lifetime span.
-                            if let hir::TyKind::Ref(lifetime, _) = &fn_decl.inputs[index].kind {
+                    if let ty::Ref(argument_region, _, _) = argument.kind()
+                        && argument_region == return_region
+                    {
+                        // Need to use the `rustc_middle::ty` types to compare against the
+                        // `return_region`. Then use the `rustc_hir` type to get only
+                        // the lifetime span.
+                        match &fn_decl.inputs[index].kind {
+                            hir::TyKind::Ref(lifetime, _) => {
                                 // With access to the lifetime, we can get
                                 // the span of it.
                                 arguments.push((*argument, lifetime.ident.span));
-                            } else {
-                                bug!("ty type is a ref but hir type is not");
+                            }
+                            // Resolve `self` whose self type is `&T`.
+                            hir::TyKind::Path(hir::QPath::Resolved(None, path)) => {
+                                if let Res::SelfTyAlias { alias_to, .. } = path.res
+                                    && let Some(alias_to) = alias_to.as_local()
+                                    && let hir::Impl { self_ty, .. } = self
+                                        .infcx
+                                        .tcx
+                                        .hir_node_by_def_id(alias_to)
+                                        .expect_item()
+                                        .expect_impl()
+                                    && let hir::TyKind::Ref(lifetime, _) = self_ty.kind
+                                {
+                                    arguments.push((*argument, lifetime.ident.span));
+                                }
+                            }
+                            _ => {
+                                // Don't ICE though. It might be a type alias.
                             }
                         }
                     }
diff --git a/tests/crashes/121816.rs b/tests/crashes/121816.rs
deleted file mode 100644
index a5569ea19d3..00000000000
--- a/tests/crashes/121816.rs
+++ /dev/null
@@ -1,12 +0,0 @@
-//@ known-bug: #121816
-fn f<'a, T>(_: &'static &'a (), x: &'a T) -> &'static T {
-    x
-}
-trait W<'a> {
-    fn g<T>(self, x: &'a T) -> &'static T;
-}
-impl<'a> W<'a> for &'static () {
-    fn g<T>(self, x: &'a T) -> &'static T {
-        f(&self, x)
-    }
-}
diff --git a/tests/ui/borrowck/ice-on-non-ref-sig-ty.rs b/tests/ui/borrowck/ice-on-non-ref-sig-ty.rs
new file mode 100644
index 00000000000..1c867bd2378
--- /dev/null
+++ b/tests/ui/borrowck/ice-on-non-ref-sig-ty.rs
@@ -0,0 +1,19 @@
+// Don't ICE when trying to annotate signature and we see `&()`
+
+fn f<'a, T>(_: &'static &'a (), x: &'a T) -> &'static T {
+    x
+}
+trait W<'a> {
+    fn g<T>(self, x: &'a T) -> &'static T;
+}
+
+// Frankly this error message is impossible to parse, but :shrug:.
+impl<'a> W<'a> for &'static () {
+    fn g<T>(self, x: &'a T) -> &'static T {
+        f(&self, x)
+        //~^ ERROR borrowed data escapes outside of method
+        //~| ERROR `self` does not live long enough
+    }
+}
+
+fn main() {}
diff --git a/tests/ui/borrowck/ice-on-non-ref-sig-ty.stderr b/tests/ui/borrowck/ice-on-non-ref-sig-ty.stderr
new file mode 100644
index 00000000000..2b900a8e68a
--- /dev/null
+++ b/tests/ui/borrowck/ice-on-non-ref-sig-ty.stderr
@@ -0,0 +1,36 @@
+error[E0521]: borrowed data escapes outside of method
+  --> $DIR/ice-on-non-ref-sig-ty.rs:13:9
+   |
+LL | impl<'a> W<'a> for &'static () {
+   |      -- lifetime `'a` defined here
+LL |     fn g<T>(self, x: &'a T) -> &'static T {
+   |             ----  - `x` is a reference that is only valid in the method body
+   |             |
+   |             `self` declared here, outside of the method body
+LL |         f(&self, x)
+   |         ^^^^^^^^^^^
+   |         |
+   |         `x` escapes the method body here
+   |         argument requires that `'a` must outlive `'static`
+
+error[E0597]: `self` does not live long enough
+  --> $DIR/ice-on-non-ref-sig-ty.rs:13:11
+   |
+LL | impl<'a> W<'a> for &'static () {
+   |                     ------- has lifetime `'static`
+LL |     fn g<T>(self, x: &'a T) -> &'static T {
+   |                                 ------- also has lifetime `'static`
+LL |         f(&self, x)
+   |           ^^^^^ `self` would have to be valid for `'static`...
+...
+LL |     }
+   |      - ...but `self` will be dropped here, when the function `g` returns
+   |
+   = help: use data from the highlighted arguments which match the `'static` lifetime of the return type
+   = note: functions cannot return a borrow to data owned within the function's scope, functions can only return borrows to data passed as arguments
+   = note: to learn more, visit <https://doc.rust-lang.org/book/ch04-02-references-and-borrowing.html#dangling-references>
+
+error: aborting due to 2 previous errors
+
+Some errors have detailed explanations: E0521, E0597.
+For more information about an error, try `rustc --explain E0521`.