Rollup merge of #110827 - compiler-errors:issue-110761-followup, r=cjgillot

Fix lifetime suggestion for type aliases with objects in them

Fixes an issue identified in https://github.com/rust-lang/rust/issues/110761#issuecomment-1520678479

This suggestion, like many other borrowck suggestions, are very fragile and there are other ways to trigger strange behavior even after this PR, so this is just a small improvement and not a total rework 💀
This commit is contained in:
Dylan DPC 2023-05-08 11:39:20 +05:30 committed by GitHub
commit e04c9019f0
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 72 additions and 6 deletions

View File

@ -845,7 +845,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
return;
}
let Some((alias_tys, alias_span)) = self
let Some((alias_tys, alias_span, lt_addition_span)) = self
.infcx
.tcx
.return_type_impl_or_dyn_traits_with_type_alias(suitable_region.def_id) else { return; };
@ -858,10 +858,20 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
()
}
if let TyKind::TraitObject(_, lt, _) = alias_ty.kind {
spans_suggs.push((lt.ident.span.shrink_to_hi(), " + 'a".to_string()));
if lt.ident.name == kw::Empty {
spans_suggs.push((lt.ident.span.shrink_to_hi(), " + 'a".to_string()));
} else {
spans_suggs.push((lt.ident.span, "'a".to_string()));
}
}
}
spans_suggs.push((alias_span.shrink_to_hi(), "<'a>".to_string()));
if let Some(lt_addition_span) = lt_addition_span {
spans_suggs.push((lt_addition_span, "'a, ".to_string()));
} else {
spans_suggs.push((alias_span.shrink_to_hi(), "<'a>".to_string()));
}
diag.multipart_suggestion_verbose(
format!(
"to declare that the trait object {captures}, you can add a lifetime parameter `'a` in the type alias"

View File

@ -1093,11 +1093,13 @@ impl<'tcx> TyCtxt<'tcx> {
v.0
}
/// Given a `DefId` for an `fn`, return all the `dyn` and `impl` traits in its return type and associated alias span when type alias is used
/// Given a `DefId` for an `fn`, return all the `dyn` and `impl` traits in
/// its return type, and the associated alias span when type alias is used,
/// along with a span for lifetime suggestion (if there are existing generics).
pub fn return_type_impl_or_dyn_traits_with_type_alias(
self,
scope_def_id: LocalDefId,
) -> Option<(Vec<&'tcx hir::Ty<'tcx>>, Span)> {
) -> Option<(Vec<&'tcx hir::Ty<'tcx>>, Span, Option<Span>)> {
let hir_id = self.hir().local_def_id_to_hir_id(scope_def_id);
let mut v = TraitObjectVisitor(vec![], self.hir());
// when the return type is a type alias
@ -1111,7 +1113,7 @@ impl<'tcx> TyCtxt<'tcx> {
{
v.visit_ty(alias_ty);
if !v.0.is_empty() {
return Some((v.0, alias_generics.span));
return Some((v.0, alias_generics.span, alias_generics.span_for_lifetime_suggestion()));
}
}
return None;

View File

@ -0,0 +1,11 @@
type Lazy<T> = Box<dyn Fn() -> T + 'static>;
fn test(x: &i32) -> Lazy<i32> {
Box::new(|| {
//~^ ERROR lifetime may not live long enough
//~| ERROR closure may outlive the current function
*x
})
}
fn main() {}

View File

@ -0,0 +1,43 @@
error: lifetime may not live long enough
--> $DIR/suggest-lt-on-ty-alias-w-generics.rs:4:5
|
LL | fn test(x: &i32) -> Lazy<i32> {
| - let's call the lifetime of this reference `'1`
LL | / Box::new(|| {
LL | |
LL | |
LL | | *x
LL | | })
| |______^ returning this value requires that `'1` must outlive `'static`
|
help: to declare that the trait object captures data from argument `x`, you can add a lifetime parameter `'a` in the type alias
|
LL | type Lazy<'a, T> = Box<dyn Fn() -> T + 'a>;
| +++ ~~
error[E0373]: closure may outlive the current function, but it borrows `x`, which is owned by the current function
--> $DIR/suggest-lt-on-ty-alias-w-generics.rs:4:14
|
LL | Box::new(|| {
| ^^ may outlive borrowed value `x`
...
LL | *x
| -- `x` is borrowed here
|
note: closure is returned here
--> $DIR/suggest-lt-on-ty-alias-w-generics.rs:4:5
|
LL | / Box::new(|| {
LL | |
LL | |
LL | | *x
LL | | })
| |______^
help: to force the closure to take ownership of `x` (and any other referenced variables), use the `move` keyword
|
LL | Box::new(move || {
| ++++
error: aborting due to 2 previous errors
For more information about this error, try `rustc --explain E0373`.