Rudimentary heuristic to insert parentheses when needed for RPIT overcaptures lint
This commit is contained in:
parent
33c245b9e9
commit
e134c74904
4 changed files with 58 additions and 6 deletions
|
@ -10,7 +10,7 @@ use rustc_hir as hir;
|
||||||
use rustc_hir::def::DefKind;
|
use rustc_hir::def::DefKind;
|
||||||
use rustc_hir::def_id::{DefId, LocalDefId};
|
use rustc_hir::def_id::{DefId, LocalDefId};
|
||||||
use rustc_hir::intravisit::{Visitor, walk_ty};
|
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_macros::{Diagnostic, Subdiagnostic};
|
||||||
use rustc_middle::ty::print::{PrintTraitRefExt as _, TraitRefPrintOnlyTraitPath};
|
use rustc_middle::ty::print::{PrintTraitRefExt as _, TraitRefPrintOnlyTraitPath};
|
||||||
use rustc_middle::ty::{self, Binder, ClosureKind, FnSig, PolyTraitRef, Region, Ty, TyCtxt};
|
use rustc_middle::ty::{self, Binder, ClosureKind, FnSig, PolyTraitRef, Region, Ty, TyCtxt};
|
||||||
|
@ -1888,10 +1888,35 @@ pub fn impl_trait_overcapture_suggestion<'tcx>(
|
||||||
.collect::<Vec<_>>()
|
.collect::<Vec<_>>()
|
||||||
.join(", ");
|
.join(", ");
|
||||||
|
|
||||||
suggs.push((
|
let opaque_hir_id = tcx.local_def_id_to_hir_id(opaque_def_id);
|
||||||
tcx.def_span(opaque_def_id).shrink_to_hi(),
|
// FIXME: This is a bit too conservative, since it ignores parens already written in AST.
|
||||||
format!(" + use<{concatenated_bounds}>"),
|
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 })
|
Some(AddPreciseCapturingForOvercapture { suggs, apit_spans })
|
||||||
}
|
}
|
||||||
|
|
|
@ -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
|
//~^ ERROR `impl Sized` will capture more lifetimes than possibly intended in edition 2024
|
||||||
//~| WARN this changes meaning in Rust 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() {}
|
fn main() {}
|
||||||
|
|
|
@ -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
|
//~^ ERROR `impl Sized` will capture more lifetimes than possibly intended in edition 2024
|
||||||
//~| WARN this changes meaning in Rust 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() {}
|
fn main() {}
|
||||||
|
|
|
@ -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<> {}
|
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
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue