Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

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

Merged
merged 1 commit into from
Jul 25, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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`.
Loading