Skip to content

Commit

Permalink
Rollup merge of rust-lang#128172 - compiler-errors:non-self-arg, r=ch…
Browse files Browse the repository at this point in the history
…enyukang

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 rust-lang#121816
  • Loading branch information
matthiaskrgr committed Jul 25, 2024
2 parents 5a853d0 + d004edf commit 4cf4196
Show file tree
Hide file tree
Showing 4 changed files with 81 additions and 20 deletions.
34 changes: 26 additions & 8 deletions compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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.
}
}
}
Expand Down
12 changes: 0 additions & 12 deletions tests/crashes/121816.rs

This file was deleted.

19 changes: 19 additions & 0 deletions tests/ui/borrowck/ice-on-non-ref-sig-ty.rs
Original file line number Diff line number Diff line change
@@ -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() {}
36 changes: 36 additions & 0 deletions tests/ui/borrowck/ice-on-non-ref-sig-ty.stderr
Original file line number Diff line number Diff line change
@@ -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`.

0 comments on commit 4cf4196

Please sign in to comment.