Skip to content

Commit 183f1a6

Browse files
Fix lifetime suggestion for type aliases with objects in them
1 parent 666fee2 commit 183f1a6

File tree

4 files changed

+72
-6
lines changed

4 files changed

+72
-6
lines changed

compiler/rustc_borrowck/src/diagnostics/region_errors.rs

+13-3
Original file line numberDiff line numberDiff line change
@@ -845,7 +845,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
845845
return;
846846
}
847847

848-
let Some((alias_tys, alias_span)) = self
848+
let Some((alias_tys, alias_span, lt_addition_span)) = self
849849
.infcx
850850
.tcx
851851
.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> {
858858
()
859859
}
860860
if let TyKind::TraitObject(_, lt, _) = alias_ty.kind {
861-
spans_suggs.push((lt.ident.span.shrink_to_hi(), " + 'a".to_string()));
861+
if lt.ident.name == kw::Empty {
862+
spans_suggs.push((lt.ident.span.shrink_to_hi(), " + 'a".to_string()));
863+
} else {
864+
spans_suggs.push((lt.ident.span, "'a".to_string()));
865+
}
862866
}
863867
}
864-
spans_suggs.push((alias_span.shrink_to_hi(), "<'a>".to_string()));
868+
869+
if let Some(lt_addition_span) = lt_addition_span {
870+
spans_suggs.push((lt_addition_span, "'a, ".to_string()));
871+
} else {
872+
spans_suggs.push((alias_span.shrink_to_hi(), "<'a>".to_string()));
873+
}
874+
865875
diag.multipart_suggestion_verbose(
866876
&format!(
867877
"to declare that the trait object {captures}, you can add a lifetime parameter `'a` in the type alias"

compiler/rustc_middle/src/ty/context.rs

+5-3
Original file line numberDiff line numberDiff line change
@@ -1116,11 +1116,13 @@ impl<'tcx> TyCtxt<'tcx> {
11161116
v.0
11171117
}
11181118

1119-
/// 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
1119+
/// Given a `DefId` for an `fn`, return all the `dyn` and `impl` traits in
1120+
/// its return type, and the associated alias span when type alias is used,
1121+
/// along with a span for lifetime suggestion (if there are existing generics).
11201122
pub fn return_type_impl_or_dyn_traits_with_type_alias(
11211123
self,
11221124
scope_def_id: LocalDefId,
1123-
) -> Option<(Vec<&'tcx hir::Ty<'tcx>>, Span)> {
1125+
) -> Option<(Vec<&'tcx hir::Ty<'tcx>>, Span, Option<Span>)> {
11241126
let hir_id = self.hir().local_def_id_to_hir_id(scope_def_id);
11251127
let mut v = TraitObjectVisitor(vec![], self.hir());
11261128
// when the return type is a type alias
@@ -1134,7 +1136,7 @@ impl<'tcx> TyCtxt<'tcx> {
11341136
{
11351137
v.visit_ty(alias_ty);
11361138
if !v.0.is_empty() {
1137-
return Some((v.0, alias_generics.span));
1139+
return Some((v.0, alias_generics.span, alias_generics.span_for_lifetime_suggestion()));
11381140
}
11391141
}
11401142
return None;
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
type Lazy<T> = Box<dyn Fn() -> T + 'static>;
2+
3+
fn test(x: &i32) -> Lazy<i32> {
4+
Box::new(|| {
5+
//~^ ERROR lifetime may not live long enough
6+
//~| ERROR closure may outlive the current function
7+
*x
8+
})
9+
}
10+
11+
fn main() {}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
error: lifetime may not live long enough
2+
--> $DIR/suggest-lt-on-ty-alias-w-generics.rs:4:5
3+
|
4+
LL | fn test(x: &i32) -> Lazy<i32> {
5+
| - let's call the lifetime of this reference `'1`
6+
LL | / Box::new(|| {
7+
LL | |
8+
LL | |
9+
LL | | *x
10+
LL | | })
11+
| |______^ returning this value requires that `'1` must outlive `'static`
12+
|
13+
help: to declare that the trait object captures data from argument `x`, you can add a lifetime parameter `'a` in the type alias
14+
|
15+
LL | type Lazy<'a, T> = Box<dyn Fn() -> T + 'a>;
16+
| +++ ~~
17+
18+
error[E0373]: closure may outlive the current function, but it borrows `x`, which is owned by the current function
19+
--> $DIR/suggest-lt-on-ty-alias-w-generics.rs:4:14
20+
|
21+
LL | Box::new(|| {
22+
| ^^ may outlive borrowed value `x`
23+
...
24+
LL | *x
25+
| -- `x` is borrowed here
26+
|
27+
note: closure is returned here
28+
--> $DIR/suggest-lt-on-ty-alias-w-generics.rs:4:5
29+
|
30+
LL | / Box::new(|| {
31+
LL | |
32+
LL | |
33+
LL | | *x
34+
LL | | })
35+
| |______^
36+
help: to force the closure to take ownership of `x` (and any other referenced variables), use the `move` keyword
37+
|
38+
LL | Box::new(move || {
39+
| ++++
40+
41+
error: aborting due to 2 previous errors
42+
43+
For more information about this error, try `rustc --explain E0373`.

0 commit comments

Comments
 (0)