1use std::cell::LazyCell;
2use std::debug_assert_matches;
3
4use rustc_data_structures::fx::{FxHashMap, FxIndexMap, FxIndexSet};
5use rustc_data_structures::unord::UnordSet;
6use rustc_errors::{Diagnostic, Subdiagnostic, msg};
7use rustc_hir as hir;
8use rustc_hir::def::DefKind;
9use rustc_hir::def_id::{DefId, LocalDefId};
10use rustc_infer::infer::TyCtxtInferExt;
11use rustc_infer::infer::outlives::env::OutlivesEnvironment;
12use rustc_lint_defs::{declare_lint, declare_lint_pass, fcw};
13use rustc_macros::Diagnostic;
14use rustc_middle::middle::resolve_bound_vars::ResolvedArg;
15use rustc_middle::ty::relate::{
16 Relate, RelateResult, TypeRelation, relate_args_with_variances, structurally_relate_consts,
17 structurally_relate_tys,
18};
19use rustc_middle::ty::{
20 self, Ty, TyCtxt, TypeSuperVisitable, TypeVisitable, TypeVisitableExt, TypeVisitor,
21 Unnormalized,
22};
23use rustc_span::{Span, Symbol, bug, span_bug};
24use rustc_trait_selection::diagnostics::{
25 AddPreciseCapturingForOvercapture, impl_trait_overcapture_suggestion,
26};
27use rustc_trait_selection::regions::OutlivesEnvironmentBuildExt;
28use rustc_trait_selection::traits::ObligationCtxt;
29
30use crate::{LateContext, LateLintPass};
31
32#[doc =
r" The `impl_trait_overcaptures` lint warns against cases where lifetime"]
#[doc = r" capture behavior will differ in edition 2024."]
#[doc = r""]
#[doc =
r" In the 2024 edition, `impl Trait`s will capture all lifetimes in scope,"]
#[doc =
r" rather than just the lifetimes that are mentioned in the bounds of the type."]
#[doc =
r" Often these sets are equal, but if not, it means that the `impl Trait` may"]
#[doc = r" cause erroneous borrow-checker errors."]
#[doc = r""]
#[doc = r" ### Example"]
#[doc = r""]
#[doc = r" ```rust,compile_fail,edition2021"]
#[doc = r" # #![deny(impl_trait_overcaptures)]"]
#[doc = r" # use std::fmt::Display;"]
#[doc = r" let mut x = vec![];"]
#[doc = r" x.push(1);"]
#[doc = r""]
#[doc = r" fn test(x: &Vec<i32>) -> impl Display {"]
#[doc = r" x[0]"]
#[doc = r" }"]
#[doc = r""]
#[doc = r" let element = test(&x);"]
#[doc = r" x.push(2);"]
#[doc = r#" println!("{element}");"#]
#[doc = r" ```"]
#[doc = r""]
#[doc = r" {{produces}}"]
#[doc = r""]
#[doc = r" ### Explanation"]
#[doc = r""]
#[doc =
r" In edition < 2024, the returned `impl Display` doesn't capture the"]
#[doc =
r" lifetime from the `&Vec<i32>`, so the vector can be mutably borrowed"]
#[doc = r" while the `impl Display` is live."]
#[doc = r""]
#[doc =
r" To fix this, we can explicitly state that the `impl Display` doesn't"]
#[doc = r" capture any lifetimes, using `impl Display + use<>`."]
pub static IMPL_TRAIT_OVERCAPTURES: &::rustc_lint_defs::Lint =
&::rustc_lint_defs::Lint {
name: "IMPL_TRAIT_OVERCAPTURES",
default_level: ::rustc_lint_defs::Allow,
desc: "`impl Trait` will capture more lifetimes than possibly intended in edition 2024",
is_externally_loaded: false,
future_incompatible: Some(::rustc_lint_defs::FutureIncompatibleInfo {
reason: ::rustc_lint_defs::FutureIncompatibilityReason::EditionSemanticsChange(::rustc_lint_defs::EditionFcw {
edition: rustc_span::edition::Edition::Edition2024,
page_slug: "rpit-lifetime-capture",
}),
..::rustc_lint_defs::FutureIncompatibleInfo::default_fields_for_macro()
}),
..::rustc_lint_defs::Lint::default_fields_for_macro()
};declare_lint! {
33 pub IMPL_TRAIT_OVERCAPTURES,
69 Allow,
70 "`impl Trait` will capture more lifetimes than possibly intended in edition 2024",
71 @future_incompatible = FutureIncompatibleInfo {
72 reason: fcw!(EditionSemanticsChange 2024 "rpit-lifetime-capture"),
73 };
74}
75
76#[doc =
r" The `impl_trait_redundant_captures` lint warns against cases where use of the"]
#[doc = r" precise capturing `use<...>` syntax is not needed."]
#[doc = r""]
#[doc =
r" In the 2024 edition, `impl Trait`s will capture all lifetimes in scope."]
#[doc =
r" If precise-capturing `use<...>` syntax is used, and the set of parameters"]
#[doc =
r" that are captures are *equal* to the set of parameters in scope, then"]
#[doc = r" the syntax is redundant, and can be removed."]
#[doc = r""]
#[doc = r" ### Example"]
#[doc = r""]
#[doc = r" ```rust,edition2024,compile_fail"]
#[doc = r" # #![deny(impl_trait_redundant_captures)]"]
#[doc = r" fn test<'a>(x: &'a i32) -> impl Sized + use<'a> { x }"]
#[doc = r" ```"]
#[doc = r""]
#[doc = r" {{produces}}"]
#[doc = r""]
#[doc = r" ### Explanation"]
#[doc = r""]
#[doc =
r" To fix this, remove the `use<'a>`, since the lifetime is already captured"]
#[doc = r" since it is in scope."]
pub static IMPL_TRAIT_REDUNDANT_CAPTURES: &::rustc_lint_defs::Lint =
&::rustc_lint_defs::Lint {
name: "IMPL_TRAIT_REDUNDANT_CAPTURES",
default_level: ::rustc_lint_defs::Allow,
desc: "redundant precise-capturing `use<...>` syntax on an `impl Trait`",
is_externally_loaded: false,
..::rustc_lint_defs::Lint::default_fields_for_macro()
};declare_lint! {
77 pub IMPL_TRAIT_REDUNDANT_CAPTURES,
99 Allow,
100 "redundant precise-capturing `use<...>` syntax on an `impl Trait`",
101}
102
103#[doc =
r" Lint for opaque types that will begin capturing in-scope but unmentioned lifetimes"]
#[doc = r" in edition 2024."]
pub struct ImplTraitOvercaptures;
#[automatically_derived]
impl ::core::marker::Copy for ImplTraitOvercaptures { }
#[automatically_derived]
#[doc(hidden)]
unsafe impl ::core::clone::TrivialClone for ImplTraitOvercaptures { }
#[automatically_derived]
impl ::core::clone::Clone for ImplTraitOvercaptures {
#[inline]
fn clone(&self) -> Self { *self }
}
impl ::rustc_lint_defs::LintPass for ImplTraitOvercaptures {
fn name(&self) -> &'static str { "ImplTraitOvercaptures" }
fn get_lints(&self) -> ::rustc_lint_defs::LintVec {
::alloc::boxed::box_assume_init_into_vec_unsafe(::alloc::intrinsics::write_box_via_move(::alloc::boxed::Box::new_uninit(),
[IMPL_TRAIT_OVERCAPTURES, IMPL_TRAIT_REDUNDANT_CAPTURES]))
}
}
impl ImplTraitOvercaptures {
#[allow(unused)]
pub fn lint_vec() -> ::rustc_lint_defs::LintVec {
::alloc::boxed::box_assume_init_into_vec_unsafe(::alloc::intrinsics::write_box_via_move(::alloc::boxed::Box::new_uninit(),
[IMPL_TRAIT_OVERCAPTURES, IMPL_TRAIT_REDUNDANT_CAPTURES]))
}
}declare_lint_pass!(
104 ImplTraitOvercaptures => [IMPL_TRAIT_OVERCAPTURES, IMPL_TRAIT_REDUNDANT_CAPTURES]
107);
108
109impl<'tcx> LateLintPass<'tcx> for ImplTraitOvercaptures {
110 fn check_item(&mut self, cx: &LateContext<'tcx>, it: &'tcx hir::Item<'tcx>) {
111 match &it.kind {
112 hir::ItemKind::Fn { .. } => check_fn(cx.tcx, it.owner_id.def_id),
113 _ => {}
114 }
115 }
116
117 fn check_impl_item(&mut self, cx: &LateContext<'tcx>, it: &'tcx hir::ImplItem<'tcx>) {
118 match &it.kind {
119 hir::ImplItemKind::Fn(_, _) => check_fn(cx.tcx, it.owner_id.def_id),
120 _ => {}
121 }
122 }
123
124 fn check_trait_item(&mut self, cx: &LateContext<'tcx>, it: &'tcx hir::TraitItem<'tcx>) {
125 match &it.kind {
126 hir::TraitItemKind::Fn(_, _) => check_fn(cx.tcx, it.owner_id.def_id),
127 _ => {}
128 }
129 }
130}
131
132#[derive(#[automatically_derived]
impl ::core::marker::StructuralPartialEq for ParamKind { }
#[automatically_derived]
impl ::core::cmp::PartialEq for ParamKind {
#[inline]
fn eq(&self, other: &Self) -> bool {
::core::intrinsics::discriminant_value(self) ==
::core::intrinsics::discriminant_value(other) &&
match (self, other) {
(Self::Early(__self_0, __self_1),
Self::Early(__arg1_0, __arg1_1)) =>
__self_1 == __arg1_1 && __self_0 == __arg1_0,
(Self::Free(__self_0), Self::Free(__arg1_0)) =>
__self_0 == __arg1_0,
_ => true,
}
}
}PartialEq, #[automatically_derived]
impl ::core::cmp::Eq for ParamKind {
#[inline]
#[doc(hidden)]
#[coverage(off)]
fn assert_fields_are_eq(&self) {
let _: ::core::cmp::AssertParamIsEq<Symbol>;
let _: ::core::cmp::AssertParamIsEq<u32>;
let _: ::core::cmp::AssertParamIsEq<DefId>;
}
}Eq, #[automatically_derived]
impl ::core::hash::Hash for ParamKind {
#[inline]
fn hash<__H: ::core::hash::Hasher>(&self, state: &mut __H) {
::core::hash::Hash::hash(&::core::intrinsics::discriminant_value(self),
state);
match self {
Self::Early(__self_0, __self_1) => {
::core::hash::Hash::hash(__self_0, state);
::core::hash::Hash::hash(__self_1, state)
}
Self::Free(__self_0) => ::core::hash::Hash::hash(__self_0, state),
_ => {}
}
}
}Hash, #[automatically_derived]
impl ::core::fmt::Debug for ParamKind {
#[inline]
fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
match self {
Self::Early(__self_0, __self_1) =>
::core::fmt::Formatter::debug_tuple_field2_finish(f, "Early",
__self_0, &__self_1),
Self::Free(__self_0) =>
::core::fmt::Formatter::debug_tuple_field1_finish(f, "Free",
&__self_0),
Self::Late => ::core::fmt::Formatter::write_str(f, "Late"),
}
}
}Debug, #[automatically_derived]
impl ::core::marker::Copy for ParamKind { }Copy, #[automatically_derived]
#[doc(hidden)]
unsafe impl ::core::clone::TrivialClone for ParamKind { }
#[automatically_derived]
impl ::core::clone::Clone for ParamKind {
#[inline]
fn clone(&self) -> Self {
let _: ::core::clone::AssertParamIsClone<Symbol>;
let _: ::core::clone::AssertParamIsClone<u32>;
let _: ::core::clone::AssertParamIsClone<DefId>;
*self
}
}Clone)]
133enum ParamKind {
134 Early(Symbol, u32),
136 Free(DefId),
138 Late,
140}
141
142fn check_fn(tcx: TyCtxt<'_>, parent_def_id: LocalDefId) {
143 let sig = tcx.fn_sig(parent_def_id).instantiate_identity().skip_norm_wip();
144
145 let mut in_scope_parameters = FxIndexMap::default();
146 let mut current_def_id = Some(parent_def_id.to_def_id());
148 while let Some(def_id) = current_def_id {
149 let generics = tcx.generics_of(def_id);
150 for param in &generics.own_params {
151 in_scope_parameters.insert(param.def_id, ParamKind::Early(param.name, param.index));
152 }
153 current_def_id = generics.parent;
154 }
155
156 for bound_var in sig.bound_vars() {
157 let ty::BoundVariableKind::Region(ty::BoundRegionKind::Named(def_id)) = bound_var else {
158 ::rustc_span::macros::bug_impl(Some(tcx.def_span(parent_def_id)),
format_args!("unexpected non-lifetime binder on fn sig"),
Location::caller());span_bug!(tcx.def_span(parent_def_id), "unexpected non-lifetime binder on fn sig");
159 };
160
161 in_scope_parameters.insert(def_id, ParamKind::Free(def_id));
162 }
163
164 let sig = tcx.liberate_late_bound_regions(parent_def_id.to_def_id(), sig);
165
166 sig.visit_with(&mut VisitOpaqueTypes {
169 tcx,
170 parent_def_id,
171 in_scope_parameters,
172 seen: Default::default(),
173 variances: LazyCell::new(|| {
175 let mut functional_variances = FunctionalVariances {
176 tcx,
177 variances: FxHashMap::default(),
178 ambient_variance: ty::Covariant,
179 generics: tcx.generics_of(parent_def_id),
180 };
181 functional_variances.relate(sig, sig).unwrap();
182 functional_variances.variances
183 }),
184 outlives_env: LazyCell::new(|| {
185 let typing_env = ty::TypingEnv::non_body_analysis(tcx, parent_def_id);
186 let (infcx, param_env) = tcx.infer_ctxt().build_with_typing_env(typing_env);
187 let ocx = ObligationCtxt::new(&infcx);
188 let assumed_wf_tys = ocx.assumed_wf_types(param_env, parent_def_id).unwrap_or_default();
189 OutlivesEnvironment::new(&infcx, parent_def_id, param_env, assumed_wf_tys)
190 }),
191 });
192}
193
194struct VisitOpaqueTypes<'tcx, VarFn, OutlivesFn> {
195 tcx: TyCtxt<'tcx>,
196 parent_def_id: LocalDefId,
197 in_scope_parameters: FxIndexMap<DefId, ParamKind>,
198 variances: LazyCell<FxHashMap<DefId, ty::Variance>, VarFn>,
199 outlives_env: LazyCell<OutlivesEnvironment<'tcx>, OutlivesFn>,
200 seen: FxIndexSet<LocalDefId>,
201}
202
203impl<'tcx, VarFn, OutlivesFn> TypeVisitor<TyCtxt<'tcx>>
204 for VisitOpaqueTypes<'tcx, VarFn, OutlivesFn>
205where
206 VarFn: FnOnce() -> FxHashMap<DefId, ty::Variance>,
207 OutlivesFn: FnOnce() -> OutlivesEnvironment<'tcx>,
208{
209 fn visit_binder<T: TypeVisitable<TyCtxt<'tcx>>>(&mut self, t: &ty::Binder<'tcx, T>) {
210 let mut added = ::alloc::vec::Vec::new()vec![];
212 for arg in t.bound_vars() {
213 let arg: ty::BoundVariableKind<'tcx> = arg;
214 match arg {
215 ty::BoundVariableKind::Region(ty::BoundRegionKind::Named(def_id))
216 | ty::BoundVariableKind::Ty(ty::BoundTyKind::Param(def_id)) => {
217 let previous = self.in_scope_parameters.insert(def_id, ParamKind::Late);
222 added.push((def_id, previous));
223 }
224 _ => {
225 self.tcx.dcx().span_delayed_bug(
226 self.tcx.def_span(self.parent_def_id),
227 ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("unsupported bound variable kind: {0:?}",
arg))
})format!("unsupported bound variable kind: {arg:?}"),
228 );
229 }
230 }
231 }
232
233 t.super_visit_with(self);
234
235 for (arg, previous) in added.into_iter().rev() {
237 if let Some(previous) = previous {
238 self.in_scope_parameters.insert(arg, previous);
239 } else {
240 self.in_scope_parameters.shift_remove(&arg);
241 }
242 }
243 }
244
245 fn visit_ty(&mut self, t: Ty<'tcx>) {
246 if !t.has_aliases() {
247 return;
248 }
249
250 if let ty::Alias(_, ty::AliasTy { kind: ty::Projection { def_id }, args, .. }) = *t.kind()
251 && self.tcx.is_impl_trait_in_trait(def_id)
252 {
253 self.tcx.type_of(def_id).instantiate(self.tcx, args).skip_norm_wip().visit_with(self)
255 } else if let ty::Alias(_, ty::AliasTy { kind: ty::Opaque { def_id }, args: opaque_ty_args, .. }) = *t.kind()
256 && let Some(opaque_def_id) = def_id.as_local()
257 && self.seen.insert(opaque_def_id)
259 && let opaque =
261 self.tcx.hir_node_by_def_id(opaque_def_id).expect_opaque_ty()
262 && let hir::OpaqueTyOrigin::FnReturn { parent, .. }
266 | hir::OpaqueTyOrigin::AsyncFn { parent, .. } = opaque.origin
267 && parent == self.parent_def_id
268 {
269 let opaque_span = self.tcx.def_span(opaque_def_id);
270 let new_capture_rules = opaque_span.at_least_rust_2024();
271 if !new_capture_rules
272 && !opaque.bounds.iter().any(|bound| #[allow(non_exhaustive_omitted_patterns)] match bound {
hir::GenericBound::Use(..) => true,
_ => false,
}matches!(bound, hir::GenericBound::Use(..)))
273 {
274 let mut captured = FxIndexSet::default();
276 let mut captured_regions = FxIndexSet::default();
277 let variances = self.tcx.variances_of(opaque_def_id);
278 let mut current_def_id = Some(opaque_def_id.to_def_id());
279 while let Some(def_id) = current_def_id {
280 let generics = self.tcx.generics_of(def_id);
281 for param in &generics.own_params {
282 if variances[param.index as usize] != ty::Invariant {
284 continue;
285 }
286
287 let arg = opaque_ty_args[param.index as usize];
288 captured.insert(extract_def_id_from_arg(self.tcx, generics, arg));
291
292 captured_regions.extend(arg.as_region());
293 }
294 current_def_id = generics.parent;
295 }
296
297 let mut uncaptured_args: FxIndexSet<_> = self
299 .in_scope_parameters
300 .iter()
301 .filter(|&(def_id, _)| !captured.contains(def_id))
302 .collect();
303 uncaptured_args.retain(|&(def_id, kind)| {
306 let Some(ty::Bivariant | ty::Contravariant) = self.variances.get(def_id) else {
307 return true;
311 };
312 if true {
{
match self.tcx.def_kind(*def_id) {
DefKind::LifetimeParam => {}
ref left_val => {
::core::panicking::assert_matches_failed(left_val,
"DefKind::LifetimeParam", ::core::option::Option::None);
}
}
};
};debug_assert_matches!(self.tcx.def_kind(*def_id), DefKind::LifetimeParam);
314 let uncaptured = match *kind {
315 ParamKind::Early(name, index) => ty::Region::new_early_param(
316 self.tcx,
317 ty::EarlyParamRegion { name, index },
318 ),
319 ParamKind::Free(def_id) => ty::Region::new_late_param(
320 self.tcx,
321 self.parent_def_id.to_def_id(),
322 ty::LateParamRegionKind::Named(def_id),
323 ),
324 ParamKind::Late => return true,
326 };
327 !captured_regions.iter().any(|r| {
329 self.outlives_env
330 .free_region_map()
331 .sub_free_regions(self.tcx, *r, uncaptured)
332 })
333 });
334
335 if !uncaptured_args.is_empty() {
338 let suggestion = impl_trait_overcapture_suggestion(
339 self.tcx,
340 opaque_def_id,
341 self.parent_def_id,
342 captured,
343 );
344
345 let uncaptured_spans: Vec<_> = uncaptured_args
346 .into_iter()
347 .map(|(&def_id, _)| self.tcx.def_span(def_id))
348 .collect();
349
350 self.tcx.emit_node_span_lint(
351 IMPL_TRAIT_OVERCAPTURES,
352 self.tcx.local_def_id_to_hir_id(opaque_def_id),
353 opaque_span,
354 ImplTraitOvercapturesLint {
355 self_ty: t,
356 num_captured: uncaptured_spans.len(),
357 uncaptured_spans,
358 suggestion,
359 },
360 );
361 }
362 }
363
364 if new_capture_rules
368 && let Some((use_idx, captured_args, capturing_span)) =
369 opaque.bounds.iter().enumerate().find_map(|(i, bound)| match *bound {
370 hir::GenericBound::Use(a, s) => Some((i, a, s)),
371 _ => None,
372 })
373 {
374 let mut explicitly_captured = UnordSet::default();
375 for arg in captured_args {
376 match self.tcx.named_bound_var(arg.hir_id()) {
377 Some(
378 ResolvedArg::EarlyBound(def_id) | ResolvedArg::LateBound(_, _, def_id),
379 ) => {
380 if self.tcx.def_kind(self.tcx.local_parent(def_id)) == DefKind::OpaqueTy
381 {
382 let def_id = self
383 .tcx
384 .map_opaque_lifetime_to_parent_lifetime(def_id)
385 .opt_param_def_id(self.tcx, self.parent_def_id.to_def_id())
386 .expect("variable should have been duplicated from parent");
387
388 explicitly_captured.insert(def_id);
389 } else {
390 explicitly_captured.insert(def_id.to_def_id());
391 }
392 }
393 _ => {
394 self.tcx.dcx().span_delayed_bug(
395 self.tcx.hir_span(arg.hir_id()),
396 "no valid for captured arg",
397 );
398 }
399 }
400 }
401
402 if self
403 .in_scope_parameters
404 .iter()
405 .all(|(def_id, _)| explicitly_captured.contains(def_id))
406 {
407 let suggestion_span = if let Some(next) = opaque.bounds.get(use_idx + 1) {
411 capturing_span.with_hi(next.span().lo())
412 } else if let Some(prev_idx) = use_idx.checked_sub(1) {
413 let prev = opaque.bounds[prev_idx];
414 capturing_span.with_lo(prev.span().hi())
415 } else {
416 capturing_span
419 };
420
421 self.tcx.emit_node_span_lint(
422 IMPL_TRAIT_REDUNDANT_CAPTURES,
423 self.tcx.local_def_id_to_hir_id(opaque_def_id),
424 opaque_span,
425 ImplTraitRedundantCapturesLint { capturing_span: suggestion_span },
426 );
427 }
428 }
429
430 for clause in self
435 .tcx
436 .item_bounds(def_id)
437 .iter_instantiated(self.tcx, opaque_ty_args)
438 .map(Unnormalized::skip_norm_wip)
439 {
440 clause.visit_with(self)
441 }
442 }
443
444 t.super_visit_with(self);
445 }
446}
447
448struct ImplTraitOvercapturesLint<'tcx> {
449 uncaptured_spans: Vec<Span>,
450 self_ty: Ty<'tcx>,
451 num_captured: usize,
452 suggestion: Option<AddPreciseCapturingForOvercapture>,
453}
454
455impl<'a> Diagnostic<'a> for ImplTraitOvercapturesLint<'_> {
456 fn into_diag(
457 self,
458 dcx: rustc_errors::DiagCtxtHandle<'a>,
459 level: rustc_errors::Level,
460 ) -> rustc_errors::Diag<'a> {
461 let mut diag = rustc_errors::Diag::new(
462 dcx,
463 level,
464 rustc_errors::DiagMessage::Inline(std::borrow::Cow::Borrowed("`{$self_ty}` will capture more lifetimes than possibly intended in edition 2024"))msg!("`{$self_ty}` will capture more lifetimes than possibly intended in edition 2024"),
465 );
466 diag.arg("self_ty", self.self_ty.to_string())
467 .arg("num_captured", self.num_captured)
468 .span_note(
469 self.uncaptured_spans,
470 rustc_errors::DiagMessage::Inline(std::borrow::Cow::Borrowed("specifically, {$num_captured ->\n [one] this lifetime is\n *[other] these lifetimes are\n } in scope but not mentioned in the type's bounds"))msg!(
471 "specifically, {$num_captured ->
472 [one] this lifetime is
473 *[other] these lifetimes are
474 } in scope but not mentioned in the type's bounds"
475 ),
476 )
477 .note(rustc_errors::DiagMessage::Inline(std::borrow::Cow::Borrowed("all lifetimes in scope will be captured by `impl Trait`s in edition 2024"))msg!("all lifetimes in scope will be captured by `impl Trait`s in edition 2024"));
478 if let Some(suggestion) = self.suggestion {
479 suggestion.add_to_diag(&mut diag);
480 }
481 diag
482 }
483}
484
485#[derive(const _: () =
{
impl<'_sess> rustc_errors::Diagnostic<'_sess> for
ImplTraitRedundantCapturesLint {
#[track_caller]
fn into_diag(self, dcx: rustc_errors::DiagCtxtHandle<'_sess>,
level: rustc_errors::Level) -> rustc_errors::Diag<'_sess> {
match self {
ImplTraitRedundantCapturesLint { capturing_span: __binding_0
} => {
let mut diag =
rustc_errors::Diag::new(dcx, level,
rustc_errors::DiagMessage::Inline(std::borrow::Cow::Borrowed("all possible in-scope parameters are already captured, so `use<...>` syntax is redundant")));
let __code_109 =
[::alloc::__export::must_use({
::alloc::fmt::format(format_args!(""))
})].into_iter();
;
diag.span_suggestions_with_style(__binding_0,
rustc_errors::DiagMessage::Inline(std::borrow::Cow::Borrowed("remove the `use<...>` syntax")),
__code_109, rustc_errors::Applicability::MachineApplicable,
rustc_errors::SuggestionStyle::ShowCode);
diag
}
}
}
}
};Diagnostic)]
486#[diag("all possible in-scope parameters are already captured, so `use<...>` syntax is redundant")]
487struct ImplTraitRedundantCapturesLint {
488 #[suggestion("remove the `use<...>` syntax", code = "", applicability = "machine-applicable")]
489 capturing_span: Span,
490}
491
492fn extract_def_id_from_arg<'tcx>(
493 tcx: TyCtxt<'tcx>,
494 generics: &'tcx ty::Generics,
495 arg: ty::GenericArg<'tcx>,
496) -> DefId {
497 match arg.kind() {
498 ty::GenericArgKind::Lifetime(re) => match re.kind() {
499 ty::ReEarlyParam(ebr) => generics.region_param(ebr, tcx).def_id,
500 ty::ReBound(_, ty::BoundRegion { kind: ty::BoundRegionKind::Named(def_id), .. })
501 | ty::ReLateParam(ty::LateParamRegion {
502 scope: _,
503 kind: ty::LateParamRegionKind::Named(def_id),
504 }) => def_id,
505 _ => ::core::panicking::panic("internal error: entered unreachable code")unreachable!(),
506 },
507 ty::GenericArgKind::Type(ty) => {
508 let ty::Param(param_ty) = *ty.kind() else {
509 ::rustc_span::macros::bug_impl(None, format_args!("impossible case reached"),
Location::caller());bug!();
510 };
511 generics.type_param(param_ty, tcx).def_id
512 }
513 ty::GenericArgKind::Const(ct) => {
514 let ty::ConstKind::Param(param_ct) = ct.kind() else {
515 ::rustc_span::macros::bug_impl(None, format_args!("impossible case reached"),
Location::caller());bug!();
516 };
517 generics.const_param(param_ct, tcx).def_id
518 }
519 }
520}
521
522struct FunctionalVariances<'tcx> {
529 tcx: TyCtxt<'tcx>,
530 variances: FxHashMap<DefId, ty::Variance>,
531 ambient_variance: ty::Variance,
532 generics: &'tcx ty::Generics,
533}
534
535impl<'tcx> TypeRelation<TyCtxt<'tcx>> for FunctionalVariances<'tcx> {
536 fn cx(&self) -> TyCtxt<'tcx> {
537 self.tcx
538 }
539
540 fn relate_ty_args(
541 &mut self,
542 a_ty: Ty<'tcx>,
543 _: Ty<'tcx>,
544 def_id: DefId,
545 a_args: ty::GenericArgsRef<'tcx>,
546 b_args: ty::GenericArgsRef<'tcx>,
547 _: impl FnOnce(ty::GenericArgsRef<'tcx>) -> Ty<'tcx>,
548 ) -> RelateResult<'tcx, Ty<'tcx>> {
549 let variances = self.cx().variances_of(def_id);
550 relate_args_with_variances(self, variances, a_args, b_args)?;
551 Ok(a_ty)
552 }
553
554 fn relate_with_variance<T: Relate<TyCtxt<'tcx>>>(
555 &mut self,
556 variance: ty::Variance,
557 _: ty::VarianceDiagInfo<TyCtxt<'tcx>>,
558 a: T,
559 b: T,
560 ) -> RelateResult<'tcx, T> {
561 let old_variance = self.ambient_variance;
562 self.ambient_variance = self.ambient_variance.xform(variance);
563 self.relate(a, b).unwrap();
564 self.ambient_variance = old_variance;
565 Ok(a)
566 }
567
568 fn tys(&mut self, a: Ty<'tcx>, b: Ty<'tcx>) -> RelateResult<'tcx, Ty<'tcx>> {
569 structurally_relate_tys(self, a, b).unwrap();
570 Ok(a)
571 }
572
573 fn regions(
574 &mut self,
575 a: ty::Region<'tcx>,
576 _: ty::Region<'tcx>,
577 ) -> RelateResult<'tcx, ty::Region<'tcx>> {
578 let def_id = match a.kind() {
579 ty::ReEarlyParam(ebr) => self.generics.region_param(ebr, self.tcx).def_id,
580 ty::ReBound(_, ty::BoundRegion { kind: ty::BoundRegionKind::Named(def_id), .. })
581 | ty::ReLateParam(ty::LateParamRegion {
582 scope: _,
583 kind: ty::LateParamRegionKind::Named(def_id),
584 }) => def_id,
585 _ => {
586 return Ok(a);
587 }
588 };
589
590 if let Some(variance) = self.variances.get_mut(&def_id) {
591 *variance = unify(*variance, self.ambient_variance);
592 } else {
593 self.variances.insert(def_id, self.ambient_variance);
594 }
595
596 Ok(a)
597 }
598
599 fn consts(
600 &mut self,
601 a: ty::Const<'tcx>,
602 b: ty::Const<'tcx>,
603 ) -> RelateResult<'tcx, ty::Const<'tcx>> {
604 structurally_relate_consts(self, a, b).unwrap();
605 Ok(a)
606 }
607
608 fn binders<T>(
609 &mut self,
610 a: ty::Binder<'tcx, T>,
611 b: ty::Binder<'tcx, T>,
612 ) -> RelateResult<'tcx, ty::Binder<'tcx, T>>
613 where
614 T: Relate<TyCtxt<'tcx>>,
615 {
616 self.relate(a.skip_binder(), b.skip_binder()).unwrap();
617 Ok(a)
618 }
619}
620
621fn unify(a: ty::Variance, b: ty::Variance) -> ty::Variance {
623 match (a, b) {
624 (ty::Bivariant, other) | (other, ty::Bivariant) => other,
626 (ty::Invariant, _) | (_, ty::Invariant) => ty::Invariant,
628 (ty::Contravariant, ty::Covariant) | (ty::Covariant, ty::Contravariant) => ty::Invariant,
630 (ty::Contravariant, ty::Contravariant) => ty::Contravariant,
632 (ty::Covariant, ty::Covariant) => ty::Covariant,
633 }
634}