Skip to content

Commit 4cf4196

Browse files
authored
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
2 parents 5a853d0 + d004edf commit 4cf4196

File tree

4 files changed

+81
-20
lines changed

4 files changed

+81
-20
lines changed

compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs

+26-8
Original file line numberDiff line numberDiff line change
@@ -4304,17 +4304,35 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, '_, 'infcx, 'tcx> {
43044304
// search for relevant arguments.
43054305
let mut arguments = Vec::new();
43064306
for (index, argument) in sig.inputs().skip_binder().iter().enumerate() {
4307-
if let ty::Ref(argument_region, _, _) = argument.kind() {
4308-
if argument_region == return_region {
4309-
// Need to use the `rustc_middle::ty` types to compare against the
4310-
// `return_region`. Then use the `rustc_hir` type to get only
4311-
// the lifetime span.
4312-
if let hir::TyKind::Ref(lifetime, _) = &fn_decl.inputs[index].kind {
4307+
if let ty::Ref(argument_region, _, _) = argument.kind()
4308+
&& argument_region == return_region
4309+
{
4310+
// Need to use the `rustc_middle::ty` types to compare against the
4311+
// `return_region`. Then use the `rustc_hir` type to get only
4312+
// the lifetime span.
4313+
match &fn_decl.inputs[index].kind {
4314+
hir::TyKind::Ref(lifetime, _) => {
43134315
// With access to the lifetime, we can get
43144316
// the span of it.
43154317
arguments.push((*argument, lifetime.ident.span));
4316-
} else {
4317-
bug!("ty type is a ref but hir type is not");
4318+
}
4319+
// Resolve `self` whose self type is `&T`.
4320+
hir::TyKind::Path(hir::QPath::Resolved(None, path)) => {
4321+
if let Res::SelfTyAlias { alias_to, .. } = path.res
4322+
&& let Some(alias_to) = alias_to.as_local()
4323+
&& let hir::Impl { self_ty, .. } = self
4324+
.infcx
4325+
.tcx
4326+
.hir_node_by_def_id(alias_to)
4327+
.expect_item()
4328+
.expect_impl()
4329+
&& let hir::TyKind::Ref(lifetime, _) = self_ty.kind
4330+
{
4331+
arguments.push((*argument, lifetime.ident.span));
4332+
}
4333+
}
4334+
_ => {
4335+
// Don't ICE though. It might be a type alias.
43184336
}
43194337
}
43204338
}

tests/crashes/121816.rs

-12
This file was deleted.
+19
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
// Don't ICE when trying to annotate signature and we see `&()`
2+
3+
fn f<'a, T>(_: &'static &'a (), x: &'a T) -> &'static T {
4+
x
5+
}
6+
trait W<'a> {
7+
fn g<T>(self, x: &'a T) -> &'static T;
8+
}
9+
10+
// Frankly this error message is impossible to parse, but :shrug:.
11+
impl<'a> W<'a> for &'static () {
12+
fn g<T>(self, x: &'a T) -> &'static T {
13+
f(&self, x)
14+
//~^ ERROR borrowed data escapes outside of method
15+
//~| ERROR `self` does not live long enough
16+
}
17+
}
18+
19+
fn main() {}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
error[E0521]: borrowed data escapes outside of method
2+
--> $DIR/ice-on-non-ref-sig-ty.rs:13:9
3+
|
4+
LL | impl<'a> W<'a> for &'static () {
5+
| -- lifetime `'a` defined here
6+
LL | fn g<T>(self, x: &'a T) -> &'static T {
7+
| ---- - `x` is a reference that is only valid in the method body
8+
| |
9+
| `self` declared here, outside of the method body
10+
LL | f(&self, x)
11+
| ^^^^^^^^^^^
12+
| |
13+
| `x` escapes the method body here
14+
| argument requires that `'a` must outlive `'static`
15+
16+
error[E0597]: `self` does not live long enough
17+
--> $DIR/ice-on-non-ref-sig-ty.rs:13:11
18+
|
19+
LL | impl<'a> W<'a> for &'static () {
20+
| ------- has lifetime `'static`
21+
LL | fn g<T>(self, x: &'a T) -> &'static T {
22+
| ------- also has lifetime `'static`
23+
LL | f(&self, x)
24+
| ^^^^^ `self` would have to be valid for `'static`...
25+
...
26+
LL | }
27+
| - ...but `self` will be dropped here, when the function `g` returns
28+
|
29+
= help: use data from the highlighted arguments which match the `'static` lifetime of the return type
30+
= note: functions cannot return a borrow to data owned within the function's scope, functions can only return borrows to data passed as arguments
31+
= note: to learn more, visit <https://doc.rust-lang.org/book/ch04-02-references-and-borrowing.html#dangling-references>
32+
33+
error: aborting due to 2 previous errors
34+
35+
Some errors have detailed explanations: E0521, E0597.
36+
For more information about an error, try `rustc --explain E0521`.

0 commit comments

Comments
 (0)