Skip to content

Commit

Permalink
Rollup merge of #134142 - compiler-errors:paren-sug, r=jieyouxu
Browse files Browse the repository at this point in the history
Rudimentary heuristic to insert parentheses when needed for RPIT overcaptures lint

We don't have basically any preexisting machinery to detect when parentheses are needed for *types*. AFAICT, all of the diagnostics we have for opaques just... fail when they suggest `+ 'a` when that's ambiguous.

Fixes #132853
  • Loading branch information
jhpratt authored Dec 11, 2024
2 parents 16b6493 + e134c74 commit f103076
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 f103076

Please sign in to comment.