mirror of
https://github.com/rust-lang/rust.git
synced 2024-11-01 06:51:58 +00:00
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:
commit
e04c9019f0
@ -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"
|
||||
|
@ -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;
|
||||
|
11
tests/ui/borrowck/suggest-lt-on-ty-alias-w-generics.rs
Normal file
11
tests/ui/borrowck/suggest-lt-on-ty-alias-w-generics.rs
Normal 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() {}
|
43
tests/ui/borrowck/suggest-lt-on-ty-alias-w-generics.stderr
Normal file
43
tests/ui/borrowck/suggest-lt-on-ty-alias-w-generics.stderr
Normal 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`.
|
Loading…
Reference in New Issue
Block a user