Skip to content

Commit e04c901

Browse files
authored
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 #110761 (comment) 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 💀
2 parents 71a1ac2 + 183f1a6 commit e04c901

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
@@ -1093,11 +1093,13 @@ impl<'tcx> TyCtxt<'tcx> {
10931093
v.0
10941094
}
10951095

1096-
/// 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
1096+
/// Given a `DefId` for an `fn`, return all the `dyn` and `impl` traits in
1097+
/// its return type, and the associated alias span when type alias is used,
1098+
/// along with a span for lifetime suggestion (if there are existing generics).
10971099
pub fn return_type_impl_or_dyn_traits_with_type_alias(
10981100
self,
10991101
scope_def_id: LocalDefId,
1100-
) -> Option<(Vec<&'tcx hir::Ty<'tcx>>, Span)> {
1102+
) -> Option<(Vec<&'tcx hir::Ty<'tcx>>, Span, Option<Span>)> {
11011103
let hir_id = self.hir().local_def_id_to_hir_id(scope_def_id);
11021104
let mut v = TraitObjectVisitor(vec![], self.hir());
11031105
// when the return type is a type alias
@@ -1111,7 +1113,7 @@ impl<'tcx> TyCtxt<'tcx> {
11111113
{
11121114
v.visit_ty(alias_ty);
11131115
if !v.0.is_empty() {
1114-
return Some((v.0, alias_generics.span));
1116+
return Some((v.0, alias_generics.span, alias_generics.span_for_lifetime_suggestion()));
11151117
}
11161118
}
11171119
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)