1use rustc_data_structures::fx::FxIndexSet;
4use rustc_errors::{Applicability, Diag, ErrorGuaranteed};
5use rustc_hir::def_id::DefId;
6use rustc_hir::intravisit::{Visitor, VisitorExt, walk_ty};
7use rustc_hir::{
8 self as hir, AmbigArg, GenericBound, GenericParam, GenericParamKind, Item, ItemKind, Lifetime,
9 LifetimeKind, LifetimeParamKind, MissingLifetimeKind, Node, TyKind,
10};
11use rustc_middle::ty::{self, Ty, TyCtxt, TypeSuperVisitable, TypeVisitor};
12use rustc_span::def_id::LocalDefId;
13use rustc_span::{Ident, Span};
14use tracing::debug;
15
16use crate::diagnostics::ButNeedsToSatisfy;
17use crate::error_reporting::infer::nice_region_error::NiceRegionError;
18use crate::infer::{RegionResolutionError, SubregionOrigin};
19
20impl<'a, 'tcx> NiceRegionError<'a, 'tcx> {
21 pub(super) fn try_report_static_impl_trait(&self) -> Option<ErrorGuaranteed> {
24 {
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("event compiler/rustc_trait_selection/src/error_reporting/infer/nice_region_error/static_impl_trait.rs:24",
"rustc_trait_selection::error_reporting::infer::nice_region_error::static_impl_trait",
::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("compiler/rustc_trait_selection/src/error_reporting/infer/nice_region_error/static_impl_trait.rs"),
::tracing_core::__macro_support::Option::Some(24u32),
::tracing_core::__macro_support::Option::Some("rustc_trait_selection::error_reporting::infer::nice_region_error::static_impl_trait"),
::tracing_core::field::FieldSet::new(&["message"],
::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::EVENT)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let enabled =
::tracing::Level::DEBUG <= ::tracing::level_filters::STATIC_MAX_LEVEL
&&
::tracing::Level::DEBUG <=
::tracing::level_filters::LevelFilter::current() &&
{
let interest = __CALLSITE.interest();
!interest.is_never() &&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest)
};
if enabled {
(|value_set: ::tracing::field::ValueSet|
{
let meta = __CALLSITE.metadata();
::tracing::Event::dispatch(meta, &value_set);
;
})({
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
let mut iter = __CALLSITE.metadata().fields().iter();
__CALLSITE.metadata().fields().value_set(&[(&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
::tracing::__macro_support::Option::Some(&format_args!("try_report_static_impl_trait(error={0:?})",
self.error) as &dyn Value))])
});
} else { ; }
};debug!("try_report_static_impl_trait(error={:?})", self.error);
25 let tcx = self.tcx();
26 let (var_origin, sub_origin, sub_r, sup_origin, sup_r, spans) = match self.error.as_ref()? {
27 RegionResolutionError::SubSupConflict(
28 _,
29 var_origin,
30 sub_origin,
31 sub_r,
32 sup_origin,
33 sup_r,
34 spans,
35 ) if sub_r.is_static() => (var_origin, sub_origin, sub_r, sup_origin, sup_r, spans),
36 _ => return None,
37 };
38 {
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("event compiler/rustc_trait_selection/src/error_reporting/infer/nice_region_error/static_impl_trait.rs:38",
"rustc_trait_selection::error_reporting::infer::nice_region_error::static_impl_trait",
::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("compiler/rustc_trait_selection/src/error_reporting/infer/nice_region_error/static_impl_trait.rs"),
::tracing_core::__macro_support::Option::Some(38u32),
::tracing_core::__macro_support::Option::Some("rustc_trait_selection::error_reporting::infer::nice_region_error::static_impl_trait"),
::tracing_core::field::FieldSet::new(&["message"],
::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::EVENT)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let enabled =
::tracing::Level::DEBUG <= ::tracing::level_filters::STATIC_MAX_LEVEL
&&
::tracing::Level::DEBUG <=
::tracing::level_filters::LevelFilter::current() &&
{
let interest = __CALLSITE.interest();
!interest.is_never() &&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest)
};
if enabled {
(|value_set: ::tracing::field::ValueSet|
{
let meta = __CALLSITE.metadata();
::tracing::Event::dispatch(meta, &value_set);
;
})({
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
let mut iter = __CALLSITE.metadata().fields().iter();
__CALLSITE.metadata().fields().value_set(&[(&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
::tracing::__macro_support::Option::Some(&format_args!("try_report_static_impl_trait(var={0:?}, sub={1:?} {2:?} sup={3:?} {4:?})",
var_origin, sub_origin, sub_r, sup_origin, sup_r) as
&dyn Value))])
});
} else { ; }
};debug!(
39 "try_report_static_impl_trait(var={:?}, sub={:?} {:?} sup={:?} {:?})",
40 var_origin, sub_origin, sub_r, sup_origin, sup_r
41 );
42 let anon_reg_sup = tcx.is_suitable_region(self.generic_param_scope, *sup_r)?;
43 {
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("event compiler/rustc_trait_selection/src/error_reporting/infer/nice_region_error/static_impl_trait.rs:43",
"rustc_trait_selection::error_reporting::infer::nice_region_error::static_impl_trait",
::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("compiler/rustc_trait_selection/src/error_reporting/infer/nice_region_error/static_impl_trait.rs"),
::tracing_core::__macro_support::Option::Some(43u32),
::tracing_core::__macro_support::Option::Some("rustc_trait_selection::error_reporting::infer::nice_region_error::static_impl_trait"),
::tracing_core::field::FieldSet::new(&["message"],
::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::EVENT)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let enabled =
::tracing::Level::DEBUG <= ::tracing::level_filters::STATIC_MAX_LEVEL
&&
::tracing::Level::DEBUG <=
::tracing::level_filters::LevelFilter::current() &&
{
let interest = __CALLSITE.interest();
!interest.is_never() &&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest)
};
if enabled {
(|value_set: ::tracing::field::ValueSet|
{
let meta = __CALLSITE.metadata();
::tracing::Event::dispatch(meta, &value_set);
;
})({
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
let mut iter = __CALLSITE.metadata().fields().iter();
__CALLSITE.metadata().fields().value_set(&[(&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
::tracing::__macro_support::Option::Some(&format_args!("try_report_static_impl_trait: anon_reg_sup={0:?}",
anon_reg_sup) as &dyn Value))])
});
} else { ; }
};debug!("try_report_static_impl_trait: anon_reg_sup={:?}", anon_reg_sup);
44 let sp = var_origin.span();
45 let return_sp = sub_origin.span();
46 let param = self.find_param_with_region(*sup_r, *sub_r)?;
47 let simple_ident = param.param.pat.simple_ident();
48 let lifetime_name =
49 if sup_r.is_named(self.tcx()) { sup_r.to_string() } else { "'_".to_owned() };
50
51 let (mention_influencer, influencer_point) =
52 if sup_origin.span().overlaps(param.param_ty_span) {
53 (false, sup_origin.span())
65 } else {
66 (!sup_origin.span().overlaps(return_sp), param.param_ty_span)
67 };
68
69 {
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("event compiler/rustc_trait_selection/src/error_reporting/infer/nice_region_error/static_impl_trait.rs:69",
"rustc_trait_selection::error_reporting::infer::nice_region_error::static_impl_trait",
::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("compiler/rustc_trait_selection/src/error_reporting/infer/nice_region_error/static_impl_trait.rs"),
::tracing_core::__macro_support::Option::Some(69u32),
::tracing_core::__macro_support::Option::Some("rustc_trait_selection::error_reporting::infer::nice_region_error::static_impl_trait"),
::tracing_core::field::FieldSet::new(&["message"],
::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::EVENT)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let enabled =
::tracing::Level::DEBUG <= ::tracing::level_filters::STATIC_MAX_LEVEL
&&
::tracing::Level::DEBUG <=
::tracing::level_filters::LevelFilter::current() &&
{
let interest = __CALLSITE.interest();
!interest.is_never() &&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest)
};
if enabled {
(|value_set: ::tracing::field::ValueSet|
{
let meta = __CALLSITE.metadata();
::tracing::Event::dispatch(meta, &value_set);
;
})({
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
let mut iter = __CALLSITE.metadata().fields().iter();
__CALLSITE.metadata().fields().value_set(&[(&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
::tracing::__macro_support::Option::Some(&format_args!("try_report_static_impl_trait: param_info={0:?}",
param) as &dyn Value))])
});
} else { ; }
};debug!("try_report_static_impl_trait: param_info={:?}", param);
70
71 let mut spans = spans.clone();
72
73 if mention_influencer {
74 spans.push(sup_origin.span());
75 }
76 spans.sort();
78 spans.dedup_by_key(|span| (span.lo(), span.hi()));
79
80 let require_span =
82 if sup_origin.span().overlaps(return_sp) { sup_origin.span() } else { return_sp };
83
84 let spans_empty = spans.is_empty();
85 let require_as_note = spans.iter().any(|sp| sp.overlaps(return_sp) || *sp > return_sp);
86 let bound = if let SubregionOrigin::RelateParamBound(_, _, Some(bound)) = sub_origin {
87 Some(*bound)
88 } else {
89 None
90 };
91
92 let diag = ButNeedsToSatisfy {
93 sp,
94 influencer_point,
95 spans: spans.clone(),
96 require_span_as_note: require_as_note.then_some(require_span),
100 require_span_as_label: (!require_as_note).then_some(require_span),
102
103 has_lifetime: sup_r.is_named(self.tcx()),
104 lifetime: lifetime_name.clone(),
105 has_param_name: simple_ident.is_some(),
106 param_name: simple_ident.map(|x| x.to_string()).unwrap_or_default(),
107 spans_empty,
108 bound,
109 };
110
111 let mut err = self.tcx().dcx().create_err(diag);
112
113 let fn_returns = tcx.return_type_impl_or_dyn_traits(anon_reg_sup.scope);
114
115 let arg = match param.param.pat.simple_ident() {
116 Some(simple_ident) => ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("argument `{0}`", simple_ident))
})format!("argument `{simple_ident}`"),
117 None => "the argument".to_string(),
118 };
119 let captures = ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("captures data from {0}", arg))
})format!("captures data from {arg}");
120 suggest_new_region_bound(
121 tcx,
122 &mut err,
123 fn_returns,
124 lifetime_name,
125 Some(arg),
126 captures,
127 Some((param.param_ty_span, param.param_ty.to_string())),
128 Some(anon_reg_sup.scope),
129 );
130
131 let reported = err.emit();
132 Some(reported)
133 }
134}
135
136pub fn suggest_new_region_bound(
137 tcx: TyCtxt<'_>,
138 err: &mut Diag<'_>,
139 fn_returns: Vec<&rustc_hir::Ty<'_>>,
140 lifetime_name: String,
141 arg: Option<String>,
142 captures: String,
143 param: Option<(Span, String)>,
144 scope_def_id: Option<LocalDefId>,
145) {
146 {
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("event compiler/rustc_trait_selection/src/error_reporting/infer/nice_region_error/static_impl_trait.rs:146",
"rustc_trait_selection::error_reporting::infer::nice_region_error::static_impl_trait",
::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("compiler/rustc_trait_selection/src/error_reporting/infer/nice_region_error/static_impl_trait.rs"),
::tracing_core::__macro_support::Option::Some(146u32),
::tracing_core::__macro_support::Option::Some("rustc_trait_selection::error_reporting::infer::nice_region_error::static_impl_trait"),
::tracing_core::field::FieldSet::new(&["message"],
::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::EVENT)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let enabled =
::tracing::Level::DEBUG <= ::tracing::level_filters::STATIC_MAX_LEVEL
&&
::tracing::Level::DEBUG <=
::tracing::level_filters::LevelFilter::current() &&
{
let interest = __CALLSITE.interest();
!interest.is_never() &&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest)
};
if enabled {
(|value_set: ::tracing::field::ValueSet|
{
let meta = __CALLSITE.metadata();
::tracing::Event::dispatch(meta, &value_set);
;
})({
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
let mut iter = __CALLSITE.metadata().fields().iter();
__CALLSITE.metadata().fields().value_set(&[(&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
::tracing::__macro_support::Option::Some(&format_args!("try_report_static_impl_trait: fn_return={0:?}",
fn_returns) as &dyn Value))])
});
} else { ; }
};debug!("try_report_static_impl_trait: fn_return={:?}", fn_returns);
147 let consider = "consider changing";
149 let declare = "to declare that";
150 let explicit = ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("you can add an explicit `{0}` lifetime bound",
lifetime_name))
})format!("you can add an explicit `{lifetime_name}` lifetime bound");
151 let explicit_static =
152 arg.map(|arg| ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("explicit `\'static` bound to the lifetime of {0}",
arg))
})format!("explicit `'static` bound to the lifetime of {arg}"));
153 let add_static_bound = "alternatively, add an explicit `'static` bound to this reference";
154 let plus_lt = ::alloc::__export::must_use({
::alloc::fmt::format(format_args!(" + {0}", lifetime_name))
})format!(" + {lifetime_name}");
155 for fn_return in fn_returns {
156 if fn_return.span.desugaring_kind().is_some() {
157 continue;
159 }
160 match fn_return.kind {
161 TyKind::OpaqueDef(opaque) => {
163 let did = opaque.def_id.to_def_id();
165 let ty = Ty::new_opaque(
166 tcx,
167 ty::IsRigid::No,
168 did,
169 ty::GenericArgs::identity_for_item(tcx, did),
170 );
171
172 if let Some(span) = opaque.bounds.iter().find_map(|arg| match arg {
173 GenericBound::Outlives(Lifetime {
174 kind: LifetimeKind::Static, ident, ..
175 }) => Some(ident.span),
176 _ => None,
177 }) {
178 if let Some(explicit_static) = &explicit_static {
179 err.span_suggestion_verbose(
180 span,
181 ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("{0} `{1}`\'s {2}", consider, ty,
explicit_static))
})format!("{consider} `{ty}`'s {explicit_static}"),
182 &lifetime_name,
183 Applicability::MaybeIncorrect,
184 );
185 }
186 if let Some((param_span, ref param_ty)) = param {
187 err.span_suggestion_verbose(
188 param_span,
189 add_static_bound,
190 param_ty,
191 Applicability::MaybeIncorrect,
192 );
193 }
194 } else if opaque.bounds.iter().any(|arg| {
195 #[allow(non_exhaustive_omitted_patterns)] match arg {
GenericBound::Outlives(Lifetime { ident, .. }) if
ident.name.to_string() == lifetime_name => true,
_ => false,
}matches!(arg,
196 GenericBound::Outlives(Lifetime { ident, .. })
197 if ident.name.to_string() == lifetime_name )
198 }) {
199 } else {
200 let existing_lt_name = if let Some(id) = scope_def_id
202 && let Some(generics) = tcx.hir_get_generics(id)
203 && let named_lifetimes = generics
204 .params
205 .iter()
206 .filter(|p| {
207 #[allow(non_exhaustive_omitted_patterns)] match p.kind {
GenericParamKind::Lifetime { kind: hir::LifetimeParamKind::Explicit } =>
true,
_ => false,
}matches!(
208 p.kind,
209 GenericParamKind::Lifetime {
210 kind: hir::LifetimeParamKind::Explicit
211 }
212 )
213 })
214 .map(|p| {
215 if let hir::ParamName::Plain(name) = p.name {
216 Some(name.to_string())
217 } else {
218 None
219 }
220 })
221 .filter(|n| !#[allow(non_exhaustive_omitted_patterns)] match n {
None => true,
_ => false,
}matches!(n, None))
222 .collect::<Vec<_>>()
223 && named_lifetimes.len() > 0
224 {
225 named_lifetimes[0].clone()
226 } else {
227 None
228 };
229 let name = if let Some(name) = &existing_lt_name { name } else { "'a" };
230 if let Some(id) = scope_def_id
233 && let Some(generics) = tcx.hir_get_generics(id)
234 && let mut spans_suggs =
235 make_elided_region_spans_suggs(name, generics.params.iter())
236 && spans_suggs.len() > 1
237 {
238 let use_lt = if existing_lt_name == None {
239 spans_suggs.push((generics.span.shrink_to_hi(), ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("<{0}>", name))
})format!("<{name}>")));
240 ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("you can introduce a named lifetime parameter `{0}`",
name))
})format!("you can introduce a named lifetime parameter `{name}`")
241 } else {
242 ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("you can use the named lifetime parameter `{0}`",
name))
})format!("you can use the named lifetime parameter `{name}`")
244 };
245 spans_suggs.push((fn_return.span.shrink_to_hi(), ::alloc::__export::must_use({
::alloc::fmt::format(format_args!(" + {0} ", name))
})format!(" + {name} ")));
246 err.multipart_suggestion(
247 ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("{0} `{1}` {2}, {3}", declare, ty,
captures, use_lt))
})format!("{declare} `{ty}` {captures}, {use_lt}"),
248 spans_suggs,
249 Applicability::MaybeIncorrect,
250 );
251 } else {
252 err.span_suggestion_verbose(
253 fn_return.span.shrink_to_hi(),
254 ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("{0} `{1}` {2}, {3}", declare, ty,
captures, explicit))
})format!("{declare} `{ty}` {captures}, {explicit}"),
255 &plus_lt,
256 Applicability::MaybeIncorrect,
257 );
258 }
259 }
260 }
261 TyKind::TraitObject(_, lt) => {
262 if let LifetimeKind::ImplicitObjectLifetimeDefault = lt.kind {
263 err.span_suggestion_verbose(
264 fn_return.span.shrink_to_hi(),
265 ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("{0} the trait object {1}, {2}",
declare, captures, explicit))
})format!("{declare} the trait object {captures}, {explicit}"),
266 &plus_lt,
267 Applicability::MaybeIncorrect,
268 );
269 } else if lt.ident.name.to_string() != lifetime_name {
270 if let Some(explicit_static) = &explicit_static {
275 err.span_suggestion_verbose(
276 lt.ident.span,
277 ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("{0} the trait object\'s {1}",
consider, explicit_static))
})format!("{consider} the trait object's {explicit_static}"),
278 &lifetime_name,
279 Applicability::MaybeIncorrect,
280 );
281 }
282 if let Some((param_span, param_ty)) = param.clone() {
283 err.span_suggestion_verbose(
284 param_span,
285 add_static_bound,
286 param_ty,
287 Applicability::MaybeIncorrect,
288 );
289 }
290 }
291 }
292 _ => {}
293 }
294 }
295}
296
297fn make_elided_region_spans_suggs<'a>(
298 name: &str,
299 generic_params: impl Iterator<Item = &'a GenericParam<'a>>,
300) -> Vec<(Span, String)> {
301 let mut spans_suggs = Vec::new();
302 let mut bracket_span = None;
303 let mut consecutive_brackets = 0;
304
305 let mut process_consecutive_brackets =
306 |span: Option<Span>, spans_suggs: &mut Vec<(Span, String)>| {
307 if let Some(span) = span
308 && bracket_span.is_none_or(|bracket_span| span == bracket_span)
309 {
310 consecutive_brackets += 1;
311 } else if let Some(bracket_span) = bracket_span.take() {
312 let sugg = std::iter::once("<")
313 .chain(std::iter::repeat_n(name, consecutive_brackets).intersperse(", "))
314 .chain([">"])
315 .collect();
316 spans_suggs.push((bracket_span.shrink_to_hi(), sugg));
317 consecutive_brackets = 0;
318 }
319 bracket_span = span;
320 };
321
322 for p in generic_params {
323 if let GenericParamKind::Lifetime { kind: LifetimeParamKind::Elided(kind) } = p.kind {
324 match kind {
325 MissingLifetimeKind::Underscore => {
326 process_consecutive_brackets(None, &mut spans_suggs);
327 spans_suggs.push((p.span, name.to_string()))
328 }
329 MissingLifetimeKind::Ampersand => {
330 process_consecutive_brackets(None, &mut spans_suggs);
331 spans_suggs.push((p.span.shrink_to_hi(), ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("{0} ", name))
})format!("{name} ")));
332 }
333 MissingLifetimeKind::Comma => {
334 process_consecutive_brackets(None, &mut spans_suggs);
335 spans_suggs.push((p.span.shrink_to_hi(), ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("{0}, ", name))
})format!("{name}, ")));
336 }
337 MissingLifetimeKind::Brackets => {
338 process_consecutive_brackets(Some(p.span), &mut spans_suggs);
339 }
340 }
341 }
342 }
343 process_consecutive_brackets(None, &mut spans_suggs);
344
345 spans_suggs
346}
347
348impl<'a, 'tcx> NiceRegionError<'a, 'tcx> {
349 pub fn get_impl_ident_and_self_ty_from_trait(
350 tcx: TyCtxt<'tcx>,
351 def_id: DefId,
352 trait_objects: &FxIndexSet<DefId>,
353 ) -> Option<(Ident, &'tcx hir::Ty<'tcx>)> {
354 match tcx.hir_get_if_local(def_id)? {
355 Node::ImplItem(impl_item) => {
356 let impl_did = tcx.hir_get_parent_item(impl_item.hir_id());
357 if let hir::OwnerNode::Item(Item {
358 kind: ItemKind::Impl(hir::Impl { self_ty, .. }),
359 ..
360 }) = tcx.hir_owner_node(impl_did)
361 {
362 Some((impl_item.ident, self_ty))
363 } else {
364 None
365 }
366 }
367 Node::TraitItem(trait_item) => {
368 let trait_id = tcx.hir_get_parent_item(trait_item.hir_id());
369 if true {
{
match (&tcx.def_kind(trait_id.def_id), &hir::def::DefKind::Trait) {
(left_val, right_val) => {
if !(*left_val == *right_val) {
let kind = ::core::panicking::AssertKind::Eq;
::core::panicking::assert_failed(kind, &*left_val,
&*right_val, ::core::option::Option::None);
}
}
}
};
};debug_assert_eq!(tcx.def_kind(trait_id.def_id), hir::def::DefKind::Trait);
370 let trait_did = trait_id.to_def_id();
374 tcx.local_trait_impls(trait_did).iter().find_map(|&impl_did| {
375 if let Node::Item(Item {
376 kind: ItemKind::Impl(hir::Impl { self_ty, .. }), ..
377 }) = tcx.hir_node_by_def_id(impl_did)
378 && trait_objects.iter().all(|did| {
379 let mut traits = ::alloc::vec::Vec::new()vec![];
385 let mut hir_v = HirTraitObjectVisitor(&mut traits, *did);
386 hir_v.visit_ty_unambig(self_ty);
387 !traits.is_empty()
388 })
389 {
390 Some((trait_item.ident, *self_ty))
391 } else {
392 None
393 }
394 })
395 }
396 _ => None,
397 }
398 }
399}
400
401pub struct TraitObjectVisitor(pub FxIndexSet<DefId>);
403
404impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for TraitObjectVisitor {
405 fn visit_ty(&mut self, t: Ty<'tcx>) {
406 match t.kind() {
407 ty::Dynamic(preds, re) if re.is_static() => {
408 if let Some(def_id) = preds.principal_def_id() {
409 self.0.insert(def_id);
410 }
411 }
412 _ => t.super_visit_with(self),
413 }
414 }
415}
416
417pub struct HirTraitObjectVisitor<'a>(pub &'a mut Vec<Span>, pub DefId);
419
420impl<'a, 'tcx> Visitor<'tcx> for HirTraitObjectVisitor<'a> {
421 fn visit_ty(&mut self, t: &'tcx hir::Ty<'tcx, AmbigArg>) {
422 if let TyKind::TraitObject(poly_trait_refs, lifetime_ptr) = t.kind
423 && let Lifetime { kind: LifetimeKind::ImplicitObjectLifetimeDefault, .. } =
424 lifetime_ptr.pointer()
425 {
426 for ptr in poly_trait_refs {
427 if Some(self.1) == ptr.trait_ref.trait_def_id() {
428 self.0.push(ptr.span);
429 }
430 }
431 }
432 walk_ty(self, t);
433 }
434}