Don't ICE if HIR and middle types disagree in borrowck error reporting
This commit is contained in:
parent
2ccafed862
commit
d004edf311
4 changed files with 81 additions and 20 deletions
|
@ -4304,17 +4304,35 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, '_, 'infcx, 'tcx> {
|
||||||
// search for relevant arguments.
|
// search for relevant arguments.
|
||||||
let mut arguments = Vec::new();
|
let mut arguments = Vec::new();
|
||||||
for (index, argument) in sig.inputs().skip_binder().iter().enumerate() {
|
for (index, argument) in sig.inputs().skip_binder().iter().enumerate() {
|
||||||
if let ty::Ref(argument_region, _, _) = argument.kind() {
|
if let ty::Ref(argument_region, _, _) = argument.kind()
|
||||||
if argument_region == return_region {
|
&& argument_region == return_region
|
||||||
|
{
|
||||||
// Need to use the `rustc_middle::ty` types to compare against the
|
// Need to use the `rustc_middle::ty` types to compare against the
|
||||||
// `return_region`. Then use the `rustc_hir` type to get only
|
// `return_region`. Then use the `rustc_hir` type to get only
|
||||||
// the lifetime span.
|
// 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
|
// With access to the lifetime, we can get
|
||||||
// the span of it.
|
// the span of it.
|
||||||
arguments.push((*argument, lifetime.ident.span));
|
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…
Add table
Add a link
Reference in a new issue