Don't ICE if HIR and middle types disagree in borrowck error reporting
This commit is contained in:
parent
2ccafed862
commit
d004edf311
@ -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 {
|
||||
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.
|
||||
if let hir::TyKind::Ref(lifetime, _) = &fn_decl.inputs[index].kind {
|
||||
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.
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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)
|
||||
}
|
||||
}
|
19
tests/ui/borrowck/ice-on-non-ref-sig-ty.rs
Normal file
19
tests/ui/borrowck/ice-on-non-ref-sig-ty.rs
Normal 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() {}
|
36
tests/ui/borrowck/ice-on-non-ref-sig-ty.stderr
Normal file
36
tests/ui/borrowck/ice-on-non-ref-sig-ty.stderr
Normal 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`.
|
Loading…
Reference in New Issue
Block a user