Rollup merge of #128172 - compiler-errors:non-self-arg, r=chenyukang

Don't ICE if HIR and middle types disagree in borrowck error reporting

We try to match up the `middle::ty::Ty` and `hir::Ty` types in borrowck error reporting, but due to things like `Self` self type alias, or regular type aliases, these might not match up. Don't ICE.

This PR also tries to recover the error by looking up the self type of the impl in case we see `Self`. The diagnostic is frankly quite confusing, but I also didn't really want to look at it because I don't understand the conflict error reporting logic. 🤷

Fixes #121816
This commit is contained in:
Matthias Krüger 2024-07-25 16:48:21 +02:00 committed by GitHub
commit 4cf4196907
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 81 additions and 20 deletions

View File

@ -4304,17 +4304,35 @@ fn annotate_fn_sig(
// 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.
}
}
}

View File

@ -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)
}
}

View File

@ -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() {}

View File

@ -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`.