@@ -9,31 +9,87 @@ use rustc_middle::middle::resolve_bound_vars::ResolvedArg;
99use rustc_middle:: ty:: {
1010 self , Ty , TyCtxt , TypeSuperVisitable , TypeVisitable , TypeVisitableExt , TypeVisitor ,
1111} ;
12- use rustc_session:: lint:: FutureIncompatibilityReason ;
13- use rustc_span:: edition:: Edition ;
14- use rustc_span:: { BytePos , Span } ;
12+ use rustc_span:: { sym, BytePos , Span } ;
1513
1614use crate :: fluent_generated as fluent;
1715use crate :: { LateContext , LateLintPass } ;
1816
19- // TODO: feature gate these too
20-
2117declare_lint ! {
22- /// UwU
18+ /// The `impl_trait_overcaptures` lint warns against cases where lifetime
19+ /// capture behavior will differ in edition 2024.
20+ ///
21+ /// In the 2024 edition, `impl Trait`s will capture all lifetimes in scope,
22+ /// rather than just the lifetimes that are mentioned in the bounds of the type.
23+ /// Often these sets are equal, but if not, it means that the `impl Trait` may
24+ /// cause erroneous borrow-checker errors.
25+ ///
26+ /// ### Example
27+ ///
28+ /// ```rust,compile_fail
29+ /// # #![feature(precise_capturing)]
30+ /// # #![allow(incomplete_features)]
31+ /// # #![deny(impl_trait_overcaptures)]
32+ /// # use std::fmt::Display;
33+ /// let mut x = vec![];
34+ /// x.push(1);
35+ ///
36+ /// fn test(x: &Vec<i32>) -> impl Display {
37+ /// x[0]
38+ /// }
39+ ///
40+ /// let element = test(&x);
41+ /// x.push(2);
42+ /// println!("{element}");
43+ /// ```
44+ ///
45+ /// {{produces}}
46+ ///
47+ /// ### Explanation
48+ ///
49+ /// In edition < 2024, the returned `impl Display` doesn't capture the
50+ /// lifetime from the `&Vec<i32>`, so the vector can be mutably borrowed
51+ /// while the `impl Display` is live.
52+ ///
53+ /// To fix this, we can explicitly state that the `impl Display` doesn't
54+ /// capture any lifetimes, using `impl use<> Display`.
2355 pub IMPL_TRAIT_OVERCAPTURES ,
2456 Allow ,
25- "will capture more lifetimes than possibly intended in edition 2024" ,
26- @future_incompatible = FutureIncompatibleInfo {
27- reason: FutureIncompatibilityReason :: EditionSemanticsChange ( Edition :: Edition2024 ) ,
28- reference: "<https://doc.rust-lang.org/nightly/edition-guide/rust-2021/IntoIterator-for-arrays.html>" ,
29- } ;
57+ "`impl Trait` will capture more lifetimes than possibly intended in edition 2024" ,
58+ @feature_gate = sym:: precise_capturing;
59+ //@future_incompatible = FutureIncompatibleInfo {
60+ // reason: FutureIncompatibilityReason::EditionSemanticsChange(Edition::Edition2024),
61+ // reference: "<FIXME>",
62+ //};
3063}
3164
3265declare_lint ! {
33- /// UwU
66+ /// The `impl_trait_redundant_captures` lint warns against cases where use of the
67+ /// precise capturing `use<...>` syntax is not needed.
68+ ///
69+ /// In the 2024 edition, `impl Trait`s will capture all lifetimes in scope.
70+ /// If precise-capturing `use<...>` syntax is used, and the set of parameters
71+ /// that are captures are *equal* to the set of parameters in scope, then
72+ /// the syntax is redundant, and can be removed.
73+ ///
74+ /// ### Example
75+ ///
76+ /// ```rust,compile_fail
77+ /// # #![feature(precise_capturing, lifetime_capture_rules_2024)]
78+ /// # #![allow(incomplete_features)]
79+ /// # #![deny(impl_trait_redundant_captures)]
80+ /// fn test<'a>(x: &'a i32) -> impl use<'a> Sized { x }
81+ /// ```
82+ ///
83+ /// {{produces}}
84+ ///
85+ /// ### Explanation
86+ ///
87+ /// To fix this, remove the `use<'a>`, since the lifetime is already captured
88+ /// since it is in scope.
3489 pub IMPL_TRAIT_REDUNDANT_CAPTURES ,
3590 Warn ,
36- "uwu 2"
91+ "redundant precise-capturing `use<...>` syntax on an `impl Trait`" ,
92+ @feature_gate = sym:: precise_capturing;
3793}
3894
3995declare_lint_pass ! (
@@ -106,7 +162,8 @@ impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for VisitOpaqueTypes<'tcx> {
106162 for arg in t. bound_vars ( ) {
107163 let arg: ty:: BoundVariableKind = arg;
108164 match arg {
109- ty:: BoundVariableKind :: Region ( ty:: BoundRegionKind :: BrNamed ( def_id, ..) ) => {
165+ ty:: BoundVariableKind :: Region ( ty:: BoundRegionKind :: BrNamed ( def_id, ..) )
166+ | ty:: BoundVariableKind :: Ty ( ty:: BoundTyKind :: Param ( def_id, _) ) => {
110167 added. push ( def_id) ;
111168 let unique = self . in_scope_parameters . insert ( def_id) ;
112169 assert ! ( unique) ;
@@ -265,7 +322,7 @@ impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for VisitOpaqueTypes<'tcx> {
265322 }
266323 _ => {
267324 self . tcx . dcx ( ) . span_delayed_bug (
268- self . tcx ( ) . hir ( ) . span ( arg. hir_id ( ) ) ,
325+ self . tcx . hir ( ) . span ( arg. hir_id ( ) ) ,
269326 "no valid for captured arg" ,
270327 ) ;
271328 }
0 commit comments