Skip to content

Commit

Permalink
Rudimentary heuristic to insert parentheses when needed for RPIT over…
Browse files Browse the repository at this point in the history
…captures lint
  • Loading branch information
compiler-errors committed Dec 10, 2024
1 parent 33c245b commit e134c74
Show file tree
Hide file tree
Showing 4 changed files with 58 additions and 6 deletions.
35 changes: 30 additions & 5 deletions compiler/rustc_trait_selection/src/errors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ use rustc_hir as hir;
use rustc_hir::def::DefKind;
use rustc_hir::def_id::{DefId, LocalDefId};
use rustc_hir::intravisit::{Visitor, walk_ty};
use rustc_hir::{FnRetTy, GenericParamKind};
use rustc_hir::{FnRetTy, GenericParamKind, Node};
use rustc_macros::{Diagnostic, Subdiagnostic};
use rustc_middle::ty::print::{PrintTraitRefExt as _, TraitRefPrintOnlyTraitPath};
use rustc_middle::ty::{self, Binder, ClosureKind, FnSig, PolyTraitRef, Region, Ty, TyCtxt};
Expand Down Expand Up @@ -1888,10 +1888,35 @@ pub fn impl_trait_overcapture_suggestion<'tcx>(
.collect::<Vec<_>>()
.join(", ");

suggs.push((
tcx.def_span(opaque_def_id).shrink_to_hi(),
format!(" + use<{concatenated_bounds}>"),
));
let opaque_hir_id = tcx.local_def_id_to_hir_id(opaque_def_id);
// FIXME: This is a bit too conservative, since it ignores parens already written in AST.
let (lparen, rparen) = match tcx
.hir()
.parent_iter(opaque_hir_id)
.nth(1)
.expect("expected ty to have a parent always")
.1
{
Node::PathSegment(segment)
if segment.args().paren_sugar_output().is_some_and(|ty| ty.hir_id == opaque_hir_id) =>
{
("(", ")")
}
Node::Ty(ty) => match ty.kind {
rustc_hir::TyKind::Ptr(_) | rustc_hir::TyKind::Ref(..) => ("(", ")"),
// FIXME: RPITs are not allowed to be nested in `impl Fn() -> ...`,
// but we eventually could support that, and that would necessitate
// making this more sophisticated.
_ => ("", ""),
},
_ => ("", ""),
};

let rpit_span = tcx.def_span(opaque_def_id);
if !lparen.is_empty() {
suggs.push((rpit_span.shrink_to_lo(), lparen.to_string()));
}
suggs.push((rpit_span.shrink_to_hi(), format!(" + use<{concatenated_bounds}>{rparen}")));

Some(AddPreciseCapturingForOvercapture { suggs, apit_spans })
}
Expand Down
4 changes: 4 additions & 0 deletions tests/ui/impl-trait/precise-capturing/overcaptures-2024.fixed
Original file line number Diff line number Diff line change
Expand Up @@ -42,4 +42,8 @@ async fn async_fn<'a>(x: &'a ()) -> impl Sized + use<> {}
//~^ ERROR `impl Sized` will capture more lifetimes than possibly intended in edition 2024
//~| WARN this changes meaning in Rust 2024

pub fn parens(x: &i32) -> &(impl Clone + use<>) { x }
//~^ ERROR `impl Clone` will capture more lifetimes than possibly intended in edition 2024
//~| WARN this changes meaning in Rust 2024

fn main() {}
4 changes: 4 additions & 0 deletions tests/ui/impl-trait/precise-capturing/overcaptures-2024.rs
Original file line number Diff line number Diff line change
Expand Up @@ -42,4 +42,8 @@ async fn async_fn<'a>(x: &'a ()) -> impl Sized {}
//~^ ERROR `impl Sized` will capture more lifetimes than possibly intended in edition 2024
//~| WARN this changes meaning in Rust 2024

pub fn parens(x: &i32) -> &impl Clone { x }
//~^ ERROR `impl Clone` will capture more lifetimes than possibly intended in edition 2024
//~| WARN this changes meaning in Rust 2024

fn main() {}
21 changes: 20 additions & 1 deletion tests/ui/impl-trait/precise-capturing/overcaptures-2024.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -146,5 +146,24 @@ help: use the precise capturing `use<...>` syntax to make the captures explicit
LL | async fn async_fn<'a>(x: &'a ()) -> impl Sized + use<> {}
| +++++++

error: aborting due to 7 previous errors
error: `impl Clone` will capture more lifetimes than possibly intended in edition 2024
--> $DIR/overcaptures-2024.rs:45:28
|
LL | pub fn parens(x: &i32) -> &impl Clone { x }
| ^^^^^^^^^^
|
= warning: this changes meaning in Rust 2024
= note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2024/rpit-lifetime-capture.html>
note: specifically, this lifetime is in scope but not mentioned in the type's bounds
--> $DIR/overcaptures-2024.rs:45:18
|
LL | pub fn parens(x: &i32) -> &impl Clone { x }
| ^
= note: all lifetimes in scope will be captured by `impl Trait`s in edition 2024
help: use the precise capturing `use<...>` syntax to make the captures explicit
|
LL | pub fn parens(x: &i32) -> &(impl Clone + use<>) { x }
| + ++++++++

error: aborting due to 8 previous errors

0 comments on commit e134c74

Please sign in to comment.