1use std::borrow::Cow;
4use std::iter;
5use std::path::PathBuf;
6
7use itertools::{EitherOrBoth, Itertools};
8use rustc_abi::ExternAbi;
9use rustc_data_structures::debug_assert_matches;
10use rustc_data_structures::fx::FxHashSet;
11use rustc_data_structures::stack::ensure_sufficient_stack;
12use rustc_errors::codes::*;
13use rustc_errors::{
14 Applicability, Diag, EmissionGuarantee, MultiSpan, Style, SuggestionStyle, pluralize,
15 struct_span_code_err,
16};
17use rustc_hir::def::{CtorOf, DefKind, Res};
18use rustc_hir::def_id::DefId;
19use rustc_hir::intravisit::{Visitor, VisitorExt};
20use rustc_hir::lang_items::LangItem;
21use rustc_hir::{
22 self as hir, AmbigArg, CoroutineDesugaring, CoroutineKind, CoroutineSource, Expr, HirId, Node,
23 expr_needs_parens,
24};
25use rustc_infer::infer::{BoundRegionConversionTime, DefineOpaqueTypes, InferCtxt, InferOk};
26use rustc_middle::middle::privacy::Level;
27use rustc_middle::traits::IsConstable;
28use rustc_middle::ty::error::TypeError;
29use rustc_middle::ty::print::{
30 PrintPolyTraitPredicateExt as _, PrintPolyTraitRefExt, PrintTraitPredicateExt as _,
31 with_forced_trimmed_paths, with_no_trimmed_paths, with_types_for_suggestion,
32};
33use rustc_middle::ty::{
34 self, AdtKind, GenericArgs, InferTy, IsSuggestable, Ty, TyCtxt, TypeFoldable, TypeFolder,
35 TypeSuperFoldable, TypeSuperVisitable, TypeVisitableExt, TypeVisitor, TypeckResults, Upcast,
36 suggest_arbitrary_trait_bound, suggest_constraining_type_param,
37};
38use rustc_middle::{bug, span_bug};
39use rustc_span::def_id::LocalDefId;
40use rustc_span::{
41 BytePos, DUMMY_SP, DesugaringKind, ExpnKind, Ident, MacroKind, Span, Symbol, kw, sym,
42};
43use tracing::{debug, instrument};
44
45use super::{
46 DefIdOrName, FindExprBySpan, ImplCandidate, Obligation, ObligationCause, ObligationCauseCode,
47 PredicateObligation,
48};
49use crate::error_reporting::TypeErrCtxt;
50use crate::errors;
51use crate::infer::InferCtxtExt as _;
52use crate::traits::query::evaluate_obligation::InferCtxtExt as _;
53use crate::traits::{ImplDerivedCause, NormalizeExt, ObligationCtxt};
54
55#[derive(#[automatically_derived]
impl ::core::fmt::Debug for CoroutineInteriorOrUpvar {
#[inline]
fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
match self {
CoroutineInteriorOrUpvar::Interior(__self_0, __self_1) =>
::core::fmt::Formatter::debug_tuple_field2_finish(f,
"Interior", __self_0, &__self_1),
CoroutineInteriorOrUpvar::Upvar(__self_0) =>
::core::fmt::Formatter::debug_tuple_field1_finish(f, "Upvar",
&__self_0),
}
}
}Debug)]
56pub enum CoroutineInteriorOrUpvar {
57 Interior(Span, Option<(Span, Option<Span>)>),
59 Upvar(Span),
61}
62
63#[derive(#[automatically_derived]
impl<'a, 'tcx> ::core::fmt::Debug for CoroutineData<'a, 'tcx> {
#[inline]
fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
::core::fmt::Formatter::debug_tuple_field1_finish(f, "CoroutineData",
&&self.0)
}
}Debug)]
66struct CoroutineData<'a, 'tcx>(&'a TypeckResults<'tcx>);
67
68impl<'a, 'tcx> CoroutineData<'a, 'tcx> {
69 fn try_get_upvar_span<F>(
73 &self,
74 infer_context: &InferCtxt<'tcx>,
75 coroutine_did: DefId,
76 ty_matches: F,
77 ) -> Option<CoroutineInteriorOrUpvar>
78 where
79 F: Fn(ty::Binder<'tcx, Ty<'tcx>>) -> bool,
80 {
81 infer_context.tcx.upvars_mentioned(coroutine_did).and_then(|upvars| {
82 upvars.iter().find_map(|(upvar_id, upvar)| {
83 let upvar_ty = self.0.node_type(*upvar_id);
84 let upvar_ty = infer_context.resolve_vars_if_possible(upvar_ty);
85 ty_matches(ty::Binder::dummy(upvar_ty))
86 .then(|| CoroutineInteriorOrUpvar::Upvar(upvar.span))
87 })
88 })
89 }
90
91 fn get_from_await_ty<F>(
95 &self,
96 visitor: AwaitsVisitor,
97 tcx: TyCtxt<'tcx>,
98 ty_matches: F,
99 ) -> Option<Span>
100 where
101 F: Fn(ty::Binder<'tcx, Ty<'tcx>>) -> bool,
102 {
103 visitor
104 .awaits
105 .into_iter()
106 .map(|id| tcx.hir_expect_expr(id))
107 .find(|await_expr| ty_matches(ty::Binder::dummy(self.0.expr_ty_adjusted(await_expr))))
108 .map(|expr| expr.span)
109 }
110}
111
112fn predicate_constraint(generics: &hir::Generics<'_>, pred: ty::Predicate<'_>) -> (Span, String) {
113 (
114 generics.tail_span_for_predicate_suggestion(),
115 {
let _guard =
::rustc_middle::ty::print::pretty::RtnModeHelper::with(RtnMode::ForSuggestion);
::alloc::__export::must_use({
::alloc::fmt::format(format_args!("{0} {1}",
generics.add_where_or_trailing_comma(), pred))
})
}with_types_for_suggestion!(format!("{} {}", generics.add_where_or_trailing_comma(), pred)),
116 )
117}
118
119pub fn suggest_restriction<'tcx, G: EmissionGuarantee>(
123 tcx: TyCtxt<'tcx>,
124 item_id: LocalDefId,
125 hir_generics: &hir::Generics<'tcx>,
126 msg: &str,
127 err: &mut Diag<'_, G>,
128 fn_sig: Option<&hir::FnSig<'_>>,
129 projection: Option<ty::AliasTy<'_>>,
130 trait_pred: ty::PolyTraitPredicate<'tcx>,
131 super_traits: Option<(&Ident, &hir::GenericBounds<'_>)>,
137) {
138 if hir_generics.where_clause_span.from_expansion()
139 || hir_generics.where_clause_span.desugaring_kind().is_some()
140 || projection.is_some_and(|projection| {
141 (tcx.is_impl_trait_in_trait(projection.def_id)
142 && !tcx.features().return_type_notation())
143 || tcx.lookup_stability(projection.def_id).is_some_and(|stab| stab.is_unstable())
144 })
145 {
146 return;
147 }
148 let generics = tcx.generics_of(item_id);
149 if let Some((param, bound_str, fn_sig)) =
151 fn_sig.zip(projection).and_then(|(sig, p)| match *p.self_ty().kind() {
152 ty::Param(param) => {
154 let param_def = generics.type_param(param, tcx);
155 if param_def.kind.is_synthetic() {
156 let bound_str =
157 param_def.name.as_str().strip_prefix("impl ")?.trim_start().to_string();
158 return Some((param_def, bound_str, sig));
159 }
160 None
161 }
162 _ => None,
163 })
164 {
165 let type_param_name = hir_generics.params.next_type_param_name(Some(&bound_str));
166 let trait_pred = trait_pred.fold_with(&mut ReplaceImplTraitFolder {
167 tcx,
168 param,
169 replace_ty: ty::ParamTy::new(generics.count() as u32, Symbol::intern(&type_param_name))
170 .to_ty(tcx),
171 });
172 if !trait_pred.is_suggestable(tcx, false) {
173 return;
174 }
175 let mut ty_spans = ::alloc::vec::Vec::new()vec![];
183 for input in fn_sig.decl.inputs {
184 ReplaceImplTraitVisitor { ty_spans: &mut ty_spans, param_did: param.def_id }
185 .visit_ty_unambig(input);
186 }
187 let type_param = ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("{0}: {1}", type_param_name,
bound_str))
})format!("{type_param_name}: {bound_str}");
189
190 let mut sugg = <[_]>::into_vec(::alloc::boxed::box_new([if let Some(span) =
hir_generics.span_for_param_suggestion() {
(span,
::alloc::__export::must_use({
::alloc::fmt::format(format_args!(", {0}", type_param))
}))
} else {
(hir_generics.span,
::alloc::__export::must_use({
::alloc::fmt::format(format_args!("<{0}>", type_param))
}))
},
predicate_constraint(hir_generics, trait_pred.upcast(tcx))]))vec![
191 if let Some(span) = hir_generics.span_for_param_suggestion() {
192 (span, format!(", {type_param}"))
193 } else {
194 (hir_generics.span, format!("<{type_param}>"))
195 },
196 predicate_constraint(hir_generics, trait_pred.upcast(tcx)),
199 ];
200 sugg.extend(ty_spans.into_iter().map(|s| (s, type_param_name.to_string())));
201
202 err.multipart_suggestion(
205 "introduce a type parameter with a trait bound instead of using `impl Trait`",
206 sugg,
207 Applicability::MaybeIncorrect,
208 );
209 } else {
210 if !trait_pred.is_suggestable(tcx, false) {
211 return;
212 }
213 let (sp, suggestion) = match (
215 hir_generics
216 .params
217 .iter()
218 .find(|p| !#[allow(non_exhaustive_omitted_patterns)] match p.kind {
hir::GenericParamKind::Type { synthetic: true, .. } => true,
_ => false,
}matches!(p.kind, hir::GenericParamKind::Type { synthetic: true, .. })),
219 super_traits,
220 ) {
221 (_, None) => predicate_constraint(hir_generics, trait_pred.upcast(tcx)),
222 (None, Some((ident, []))) => (
223 ident.span.shrink_to_hi(),
224 ::alloc::__export::must_use({
::alloc::fmt::format(format_args!(": {0}",
trait_pred.print_modifiers_and_trait_path()))
})format!(": {}", trait_pred.print_modifiers_and_trait_path()),
225 ),
226 (_, Some((_, [.., bounds]))) => (
227 bounds.span().shrink_to_hi(),
228 ::alloc::__export::must_use({
::alloc::fmt::format(format_args!(" + {0}",
trait_pred.print_modifiers_and_trait_path()))
})format!(" + {}", trait_pred.print_modifiers_and_trait_path()),
229 ),
230 (Some(_), Some((_, []))) => (
231 hir_generics.span.shrink_to_hi(),
232 ::alloc::__export::must_use({
::alloc::fmt::format(format_args!(": {0}",
trait_pred.print_modifiers_and_trait_path()))
})format!(": {}", trait_pred.print_modifiers_and_trait_path()),
233 ),
234 };
235
236 err.span_suggestion_verbose(
237 sp,
238 ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("consider further restricting {0}",
msg))
})format!("consider further restricting {msg}"),
239 suggestion,
240 Applicability::MachineApplicable,
241 );
242 }
243}
244
245impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
246 pub fn suggest_restricting_param_bound(
247 &self,
248 err: &mut Diag<'_>,
249 trait_pred: ty::PolyTraitPredicate<'tcx>,
250 associated_ty: Option<(&'static str, Ty<'tcx>)>,
251 mut body_id: LocalDefId,
252 ) {
253 if trait_pred.skip_binder().polarity != ty::PredicatePolarity::Positive {
254 return;
255 }
256
257 let trait_pred = self.resolve_numeric_literals_with_default(trait_pred);
258
259 let self_ty = trait_pred.skip_binder().self_ty();
260 let (param_ty, projection) = match *self_ty.kind() {
261 ty::Param(_) => (true, None),
262 ty::Alias(ty::Projection, projection) => (false, Some(projection)),
263 _ => (false, None),
264 };
265
266 let mut finder = ParamFinder { .. };
267 finder.visit_binder(&trait_pred);
268
269 loop {
272 let node = self.tcx.hir_node_by_def_id(body_id);
273 match node {
274 hir::Node::Item(hir::Item {
275 kind: hir::ItemKind::Trait(_, _, _, ident, generics, bounds, _),
276 ..
277 }) if self_ty == self.tcx.types.self_param => {
278 if !param_ty { ::core::panicking::panic("assertion failed: param_ty") };assert!(param_ty);
279 suggest_restriction(
281 self.tcx,
282 body_id,
283 generics,
284 "`Self`",
285 err,
286 None,
287 projection,
288 trait_pred,
289 Some((&ident, bounds)),
290 );
291 return;
292 }
293
294 hir::Node::TraitItem(hir::TraitItem {
295 generics,
296 kind: hir::TraitItemKind::Fn(..),
297 ..
298 }) if self_ty == self.tcx.types.self_param => {
299 if !param_ty { ::core::panicking::panic("assertion failed: param_ty") };assert!(param_ty);
300 suggest_restriction(
302 self.tcx, body_id, generics, "`Self`", err, None, projection, trait_pred,
303 None,
304 );
305 return;
306 }
307
308 hir::Node::TraitItem(hir::TraitItem {
309 generics,
310 kind: hir::TraitItemKind::Fn(fn_sig, ..),
311 ..
312 })
313 | hir::Node::ImplItem(hir::ImplItem {
314 generics,
315 kind: hir::ImplItemKind::Fn(fn_sig, ..),
316 ..
317 })
318 | hir::Node::Item(hir::Item {
319 kind: hir::ItemKind::Fn { sig: fn_sig, generics, .. },
320 ..
321 }) if projection.is_some() => {
322 suggest_restriction(
324 self.tcx,
325 body_id,
326 generics,
327 "the associated type",
328 err,
329 Some(fn_sig),
330 projection,
331 trait_pred,
332 None,
333 );
334 return;
335 }
336 hir::Node::Item(hir::Item {
337 kind:
338 hir::ItemKind::Trait(_, _, _, _, generics, ..)
339 | hir::ItemKind::Impl(hir::Impl { generics, .. }),
340 ..
341 }) if projection.is_some() => {
342 suggest_restriction(
344 self.tcx,
345 body_id,
346 generics,
347 "the associated type",
348 err,
349 None,
350 projection,
351 trait_pred,
352 None,
353 );
354 return;
355 }
356
357 hir::Node::Item(hir::Item {
358 kind:
359 hir::ItemKind::Struct(_, generics, _)
360 | hir::ItemKind::Enum(_, generics, _)
361 | hir::ItemKind::Union(_, generics, _)
362 | hir::ItemKind::Trait(_, _, _, _, generics, ..)
363 | hir::ItemKind::Impl(hir::Impl { generics, .. })
364 | hir::ItemKind::Fn { generics, .. }
365 | hir::ItemKind::TyAlias(_, generics, _)
366 | hir::ItemKind::Const(_, generics, _, _)
367 | hir::ItemKind::TraitAlias(_, _, generics, _),
368 ..
369 })
370 | hir::Node::TraitItem(hir::TraitItem { generics, .. })
371 | hir::Node::ImplItem(hir::ImplItem { generics, .. })
372 if param_ty =>
373 {
374 if !trait_pred.skip_binder().trait_ref.args[1..]
383 .iter()
384 .all(|g| g.is_suggestable(self.tcx, false))
385 {
386 return;
387 }
388 let param_name = self_ty.to_string();
390 let mut constraint = {
let _guard = NoTrimmedGuard::new();
trait_pred.print_modifiers_and_trait_path().to_string()
}with_no_trimmed_paths!(
391 trait_pred.print_modifiers_and_trait_path().to_string()
392 );
393
394 if let Some((name, term)) = associated_ty {
395 if let Some(stripped) = constraint.strip_suffix('>') {
398 constraint = ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("{0}, {1} = {2}>", stripped, name,
term))
})format!("{stripped}, {name} = {term}>");
399 } else {
400 constraint.push_str(&::alloc::__export::must_use({
::alloc::fmt::format(format_args!("<{0} = {1}>", name, term))
})format!("<{name} = {term}>"));
401 }
402 }
403
404 if suggest_constraining_type_param(
405 self.tcx,
406 generics,
407 err,
408 ¶m_name,
409 &constraint,
410 Some(trait_pred.def_id()),
411 None,
412 ) {
413 return;
414 }
415 }
416
417 hir::Node::TraitItem(hir::TraitItem {
418 generics,
419 kind: hir::TraitItemKind::Fn(..),
420 ..
421 })
422 | hir::Node::ImplItem(hir::ImplItem {
423 generics,
424 impl_kind: hir::ImplItemImplKind::Inherent { .. },
425 kind: hir::ImplItemKind::Fn(..),
426 ..
427 }) if finder.can_suggest_bound(generics) => {
428 suggest_arbitrary_trait_bound(
430 self.tcx,
431 generics,
432 err,
433 trait_pred,
434 associated_ty,
435 );
436 }
437 hir::Node::Item(hir::Item {
438 kind:
439 hir::ItemKind::Struct(_, generics, _)
440 | hir::ItemKind::Enum(_, generics, _)
441 | hir::ItemKind::Union(_, generics, _)
442 | hir::ItemKind::Trait(_, _, _, _, generics, ..)
443 | hir::ItemKind::Impl(hir::Impl { generics, .. })
444 | hir::ItemKind::Fn { generics, .. }
445 | hir::ItemKind::TyAlias(_, generics, _)
446 | hir::ItemKind::Const(_, generics, _, _)
447 | hir::ItemKind::TraitAlias(_, _, generics, _),
448 ..
449 }) if finder.can_suggest_bound(generics) => {
450 if suggest_arbitrary_trait_bound(
452 self.tcx,
453 generics,
454 err,
455 trait_pred,
456 associated_ty,
457 ) {
458 return;
459 }
460 }
461 hir::Node::Crate(..) => return,
462
463 _ => {}
464 }
465 body_id = self.tcx.local_parent(body_id);
466 }
467 }
468
469 pub(super) fn suggest_dereferences(
472 &self,
473 obligation: &PredicateObligation<'tcx>,
474 err: &mut Diag<'_>,
475 trait_pred: ty::PolyTraitPredicate<'tcx>,
476 ) -> bool {
477 let mut code = obligation.cause.code();
478 if let ObligationCauseCode::FunctionArg { arg_hir_id, call_hir_id, .. } = code
479 && let Some(typeck_results) = &self.typeck_results
480 && let hir::Node::Expr(expr) = self.tcx.hir_node(*arg_hir_id)
481 && let Some(arg_ty) = typeck_results.expr_ty_adjusted_opt(expr)
482 {
483 let mut real_trait_pred = trait_pred;
487 while let Some((parent_code, parent_trait_pred)) = code.parent_with_predicate() {
488 code = parent_code;
489 if let Some(parent_trait_pred) = parent_trait_pred {
490 real_trait_pred = parent_trait_pred;
491 }
492 }
493
494 let real_ty = self.tcx.instantiate_bound_regions_with_erased(real_trait_pred.self_ty());
497 if !self.can_eq(obligation.param_env, real_ty, arg_ty) {
498 return false;
499 }
500
501 let (is_under_ref, base_ty, span) = match expr.kind {
508 hir::ExprKind::AddrOf(hir::BorrowKind::Ref, hir::Mutability::Not, subexpr)
509 if let &ty::Ref(region, base_ty, hir::Mutability::Not) = real_ty.kind() =>
510 {
511 (Some(region), base_ty, subexpr.span)
512 }
513 hir::ExprKind::AddrOf(..) => return false,
515 _ => (None, real_ty, obligation.cause.span),
516 };
517
518 let autoderef = (self.autoderef_steps)(base_ty);
519 let mut is_boxed = base_ty.is_box();
520 if let Some(steps) = autoderef.into_iter().position(|(mut ty, obligations)| {
521 let can_deref = is_under_ref.is_some()
524 || self.type_is_copy_modulo_regions(obligation.param_env, ty)
525 || ty.is_numeric() || is_boxed && self.type_is_sized_modulo_regions(obligation.param_env, ty);
527 is_boxed &= ty.is_box();
528
529 if let Some(region) = is_under_ref {
531 ty = Ty::new_ref(self.tcx, region, ty, hir::Mutability::Not);
532 }
533
534 let real_trait_pred_and_ty =
536 real_trait_pred.map_bound(|inner_trait_pred| (inner_trait_pred, ty));
537 let obligation = self.mk_trait_obligation_with_new_self_ty(
538 obligation.param_env,
539 real_trait_pred_and_ty,
540 );
541
542 can_deref
543 && obligations
544 .iter()
545 .chain([&obligation])
546 .all(|obligation| self.predicate_may_hold(obligation))
547 }) && steps > 0
548 {
549 let derefs = "*".repeat(steps);
550 let msg = "consider dereferencing here";
551 let call_node = self.tcx.hir_node(*call_hir_id);
552 let is_receiver = #[allow(non_exhaustive_omitted_patterns)] match call_node {
Node::Expr(hir::Expr {
kind: hir::ExprKind::MethodCall(_, receiver_expr, ..), .. }) if
receiver_expr.hir_id == *arg_hir_id => true,
_ => false,
}matches!(
553 call_node,
554 Node::Expr(hir::Expr {
555 kind: hir::ExprKind::MethodCall(_, receiver_expr, ..),
556 ..
557 })
558 if receiver_expr.hir_id == *arg_hir_id
559 );
560 if is_receiver {
561 err.multipart_suggestion_verbose(
562 msg,
563 <[_]>::into_vec(::alloc::boxed::box_new([(span.shrink_to_lo(),
::alloc::__export::must_use({
::alloc::fmt::format(format_args!("({0}", derefs))
})), (span.shrink_to_hi(), ")".to_string())]))vec![
564 (span.shrink_to_lo(), format!("({derefs}")),
565 (span.shrink_to_hi(), ")".to_string()),
566 ],
567 Applicability::MachineApplicable,
568 )
569 } else {
570 err.span_suggestion_verbose(
571 span.shrink_to_lo(),
572 msg,
573 derefs,
574 Applicability::MachineApplicable,
575 )
576 };
577 return true;
578 }
579 } else if let (
580 ObligationCauseCode::BinOp { lhs_hir_id, rhs_hir_id, .. },
581 predicate,
582 ) = code.peel_derives_with_predicate()
583 && let Some(typeck_results) = &self.typeck_results
584 && let hir::Node::Expr(lhs) = self.tcx.hir_node(*lhs_hir_id)
585 && let hir::Node::Expr(rhs) = self.tcx.hir_node(*rhs_hir_id)
586 && let Some(rhs_ty) = typeck_results.expr_ty_opt(rhs)
587 && let trait_pred = predicate.unwrap_or(trait_pred)
588 && hir::lang_items::BINARY_OPERATORS
590 .iter()
591 .filter_map(|&op| self.tcx.lang_items().get(op))
592 .any(|op| {
593 op == trait_pred.skip_binder().trait_ref.def_id
594 })
595 {
596 let trait_pred = predicate.unwrap_or(trait_pred);
599 let lhs_ty = self.tcx.instantiate_bound_regions_with_erased(trait_pred.self_ty());
600 let lhs_autoderef = (self.autoderef_steps)(lhs_ty);
601 let rhs_autoderef = (self.autoderef_steps)(rhs_ty);
602 let first_lhs = lhs_autoderef.first().unwrap().clone();
603 let first_rhs = rhs_autoderef.first().unwrap().clone();
604 let mut autoderefs = lhs_autoderef
605 .into_iter()
606 .enumerate()
607 .rev()
608 .zip_longest(rhs_autoderef.into_iter().enumerate().rev())
609 .map(|t| match t {
610 EitherOrBoth::Both(a, b) => (a, b),
611 EitherOrBoth::Left(a) => (a, (0, first_rhs.clone())),
612 EitherOrBoth::Right(b) => ((0, first_lhs.clone()), b),
613 })
614 .rev();
615 if let Some((lsteps, rsteps)) =
616 autoderefs.find_map(|((lsteps, (l_ty, _)), (rsteps, (r_ty, _)))| {
617 let trait_pred_and_ty = trait_pred.map_bound(|inner| {
621 (
622 ty::TraitPredicate {
623 trait_ref: ty::TraitRef::new_from_args(
624 self.tcx,
625 inner.trait_ref.def_id,
626 self.tcx.mk_args(
627 &[&[l_ty.into(), r_ty.into()], &inner.trait_ref.args[2..]]
628 .concat(),
629 ),
630 ),
631 ..inner
632 },
633 l_ty,
634 )
635 });
636 let obligation = self.mk_trait_obligation_with_new_self_ty(
637 obligation.param_env,
638 trait_pred_and_ty,
639 );
640 self.predicate_may_hold(&obligation).then_some(match (lsteps, rsteps) {
641 (_, 0) => (Some(lsteps), None),
642 (0, _) => (None, Some(rsteps)),
643 _ => (Some(lsteps), Some(rsteps)),
644 })
645 })
646 {
647 let make_sugg = |mut expr: &Expr<'_>, mut steps| {
648 let mut prefix_span = expr.span.shrink_to_lo();
649 let mut msg = "consider dereferencing here";
650 if let hir::ExprKind::AddrOf(_, _, inner) = expr.kind {
651 msg = "consider removing the borrow and dereferencing instead";
652 if let hir::ExprKind::AddrOf(..) = inner.kind {
653 msg = "consider removing the borrows and dereferencing instead";
654 }
655 }
656 while let hir::ExprKind::AddrOf(_, _, inner) = expr.kind
657 && steps > 0
658 {
659 prefix_span = prefix_span.with_hi(inner.span.lo());
660 expr = inner;
661 steps -= 1;
662 }
663 if steps == 0 {
665 return (
666 msg.trim_end_matches(" and dereferencing instead"),
667 <[_]>::into_vec(::alloc::boxed::box_new([(prefix_span, String::new())]))vec![(prefix_span, String::new())],
668 );
669 }
670 let derefs = "*".repeat(steps);
671 let needs_parens = steps > 0 && expr_needs_parens(expr);
672 let mut suggestion = if needs_parens {
673 <[_]>::into_vec(::alloc::boxed::box_new([(expr.span.with_lo(prefix_span.hi()).shrink_to_lo(),
::alloc::__export::must_use({
::alloc::fmt::format(format_args!("{0}(", derefs))
})), (expr.span.shrink_to_hi(), ")".to_string())]))vec![
674 (
675 expr.span.with_lo(prefix_span.hi()).shrink_to_lo(),
676 format!("{derefs}("),
677 ),
678 (expr.span.shrink_to_hi(), ")".to_string()),
679 ]
680 } else {
681 <[_]>::into_vec(::alloc::boxed::box_new([(expr.span.with_lo(prefix_span.hi()).shrink_to_lo(),
::alloc::__export::must_use({
::alloc::fmt::format(format_args!("{0}", derefs))
}))]))vec![(
682 expr.span.with_lo(prefix_span.hi()).shrink_to_lo(),
683 format!("{derefs}"),
684 )]
685 };
686 if !prefix_span.is_empty() {
688 suggestion.push((prefix_span, String::new()));
689 }
690 (msg, suggestion)
691 };
692
693 if let Some(lsteps) = lsteps
694 && let Some(rsteps) = rsteps
695 && lsteps > 0
696 && rsteps > 0
697 {
698 let mut suggestion = make_sugg(lhs, lsteps).1;
699 suggestion.append(&mut make_sugg(rhs, rsteps).1);
700 err.multipart_suggestion_verbose(
701 "consider dereferencing both sides of the expression",
702 suggestion,
703 Applicability::MachineApplicable,
704 );
705 return true;
706 } else if let Some(lsteps) = lsteps
707 && lsteps > 0
708 {
709 let (msg, suggestion) = make_sugg(lhs, lsteps);
710 err.multipart_suggestion_verbose(
711 msg,
712 suggestion,
713 Applicability::MachineApplicable,
714 );
715 return true;
716 } else if let Some(rsteps) = rsteps
717 && rsteps > 0
718 {
719 let (msg, suggestion) = make_sugg(rhs, rsteps);
720 err.multipart_suggestion_verbose(
721 msg,
722 suggestion,
723 Applicability::MachineApplicable,
724 );
725 return true;
726 }
727 }
728 }
729 false
730 }
731
732 fn get_closure_name(
736 &self,
737 def_id: DefId,
738 err: &mut Diag<'_>,
739 msg: Cow<'static, str>,
740 ) -> Option<Symbol> {
741 let get_name = |err: &mut Diag<'_>, kind: &hir::PatKind<'_>| -> Option<Symbol> {
742 match &kind {
745 hir::PatKind::Binding(hir::BindingMode::NONE, _, ident, None) => Some(ident.name),
746 _ => {
747 err.note(msg);
748 None
749 }
750 }
751 };
752
753 let hir_id = self.tcx.local_def_id_to_hir_id(def_id.as_local()?);
754 match self.tcx.parent_hir_node(hir_id) {
755 hir::Node::Stmt(hir::Stmt { kind: hir::StmtKind::Let(local), .. }) => {
756 get_name(err, &local.pat.kind)
757 }
758 hir::Node::LetStmt(local) => get_name(err, &local.pat.kind),
761 _ => None,
762 }
763 }
764
765 pub(super) fn suggest_fn_call(
769 &self,
770 obligation: &PredicateObligation<'tcx>,
771 err: &mut Diag<'_>,
772 trait_pred: ty::PolyTraitPredicate<'tcx>,
773 ) -> bool {
774 if self.typeck_results.is_none() {
777 return false;
778 }
779
780 if let ty::PredicateKind::Clause(ty::ClauseKind::Trait(trait_pred)) =
781 obligation.predicate.kind().skip_binder()
782 && self.tcx.is_lang_item(trait_pred.def_id(), LangItem::Sized)
783 {
784 return false;
786 }
787
788 let self_ty = self.instantiate_binder_with_fresh_vars(
789 DUMMY_SP,
790 BoundRegionConversionTime::FnCall,
791 trait_pred.self_ty(),
792 );
793
794 let Some((def_id_or_name, output, inputs)) =
795 self.extract_callable_info(obligation.cause.body_id, obligation.param_env, self_ty)
796 else {
797 return false;
798 };
799
800 let trait_pred_and_self = trait_pred.map_bound(|trait_pred| (trait_pred, output));
802
803 let new_obligation =
804 self.mk_trait_obligation_with_new_self_ty(obligation.param_env, trait_pred_and_self);
805 if !self.predicate_must_hold_modulo_regions(&new_obligation) {
806 return false;
807 }
808
809 let msg = match def_id_or_name {
811 DefIdOrName::DefId(def_id) => match self.tcx.def_kind(def_id) {
812 DefKind::Ctor(CtorOf::Struct, _) => {
813 Cow::from("use parentheses to construct this tuple struct")
814 }
815 DefKind::Ctor(CtorOf::Variant, _) => {
816 Cow::from("use parentheses to construct this tuple variant")
817 }
818 kind => Cow::from(::alloc::__export::must_use({
::alloc::fmt::format(format_args!("use parentheses to call this {0}",
self.tcx.def_kind_descr(kind, def_id)))
})format!(
819 "use parentheses to call this {}",
820 self.tcx.def_kind_descr(kind, def_id)
821 )),
822 },
823 DefIdOrName::Name(name) => Cow::from(::alloc::__export::must_use({
::alloc::fmt::format(format_args!("use parentheses to call this {0}",
name))
})format!("use parentheses to call this {name}")),
824 };
825
826 let args = inputs
827 .into_iter()
828 .map(|ty| {
829 if ty.is_suggestable(self.tcx, false) {
830 ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("/* {0} */", ty))
})format!("/* {ty} */")
831 } else {
832 "/* value */".to_string()
833 }
834 })
835 .collect::<Vec<_>>()
836 .join(", ");
837
838 if #[allow(non_exhaustive_omitted_patterns)] match obligation.cause.code() {
ObligationCauseCode::FunctionArg { .. } => true,
_ => false,
}matches!(obligation.cause.code(), ObligationCauseCode::FunctionArg { .. })
839 && obligation.cause.span.can_be_used_for_suggestions()
840 {
841 let (span, sugg) = if let Some(snippet) =
842 self.tcx.sess.source_map().span_to_snippet(obligation.cause.span).ok()
843 && snippet.starts_with("|")
844 {
845 (obligation.cause.span, ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("({0})({1})", snippet, args))
})format!("({snippet})({args})"))
846 } else {
847 (obligation.cause.span.shrink_to_hi(), ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("({0})", args))
})format!("({args})"))
848 };
849
850 err.span_suggestion_verbose(span, msg, sugg, Applicability::HasPlaceholders);
855 } else if let DefIdOrName::DefId(def_id) = def_id_or_name {
856 let name = match self.tcx.hir_get_if_local(def_id) {
857 Some(hir::Node::Expr(hir::Expr {
858 kind: hir::ExprKind::Closure(hir::Closure { fn_decl_span, .. }),
859 ..
860 })) => {
861 err.span_label(*fn_decl_span, "consider calling this closure");
862 let Some(name) = self.get_closure_name(def_id, err, msg.clone()) else {
863 return false;
864 };
865 name.to_string()
866 }
867 Some(hir::Node::Item(hir::Item {
868 kind: hir::ItemKind::Fn { ident, .. }, ..
869 })) => {
870 err.span_label(ident.span, "consider calling this function");
871 ident.to_string()
872 }
873 Some(hir::Node::Ctor(..)) => {
874 let name = self.tcx.def_path_str(def_id);
875 err.span_label(
876 self.tcx.def_span(def_id),
877 ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("consider calling the constructor for `{0}`",
name))
})format!("consider calling the constructor for `{name}`"),
878 );
879 name
880 }
881 _ => return false,
882 };
883 err.help(::alloc::__export::must_use({
::alloc::fmt::format(format_args!("{0}: `{1}({2})`", msg, name, args))
})format!("{msg}: `{name}({args})`"));
884 }
885 true
886 }
887
888 pub(super) fn check_for_binding_assigned_block_without_tail_expression(
889 &self,
890 obligation: &PredicateObligation<'tcx>,
891 err: &mut Diag<'_>,
892 trait_pred: ty::PolyTraitPredicate<'tcx>,
893 ) {
894 let mut span = obligation.cause.span;
895 while span.from_expansion() {
896 span.remove_mark();
898 }
899 let mut expr_finder = FindExprBySpan::new(span, self.tcx);
900 let Some(body) = self.tcx.hir_maybe_body_owned_by(obligation.cause.body_id) else {
901 return;
902 };
903 expr_finder.visit_expr(body.value);
904 let Some(expr) = expr_finder.result else {
905 return;
906 };
907 let Some(typeck) = &self.typeck_results else {
908 return;
909 };
910 let Some(ty) = typeck.expr_ty_adjusted_opt(expr) else {
911 return;
912 };
913 if !ty.is_unit() {
914 return;
915 };
916 let hir::ExprKind::Path(hir::QPath::Resolved(None, path)) = expr.kind else {
917 return;
918 };
919 let Res::Local(hir_id) = path.res else {
920 return;
921 };
922 let hir::Node::Pat(pat) = self.tcx.hir_node(hir_id) else {
923 return;
924 };
925 let hir::Node::LetStmt(hir::LetStmt { ty: None, init: Some(init), .. }) =
926 self.tcx.parent_hir_node(pat.hir_id)
927 else {
928 return;
929 };
930 let hir::ExprKind::Block(block, None) = init.kind else {
931 return;
932 };
933 if block.expr.is_some() {
934 return;
935 }
936 let [.., stmt] = block.stmts else {
937 err.span_label(block.span, "this empty block is missing a tail expression");
938 return;
939 };
940 if stmt.span.from_expansion() {
943 return;
944 }
945 let hir::StmtKind::Semi(tail_expr) = stmt.kind else {
946 return;
947 };
948 let Some(ty) = typeck.expr_ty_opt(tail_expr) else {
949 err.span_label(block.span, "this block is missing a tail expression");
950 return;
951 };
952 let ty = self.resolve_numeric_literals_with_default(self.resolve_vars_if_possible(ty));
953 let trait_pred_and_self = trait_pred.map_bound(|trait_pred| (trait_pred, ty));
954
955 let new_obligation =
956 self.mk_trait_obligation_with_new_self_ty(obligation.param_env, trait_pred_and_self);
957 if self.predicate_must_hold_modulo_regions(&new_obligation) {
958 err.span_suggestion_short(
959 stmt.span.with_lo(tail_expr.span.hi()),
960 "remove this semicolon",
961 "",
962 Applicability::MachineApplicable,
963 );
964 } else {
965 err.span_label(block.span, "this block is missing a tail expression");
966 }
967 }
968
969 pub(super) fn suggest_add_clone_to_arg(
970 &self,
971 obligation: &PredicateObligation<'tcx>,
972 err: &mut Diag<'_>,
973 trait_pred: ty::PolyTraitPredicate<'tcx>,
974 ) -> bool {
975 let self_ty = self.resolve_vars_if_possible(trait_pred.self_ty());
976 self.enter_forall(self_ty, |ty: Ty<'_>| {
977 let Some(generics) = self.tcx.hir_get_generics(obligation.cause.body_id) else {
978 return false;
979 };
980 let ty::Ref(_, inner_ty, hir::Mutability::Not) = ty.kind() else { return false };
981 let ty::Param(param) = inner_ty.kind() else { return false };
982 let ObligationCauseCode::FunctionArg { arg_hir_id, .. } = obligation.cause.code()
983 else {
984 return false;
985 };
986
987 let clone_trait = self.tcx.require_lang_item(LangItem::Clone, obligation.cause.span);
988 let has_clone = |ty| {
989 self.type_implements_trait(clone_trait, [ty], obligation.param_env)
990 .must_apply_modulo_regions()
991 };
992
993 let existing_clone_call = match self.tcx.hir_node(*arg_hir_id) {
994 Node::Expr(Expr { kind: hir::ExprKind::Path(_), .. }) => None,
996 Node::Expr(Expr {
999 kind:
1000 hir::ExprKind::MethodCall(
1001 hir::PathSegment { ident, .. },
1002 _receiver,
1003 [],
1004 call_span,
1005 ),
1006 hir_id,
1007 ..
1008 }) if ident.name == sym::clone
1009 && !call_span.from_expansion()
1010 && !has_clone(*inner_ty) =>
1011 {
1012 let Some(typeck_results) = self.typeck_results.as_ref() else { return false };
1014 let Some((DefKind::AssocFn, did)) = typeck_results.type_dependent_def(*hir_id)
1015 else {
1016 return false;
1017 };
1018 if self.tcx.trait_of_assoc(did) != Some(clone_trait) {
1019 return false;
1020 }
1021 Some(ident.span)
1022 }
1023 _ => return false,
1024 };
1025
1026 let new_obligation = self.mk_trait_obligation_with_new_self_ty(
1027 obligation.param_env,
1028 trait_pred.map_bound(|trait_pred| (trait_pred, *inner_ty)),
1029 );
1030
1031 if self.predicate_may_hold(&new_obligation) && has_clone(ty) {
1032 if !has_clone(param.to_ty(self.tcx)) {
1033 suggest_constraining_type_param(
1034 self.tcx,
1035 generics,
1036 err,
1037 param.name.as_str(),
1038 "Clone",
1039 Some(clone_trait),
1040 None,
1041 );
1042 }
1043 if let Some(existing_clone_call) = existing_clone_call {
1044 err.span_note(
1045 existing_clone_call,
1046 ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("this `clone()` copies the reference, which does not do anything, because `{0}` does not implement `Clone`",
inner_ty))
})format!(
1047 "this `clone()` copies the reference, \
1048 which does not do anything, \
1049 because `{inner_ty}` does not implement `Clone`"
1050 ),
1051 );
1052 } else {
1053 err.span_suggestion_verbose(
1054 obligation.cause.span.shrink_to_hi(),
1055 "consider using clone here",
1056 ".clone()".to_string(),
1057 Applicability::MaybeIncorrect,
1058 );
1059 }
1060 return true;
1061 }
1062 false
1063 })
1064 }
1065
1066 pub fn extract_callable_info(
1070 &self,
1071 body_id: LocalDefId,
1072 param_env: ty::ParamEnv<'tcx>,
1073 found: Ty<'tcx>,
1074 ) -> Option<(DefIdOrName, Ty<'tcx>, Vec<Ty<'tcx>>)> {
1075 let Some((def_id_or_name, output, inputs)) =
1077 (self.autoderef_steps)(found).into_iter().find_map(|(found, _)| match *found.kind() {
1078 ty::FnPtr(sig_tys, _) => Some((
1079 DefIdOrName::Name("function pointer"),
1080 sig_tys.output(),
1081 sig_tys.inputs(),
1082 )),
1083 ty::FnDef(def_id, _) => {
1084 let fn_sig = found.fn_sig(self.tcx);
1085 Some((DefIdOrName::DefId(def_id), fn_sig.output(), fn_sig.inputs()))
1086 }
1087 ty::Closure(def_id, args) => {
1088 let fn_sig = args.as_closure().sig();
1089 Some((
1090 DefIdOrName::DefId(def_id),
1091 fn_sig.output(),
1092 fn_sig.inputs().map_bound(|inputs| inputs[0].tuple_fields().as_slice()),
1093 ))
1094 }
1095 ty::CoroutineClosure(def_id, args) => {
1096 let sig_parts = args.as_coroutine_closure().coroutine_closure_sig();
1097 Some((
1098 DefIdOrName::DefId(def_id),
1099 sig_parts.map_bound(|sig| {
1100 sig.to_coroutine(
1101 self.tcx,
1102 args.as_coroutine_closure().parent_args(),
1103 self.next_ty_var(DUMMY_SP),
1106 self.tcx.coroutine_for_closure(def_id),
1107 self.next_ty_var(DUMMY_SP),
1108 )
1109 }),
1110 sig_parts.map_bound(|sig| sig.tupled_inputs_ty.tuple_fields().as_slice()),
1111 ))
1112 }
1113 ty::Alias(ty::Opaque, ty::AliasTy { def_id, args, .. }) => {
1114 self.tcx.item_self_bounds(def_id).instantiate(self.tcx, args).iter().find_map(
1115 |pred| {
1116 if let ty::ClauseKind::Projection(proj) = pred.kind().skip_binder()
1117 && self
1118 .tcx
1119 .is_lang_item(proj.projection_term.def_id, LangItem::FnOnceOutput)
1120 && let ty::Tuple(args) = proj.projection_term.args.type_at(1).kind()
1122 {
1123 Some((
1124 DefIdOrName::DefId(def_id),
1125 pred.kind().rebind(proj.term.expect_type()),
1126 pred.kind().rebind(args.as_slice()),
1127 ))
1128 } else {
1129 None
1130 }
1131 },
1132 )
1133 }
1134 ty::Dynamic(data, _) => data.iter().find_map(|pred| {
1135 if let ty::ExistentialPredicate::Projection(proj) = pred.skip_binder()
1136 && self.tcx.is_lang_item(proj.def_id, LangItem::FnOnceOutput)
1137 && let ty::Tuple(args) = proj.args.type_at(0).kind()
1139 {
1140 Some((
1141 DefIdOrName::Name("trait object"),
1142 pred.rebind(proj.term.expect_type()),
1143 pred.rebind(args.as_slice()),
1144 ))
1145 } else {
1146 None
1147 }
1148 }),
1149 ty::Param(param) => {
1150 let generics = self.tcx.generics_of(body_id);
1151 let name = if generics.count() > param.index as usize
1152 && let def = generics.param_at(param.index as usize, self.tcx)
1153 && #[allow(non_exhaustive_omitted_patterns)] match def.kind {
ty::GenericParamDefKind::Type { .. } => true,
_ => false,
}matches!(def.kind, ty::GenericParamDefKind::Type { .. })
1154 && def.name == param.name
1155 {
1156 DefIdOrName::DefId(def.def_id)
1157 } else {
1158 DefIdOrName::Name("type parameter")
1159 };
1160 param_env.caller_bounds().iter().find_map(|pred| {
1161 if let ty::ClauseKind::Projection(proj) = pred.kind().skip_binder()
1162 && self
1163 .tcx
1164 .is_lang_item(proj.projection_term.def_id, LangItem::FnOnceOutput)
1165 && proj.projection_term.self_ty() == found
1166 && let ty::Tuple(args) = proj.projection_term.args.type_at(1).kind()
1168 {
1169 Some((
1170 name,
1171 pred.kind().rebind(proj.term.expect_type()),
1172 pred.kind().rebind(args.as_slice()),
1173 ))
1174 } else {
1175 None
1176 }
1177 })
1178 }
1179 _ => None,
1180 })
1181 else {
1182 return None;
1183 };
1184
1185 let output = self.instantiate_binder_with_fresh_vars(
1186 DUMMY_SP,
1187 BoundRegionConversionTime::FnCall,
1188 output,
1189 );
1190 let inputs = inputs
1191 .skip_binder()
1192 .iter()
1193 .map(|ty| {
1194 self.instantiate_binder_with_fresh_vars(
1195 DUMMY_SP,
1196 BoundRegionConversionTime::FnCall,
1197 inputs.rebind(*ty),
1198 )
1199 })
1200 .collect();
1201
1202 let InferOk { value: output, obligations: _ } =
1206 self.at(&ObligationCause::dummy(), param_env).normalize(output);
1207
1208 if output.is_ty_var() { None } else { Some((def_id_or_name, output, inputs)) }
1209 }
1210
1211 pub(super) fn suggest_add_reference_to_arg(
1212 &self,
1213 obligation: &PredicateObligation<'tcx>,
1214 err: &mut Diag<'_>,
1215 poly_trait_pred: ty::PolyTraitPredicate<'tcx>,
1216 has_custom_message: bool,
1217 ) -> bool {
1218 let span = obligation.cause.span;
1219 let param_env = obligation.param_env;
1220
1221 let mk_result = |trait_pred_and_new_ty| {
1222 let obligation =
1223 self.mk_trait_obligation_with_new_self_ty(param_env, trait_pred_and_new_ty);
1224 self.predicate_must_hold_modulo_regions(&obligation)
1225 };
1226
1227 let code = match obligation.cause.code() {
1228 ObligationCauseCode::FunctionArg { parent_code, .. } => parent_code,
1229 c @ ObligationCauseCode::WhereClauseInExpr(_, _, hir_id, _)
1232 if self.tcx.hir_span(*hir_id).lo() == span.lo() =>
1233 {
1234 if let hir::Node::Expr(expr) = self.tcx.parent_hir_node(*hir_id)
1238 && let hir::ExprKind::Call(base, _) = expr.kind
1239 && let hir::ExprKind::Path(hir::QPath::TypeRelative(ty, segment)) = base.kind
1240 && let hir::Node::Expr(outer) = self.tcx.parent_hir_node(expr.hir_id)
1241 && let hir::ExprKind::AddrOf(hir::BorrowKind::Ref, mtbl, _) = outer.kind
1242 && ty.span == span
1243 {
1244 let trait_pred_and_imm_ref = poly_trait_pred.map_bound(|p| {
1250 (p, Ty::new_imm_ref(self.tcx, self.tcx.lifetimes.re_static, p.self_ty()))
1251 });
1252 let trait_pred_and_mut_ref = poly_trait_pred.map_bound(|p| {
1253 (p, Ty::new_mut_ref(self.tcx, self.tcx.lifetimes.re_static, p.self_ty()))
1254 });
1255
1256 let imm_ref_self_ty_satisfies_pred = mk_result(trait_pred_and_imm_ref);
1257 let mut_ref_self_ty_satisfies_pred = mk_result(trait_pred_and_mut_ref);
1258 let sugg_msg = |pre: &str| {
1259 ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("you likely meant to call the associated function `{0}` for type `&{2}{1}`, but the code as written calls associated function `{0}` on type `{1}`",
segment.ident, poly_trait_pred.self_ty(), pre))
})format!(
1260 "you likely meant to call the associated function `{FN}` for type \
1261 `&{pre}{TY}`, but the code as written calls associated function `{FN}` on \
1262 type `{TY}`",
1263 FN = segment.ident,
1264 TY = poly_trait_pred.self_ty(),
1265 )
1266 };
1267 match (imm_ref_self_ty_satisfies_pred, mut_ref_self_ty_satisfies_pred, mtbl) {
1268 (true, _, hir::Mutability::Not) | (_, true, hir::Mutability::Mut) => {
1269 err.multipart_suggestion_verbose(
1270 sugg_msg(mtbl.prefix_str()),
1271 <[_]>::into_vec(::alloc::boxed::box_new([(outer.span.shrink_to_lo(),
"<".to_string()), (span.shrink_to_hi(), ">".to_string())]))vec![
1272 (outer.span.shrink_to_lo(), "<".to_string()),
1273 (span.shrink_to_hi(), ">".to_string()),
1274 ],
1275 Applicability::MachineApplicable,
1276 );
1277 }
1278 (true, _, hir::Mutability::Mut) => {
1279 err.multipart_suggestion_verbose(
1281 sugg_msg("mut "),
1282 <[_]>::into_vec(::alloc::boxed::box_new([(outer.span.shrink_to_lo().until(span),
"<&".to_string()), (span.shrink_to_hi(), ">".to_string())]))vec![
1283 (outer.span.shrink_to_lo().until(span), "<&".to_string()),
1284 (span.shrink_to_hi(), ">".to_string()),
1285 ],
1286 Applicability::MachineApplicable,
1287 );
1288 }
1289 (_, true, hir::Mutability::Not) => {
1290 err.multipart_suggestion_verbose(
1291 sugg_msg(""),
1292 <[_]>::into_vec(::alloc::boxed::box_new([(outer.span.shrink_to_lo().until(span),
"<&mut ".to_string()),
(span.shrink_to_hi(), ">".to_string())]))vec![
1293 (outer.span.shrink_to_lo().until(span), "<&mut ".to_string()),
1294 (span.shrink_to_hi(), ">".to_string()),
1295 ],
1296 Applicability::MachineApplicable,
1297 );
1298 }
1299 _ => {}
1300 }
1301 return false;
1303 }
1304 c
1305 }
1306 c if #[allow(non_exhaustive_omitted_patterns)] match span.ctxt().outer_expn_data().kind
{
ExpnKind::Desugaring(DesugaringKind::ForLoop) => true,
_ => false,
}matches!(
1307 span.ctxt().outer_expn_data().kind,
1308 ExpnKind::Desugaring(DesugaringKind::ForLoop)
1309 ) =>
1310 {
1311 c
1312 }
1313 _ => return false,
1314 };
1315
1316 let mut never_suggest_borrow: Vec<_> =
1320 [LangItem::Copy, LangItem::Clone, LangItem::Unpin, LangItem::Sized]
1321 .iter()
1322 .filter_map(|lang_item| self.tcx.lang_items().get(*lang_item))
1323 .collect();
1324
1325 if let Some(def_id) = self.tcx.get_diagnostic_item(sym::Send) {
1326 never_suggest_borrow.push(def_id);
1327 }
1328
1329 let mut try_borrowing = |old_pred: ty::PolyTraitPredicate<'tcx>,
1331 blacklist: &[DefId]|
1332 -> bool {
1333 if blacklist.contains(&old_pred.def_id()) {
1334 return false;
1335 }
1336 let trait_pred_and_imm_ref = old_pred.map_bound(|trait_pred| {
1338 (
1339 trait_pred,
1340 Ty::new_imm_ref(self.tcx, self.tcx.lifetimes.re_static, trait_pred.self_ty()),
1341 )
1342 });
1343 let trait_pred_and_mut_ref = old_pred.map_bound(|trait_pred| {
1344 (
1345 trait_pred,
1346 Ty::new_mut_ref(self.tcx, self.tcx.lifetimes.re_static, trait_pred.self_ty()),
1347 )
1348 });
1349
1350 let imm_ref_self_ty_satisfies_pred = mk_result(trait_pred_and_imm_ref);
1351 let mut_ref_self_ty_satisfies_pred = mk_result(trait_pred_and_mut_ref);
1352
1353 let (ref_inner_ty_satisfies_pred, ref_inner_ty_is_mut) =
1354 if let ObligationCauseCode::WhereClauseInExpr(..) = obligation.cause.code()
1355 && let ty::Ref(_, ty, mutability) = old_pred.self_ty().skip_binder().kind()
1356 {
1357 (
1358 mk_result(old_pred.map_bound(|trait_pred| (trait_pred, *ty))),
1359 mutability.is_mut(),
1360 )
1361 } else {
1362 (false, false)
1363 };
1364
1365 let is_immut = imm_ref_self_ty_satisfies_pred
1366 || (ref_inner_ty_satisfies_pred && !ref_inner_ty_is_mut);
1367 let is_mut = mut_ref_self_ty_satisfies_pred || ref_inner_ty_is_mut;
1368 if !is_immut && !is_mut {
1369 return false;
1370 }
1371 let Ok(_snippet) = self.tcx.sess.source_map().span_to_snippet(span) else {
1372 return false;
1373 };
1374 if !#[allow(non_exhaustive_omitted_patterns)] match span.ctxt().outer_expn_data().kind
{
ExpnKind::Root | ExpnKind::Desugaring(DesugaringKind::ForLoop) => true,
_ => false,
}matches!(
1382 span.ctxt().outer_expn_data().kind,
1383 ExpnKind::Root | ExpnKind::Desugaring(DesugaringKind::ForLoop)
1384 ) {
1385 return false;
1386 }
1387 let mut label = || {
1394 let is_sized = match obligation.predicate.kind().skip_binder() {
1397 ty::PredicateKind::Clause(ty::ClauseKind::Trait(trait_pred)) => {
1398 self.tcx.is_lang_item(trait_pred.def_id(), LangItem::Sized)
1399 }
1400 _ => false,
1401 };
1402
1403 let msg = ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("the trait bound `{0}` is not satisfied",
self.tcx.short_string(old_pred, err.long_ty_path())))
})format!(
1404 "the trait bound `{}` is not satisfied",
1405 self.tcx.short_string(old_pred, err.long_ty_path()),
1406 );
1407 let self_ty_str = self.tcx.short_string(old_pred.self_ty(), err.long_ty_path());
1408 let trait_path = self
1409 .tcx
1410 .short_string(old_pred.print_modifiers_and_trait_path(), err.long_ty_path());
1411
1412 if has_custom_message {
1413 let msg = if is_sized {
1414 "the trait bound `Sized` is not satisfied".into()
1415 } else {
1416 msg
1417 };
1418 err.note(msg);
1419 } else {
1420 err.messages = <[_]>::into_vec(::alloc::boxed::box_new([(rustc_errors::DiagMessage::from(msg),
Style::NoStyle)]))vec![(rustc_errors::DiagMessage::from(msg), Style::NoStyle)];
1421 }
1422 if is_sized {
1423 err.span_label(
1424 span,
1425 ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("the trait `Sized` is not implemented for `{0}`",
self_ty_str))
})format!("the trait `Sized` is not implemented for `{self_ty_str}`"),
1426 );
1427 } else {
1428 err.span_label(
1429 span,
1430 ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("the trait `{0}` is not implemented for `{1}`",
trait_path, self_ty_str))
})format!("the trait `{trait_path}` is not implemented for `{self_ty_str}`"),
1431 );
1432 }
1433 };
1434
1435 let mut sugg_prefixes = ::alloc::vec::Vec::new()vec![];
1436 if is_immut {
1437 sugg_prefixes.push("&");
1438 }
1439 if is_mut {
1440 sugg_prefixes.push("&mut ");
1441 }
1442 let sugg_msg = ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("consider{0} borrowing here",
if is_mut && !is_immut { " mutably" } else { "" }))
})format!(
1443 "consider{} borrowing here",
1444 if is_mut && !is_immut { " mutably" } else { "" },
1445 );
1446
1447 let Some(body) = self.tcx.hir_maybe_body_owned_by(obligation.cause.body_id) else {
1451 return false;
1452 };
1453 let mut expr_finder = FindExprBySpan::new(span, self.tcx);
1454 expr_finder.visit_expr(body.value);
1455
1456 if let Some(ty) = expr_finder.ty_result {
1457 if let hir::Node::Expr(expr) = self.tcx.parent_hir_node(ty.hir_id)
1458 && let hir::ExprKind::Path(hir::QPath::TypeRelative(_, _)) = expr.kind
1459 && ty.span == span
1460 {
1461 label();
1464 err.multipart_suggestions(
1465 sugg_msg,
1466 sugg_prefixes.into_iter().map(|sugg_prefix| {
1467 <[_]>::into_vec(::alloc::boxed::box_new([(span.shrink_to_lo(),
::alloc::__export::must_use({
::alloc::fmt::format(format_args!("<{0}", sugg_prefix))
})), (span.shrink_to_hi(), ">".to_string())]))vec![
1468 (span.shrink_to_lo(), format!("<{sugg_prefix}")),
1469 (span.shrink_to_hi(), ">".to_string()),
1470 ]
1471 }),
1472 Applicability::MaybeIncorrect,
1473 );
1474 return true;
1475 }
1476 return false;
1477 }
1478 let Some(expr) = expr_finder.result else {
1479 return false;
1480 };
1481 if let hir::ExprKind::AddrOf(_, _, _) = expr.kind {
1482 return false;
1483 }
1484 let needs_parens_post = expr_needs_parens(expr);
1485 let needs_parens_pre = match self.tcx.parent_hir_node(expr.hir_id) {
1486 Node::Expr(e)
1487 if let hir::ExprKind::MethodCall(_, base, _, _) = e.kind
1488 && base.hir_id == expr.hir_id =>
1489 {
1490 true
1491 }
1492 _ => false,
1493 };
1494
1495 label();
1496 let suggestions = sugg_prefixes.into_iter().map(|sugg_prefix| {
1497 match (needs_parens_pre, needs_parens_post) {
1498 (false, false) => <[_]>::into_vec(::alloc::boxed::box_new([(span.shrink_to_lo(),
sugg_prefix.to_string())]))vec![(span.shrink_to_lo(), sugg_prefix.to_string())],
1499 (false, true) => <[_]>::into_vec(::alloc::boxed::box_new([(span.shrink_to_lo(),
::alloc::__export::must_use({
::alloc::fmt::format(format_args!("{0}(", sugg_prefix))
})), (span.shrink_to_hi(), ")".to_string())]))vec![
1502 (span.shrink_to_lo(), format!("{sugg_prefix}(")),
1503 (span.shrink_to_hi(), ")".to_string()),
1504 ],
1505 (true, false) => <[_]>::into_vec(::alloc::boxed::box_new([(span.shrink_to_lo(),
::alloc::__export::must_use({
::alloc::fmt::format(format_args!("({0}", sugg_prefix))
})), (span.shrink_to_hi(), ")".to_string())]))vec![
1508 (span.shrink_to_lo(), format!("({sugg_prefix}")),
1509 (span.shrink_to_hi(), ")".to_string()),
1510 ],
1511 (true, true) => <[_]>::into_vec(::alloc::boxed::box_new([(span.shrink_to_lo(),
::alloc::__export::must_use({
::alloc::fmt::format(format_args!("({0}(", sugg_prefix))
})), (span.shrink_to_hi(), "))".to_string())]))vec![
1512 (span.shrink_to_lo(), format!("({sugg_prefix}(")),
1513 (span.shrink_to_hi(), "))".to_string()),
1514 ],
1515 }
1516 });
1517 err.multipart_suggestions(sugg_msg, suggestions, Applicability::MaybeIncorrect);
1518 return true;
1519 };
1520
1521 if let ObligationCauseCode::ImplDerived(cause) = &*code {
1522 try_borrowing(cause.derived.parent_trait_pred, &[])
1523 } else if let ObligationCauseCode::WhereClause(..)
1524 | ObligationCauseCode::WhereClauseInExpr(..) = code
1525 {
1526 try_borrowing(poly_trait_pred, &never_suggest_borrow)
1527 } else {
1528 false
1529 }
1530 }
1531
1532 pub(super) fn suggest_borrowing_for_object_cast(
1534 &self,
1535 err: &mut Diag<'_>,
1536 obligation: &PredicateObligation<'tcx>,
1537 self_ty: Ty<'tcx>,
1538 target_ty: Ty<'tcx>,
1539 ) {
1540 let ty::Ref(_, object_ty, hir::Mutability::Not) = target_ty.kind() else {
1541 return;
1542 };
1543 let ty::Dynamic(predicates, _) = object_ty.kind() else {
1544 return;
1545 };
1546 let self_ref_ty = Ty::new_imm_ref(self.tcx, self.tcx.lifetimes.re_erased, self_ty);
1547
1548 for predicate in predicates.iter() {
1549 if !self.predicate_must_hold_modulo_regions(
1550 &obligation.with(self.tcx, predicate.with_self_ty(self.tcx, self_ref_ty)),
1551 ) {
1552 return;
1553 }
1554 }
1555
1556 err.span_suggestion_verbose(
1557 obligation.cause.span.shrink_to_lo(),
1558 ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("consider borrowing the value, since `&{0}` can be coerced into `{1}`",
self_ty, target_ty))
})format!(
1559 "consider borrowing the value, since `&{self_ty}` can be coerced into `{target_ty}`"
1560 ),
1561 "&",
1562 Applicability::MaybeIncorrect,
1563 );
1564 }
1565
1566 pub(super) fn suggest_remove_reference(
1569 &self,
1570 obligation: &PredicateObligation<'tcx>,
1571 err: &mut Diag<'_>,
1572 trait_pred: ty::PolyTraitPredicate<'tcx>,
1573 ) -> bool {
1574 let mut span = obligation.cause.span;
1575 let mut trait_pred = trait_pred;
1576 let mut code = obligation.cause.code();
1577 while let Some((c, Some(parent_trait_pred))) = code.parent_with_predicate() {
1578 code = c;
1581 trait_pred = parent_trait_pred;
1582 }
1583 while span.desugaring_kind().is_some() {
1584 span.remove_mark();
1586 }
1587 let mut expr_finder = super::FindExprBySpan::new(span, self.tcx);
1588 let Some(body) = self.tcx.hir_maybe_body_owned_by(obligation.cause.body_id) else {
1589 return false;
1590 };
1591 expr_finder.visit_expr(body.value);
1592 let mut maybe_suggest = |suggested_ty, count, suggestions| {
1593 let trait_pred_and_suggested_ty =
1595 trait_pred.map_bound(|trait_pred| (trait_pred, suggested_ty));
1596
1597 let new_obligation = self.mk_trait_obligation_with_new_self_ty(
1598 obligation.param_env,
1599 trait_pred_and_suggested_ty,
1600 );
1601
1602 if self.predicate_may_hold(&new_obligation) {
1603 let msg = if count == 1 {
1604 "consider removing the leading `&`-reference".to_string()
1605 } else {
1606 ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("consider removing {0} leading `&`-references",
count))
})format!("consider removing {count} leading `&`-references")
1607 };
1608
1609 err.multipart_suggestion_verbose(
1610 msg,
1611 suggestions,
1612 Applicability::MachineApplicable,
1613 );
1614 true
1615 } else {
1616 false
1617 }
1618 };
1619
1620 let mut count = 0;
1623 let mut suggestions = ::alloc::vec::Vec::new()vec![];
1624 let mut suggested_ty = trait_pred.self_ty().skip_binder();
1626 if let Some(mut hir_ty) = expr_finder.ty_result {
1627 while let hir::TyKind::Ref(_, mut_ty) = &hir_ty.kind {
1628 count += 1;
1629 let span = hir_ty.span.until(mut_ty.ty.span);
1630 suggestions.push((span, String::new()));
1631
1632 let ty::Ref(_, inner_ty, _) = suggested_ty.kind() else {
1633 break;
1634 };
1635 suggested_ty = *inner_ty;
1636
1637 hir_ty = mut_ty.ty;
1638
1639 if maybe_suggest(suggested_ty, count, suggestions.clone()) {
1640 return true;
1641 }
1642 }
1643 }
1644
1645 let Some(mut expr) = expr_finder.result else {
1647 return false;
1648 };
1649 let mut count = 0;
1650 let mut suggestions = ::alloc::vec::Vec::new()vec![];
1651 let mut suggested_ty = trait_pred.self_ty().skip_binder();
1653 'outer: loop {
1654 while let hir::ExprKind::AddrOf(_, _, borrowed) = expr.kind {
1655 count += 1;
1656 let span =
1657 if let Some(borrowed_span) = borrowed.span.find_ancestor_inside(expr.span) {
1658 expr.span.until(borrowed_span)
1659 } else {
1660 break 'outer;
1661 };
1662
1663 match self.tcx.sess.source_map().span_to_snippet(span) {
1666 Ok(snippet) if snippet.starts_with("&") => {}
1667 _ => break 'outer,
1668 }
1669
1670 suggestions.push((span, String::new()));
1671
1672 let ty::Ref(_, inner_ty, _) = suggested_ty.kind() else {
1673 break 'outer;
1674 };
1675 suggested_ty = *inner_ty;
1676
1677 expr = borrowed;
1678
1679 if maybe_suggest(suggested_ty, count, suggestions.clone()) {
1680 return true;
1681 }
1682 }
1683 if let hir::ExprKind::Path(hir::QPath::Resolved(None, path)) = expr.kind
1684 && let Res::Local(hir_id) = path.res
1685 && let hir::Node::Pat(binding) = self.tcx.hir_node(hir_id)
1686 && let hir::Node::LetStmt(local) = self.tcx.parent_hir_node(binding.hir_id)
1687 && let None = local.ty
1688 && let Some(binding_expr) = local.init
1689 {
1690 expr = binding_expr;
1691 } else {
1692 break 'outer;
1693 }
1694 }
1695 false
1696 }
1697
1698 pub(super) fn suggest_remove_await(
1699 &self,
1700 obligation: &PredicateObligation<'tcx>,
1701 err: &mut Diag<'_>,
1702 ) {
1703 if let ObligationCauseCode::AwaitableExpr(hir_id) = obligation.cause.code().peel_derives()
1704 && let hir::Node::Expr(expr) = self.tcx.hir_node(*hir_id)
1705 {
1706 if let Some((_, hir::Node::Expr(await_expr))) = self.tcx.hir_parent_iter(*hir_id).nth(1)
1713 && let Some(expr_span) = expr.span.find_ancestor_inside_same_ctxt(await_expr.span)
1714 {
1715 let removal_span = self
1716 .tcx
1717 .sess
1718 .source_map()
1719 .span_extend_while_whitespace(expr_span)
1720 .shrink_to_hi()
1721 .to(await_expr.span.shrink_to_hi());
1722 err.span_suggestion_verbose(
1723 removal_span,
1724 "remove the `.await`",
1725 "",
1726 Applicability::MachineApplicable,
1727 );
1728 } else {
1729 err.span_label(obligation.cause.span, "remove the `.await`");
1730 }
1731 if let hir::Expr { span, kind: hir::ExprKind::Call(base, _), .. } = expr {
1733 if let ty::PredicateKind::Clause(ty::ClauseKind::Trait(pred)) =
1734 obligation.predicate.kind().skip_binder()
1735 {
1736 err.span_label(*span, ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("this call returns `{0}`",
pred.self_ty()))
})format!("this call returns `{}`", pred.self_ty()));
1737 }
1738 if let Some(typeck_results) = &self.typeck_results
1739 && let ty = typeck_results.expr_ty_adjusted(base)
1740 && let ty::FnDef(def_id, _args) = ty.kind()
1741 && let Some(hir::Node::Item(item)) = self.tcx.hir_get_if_local(*def_id)
1742 {
1743 let (ident, _, _, _) = item.expect_fn();
1744 let msg = ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("alternatively, consider making `fn {0}` asynchronous",
ident))
})format!("alternatively, consider making `fn {ident}` asynchronous");
1745 if item.vis_span.is_empty() {
1746 err.span_suggestion_verbose(
1747 item.span.shrink_to_lo(),
1748 msg,
1749 "async ",
1750 Applicability::MaybeIncorrect,
1751 );
1752 } else {
1753 err.span_suggestion_verbose(
1754 item.vis_span.shrink_to_hi(),
1755 msg,
1756 " async",
1757 Applicability::MaybeIncorrect,
1758 );
1759 }
1760 }
1761 }
1762 }
1763 }
1764
1765 pub(super) fn suggest_change_mut(
1768 &self,
1769 obligation: &PredicateObligation<'tcx>,
1770 err: &mut Diag<'_>,
1771 trait_pred: ty::PolyTraitPredicate<'tcx>,
1772 ) {
1773 let points_at_arg =
1774 #[allow(non_exhaustive_omitted_patterns)] match obligation.cause.code() {
ObligationCauseCode::FunctionArg { .. } => true,
_ => false,
}matches!(obligation.cause.code(), ObligationCauseCode::FunctionArg { .. },);
1775
1776 let span = obligation.cause.span;
1777 if let Ok(snippet) = self.tcx.sess.source_map().span_to_snippet(span) {
1778 let refs_number =
1779 snippet.chars().filter(|c| !c.is_whitespace()).take_while(|c| *c == '&').count();
1780 if let Some('\'') = snippet.chars().filter(|c| !c.is_whitespace()).nth(refs_number) {
1781 return;
1783 }
1784 let trait_pred = self.resolve_vars_if_possible(trait_pred);
1785 if trait_pred.has_non_region_infer() {
1786 return;
1789 }
1790
1791 if let ty::Ref(region, t_type, mutability) = *trait_pred.skip_binder().self_ty().kind()
1793 {
1794 let suggested_ty = match mutability {
1795 hir::Mutability::Mut => Ty::new_imm_ref(self.tcx, region, t_type),
1796 hir::Mutability::Not => Ty::new_mut_ref(self.tcx, region, t_type),
1797 };
1798
1799 let trait_pred_and_suggested_ty =
1801 trait_pred.map_bound(|trait_pred| (trait_pred, suggested_ty));
1802
1803 let new_obligation = self.mk_trait_obligation_with_new_self_ty(
1804 obligation.param_env,
1805 trait_pred_and_suggested_ty,
1806 );
1807 let suggested_ty_would_satisfy_obligation = self
1808 .evaluate_obligation_no_overflow(&new_obligation)
1809 .must_apply_modulo_regions();
1810 if suggested_ty_would_satisfy_obligation {
1811 let sp = self
1812 .tcx
1813 .sess
1814 .source_map()
1815 .span_take_while(span, |c| c.is_whitespace() || *c == '&');
1816 if points_at_arg && mutability.is_not() && refs_number > 0 {
1817 if snippet
1819 .trim_start_matches(|c: char| c.is_whitespace() || c == '&')
1820 .starts_with("mut")
1821 {
1822 return;
1823 }
1824 err.span_suggestion_verbose(
1825 sp,
1826 "consider changing this borrow's mutability",
1827 "&mut ",
1828 Applicability::MachineApplicable,
1829 );
1830 } else {
1831 err.note(::alloc::__export::must_use({
::alloc::fmt::format(format_args!("`{0}` is implemented for `{1}`, but not for `{2}`",
trait_pred.print_modifiers_and_trait_path(), suggested_ty,
trait_pred.skip_binder().self_ty()))
})format!(
1832 "`{}` is implemented for `{}`, but not for `{}`",
1833 trait_pred.print_modifiers_and_trait_path(),
1834 suggested_ty,
1835 trait_pred.skip_binder().self_ty(),
1836 ));
1837 }
1838 }
1839 }
1840 }
1841 }
1842
1843 pub(super) fn suggest_semicolon_removal(
1844 &self,
1845 obligation: &PredicateObligation<'tcx>,
1846 err: &mut Diag<'_>,
1847 span: Span,
1848 trait_pred: ty::PolyTraitPredicate<'tcx>,
1849 ) -> bool {
1850 let node = self.tcx.hir_node_by_def_id(obligation.cause.body_id);
1851 if let hir::Node::Item(hir::Item { kind: hir::ItemKind::Fn {sig, body: body_id, .. }, .. }) = node
1852 && let hir::ExprKind::Block(blk, _) = &self.tcx.hir_body(*body_id).value.kind
1853 && sig.decl.output.span().overlaps(span)
1854 && blk.expr.is_none()
1855 && trait_pred.self_ty().skip_binder().is_unit()
1856 && let Some(stmt) = blk.stmts.last()
1857 && let hir::StmtKind::Semi(expr) = stmt.kind
1858 && let Some(typeck_results) = &self.typeck_results
1860 && let Some(ty) = typeck_results.expr_ty_opt(expr)
1861 && self.predicate_may_hold(&self.mk_trait_obligation_with_new_self_ty(
1862 obligation.param_env, trait_pred.map_bound(|trait_pred| (trait_pred, ty))
1863 ))
1864 {
1865 err.span_label(
1866 expr.span,
1867 ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("this expression has type `{0}`, which implements `{1}`",
ty, trait_pred.print_modifiers_and_trait_path()))
})format!(
1868 "this expression has type `{}`, which implements `{}`",
1869 ty,
1870 trait_pred.print_modifiers_and_trait_path()
1871 ),
1872 );
1873 err.span_suggestion(
1874 self.tcx.sess.source_map().end_point(stmt.span),
1875 "remove this semicolon",
1876 "",
1877 Applicability::MachineApplicable,
1878 );
1879 return true;
1880 }
1881 false
1882 }
1883
1884 pub(super) fn return_type_span(&self, obligation: &PredicateObligation<'tcx>) -> Option<Span> {
1885 let hir::Node::Item(hir::Item { kind: hir::ItemKind::Fn { sig, .. }, .. }) =
1886 self.tcx.hir_node_by_def_id(obligation.cause.body_id)
1887 else {
1888 return None;
1889 };
1890
1891 if let hir::FnRetTy::Return(ret_ty) = sig.decl.output { Some(ret_ty.span) } else { None }
1892 }
1893
1894 pub(super) fn suggest_impl_trait(
1898 &self,
1899 err: &mut Diag<'_>,
1900 obligation: &PredicateObligation<'tcx>,
1901 trait_pred: ty::PolyTraitPredicate<'tcx>,
1902 ) -> bool {
1903 let ObligationCauseCode::SizedReturnType = obligation.cause.code() else {
1904 return false;
1905 };
1906 let ty::Dynamic(_, _) = trait_pred.self_ty().skip_binder().kind() else {
1907 return false;
1908 };
1909 if let Node::Item(hir::Item { kind: hir::ItemKind::Fn { sig: fn_sig, .. }, .. })
1910 | Node::ImplItem(hir::ImplItem { kind: hir::ImplItemKind::Fn(fn_sig, _), .. })
1911 | Node::TraitItem(hir::TraitItem { kind: hir::TraitItemKind::Fn(fn_sig, _), .. }) =
1912 self.tcx.hir_node_by_def_id(obligation.cause.body_id)
1913 && let hir::FnRetTy::Return(ty) = fn_sig.decl.output
1914 && let hir::TyKind::Path(qpath) = ty.kind
1915 && let hir::QPath::Resolved(None, path) = qpath
1916 && let Res::Def(DefKind::TyAlias, def_id) = path.res
1917 {
1918 err.span_note(self.tcx.def_span(def_id), "this type alias is unsized");
1922 err.multipart_suggestion(
1923 ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("consider boxing the return type, and wrapping all of the returned values in `Box::new`"))
})format!(
1924 "consider boxing the return type, and wrapping all of the returned values in \
1925 `Box::new`",
1926 ),
1927 <[_]>::into_vec(::alloc::boxed::box_new([(ty.span.shrink_to_lo(),
"Box<".to_string()),
(ty.span.shrink_to_hi(), ">".to_string())]))vec![
1928 (ty.span.shrink_to_lo(), "Box<".to_string()),
1929 (ty.span.shrink_to_hi(), ">".to_string()),
1930 ],
1931 Applicability::MaybeIncorrect,
1932 );
1933 return false;
1934 }
1935
1936 err.code(E0746);
1937 err.primary_message("return type cannot be a trait object without pointer indirection");
1938 err.children.clear();
1939
1940 let mut span = obligation.cause.span;
1941 if let DefKind::Closure = self.tcx.def_kind(obligation.cause.body_id)
1942 && let parent = self.tcx.parent(obligation.cause.body_id.into())
1943 && let DefKind::Fn | DefKind::AssocFn = self.tcx.def_kind(parent)
1944 && self.tcx.asyncness(parent).is_async()
1945 && let Some(parent) = parent.as_local()
1946 && let Node::Item(hir::Item { kind: hir::ItemKind::Fn { sig: fn_sig, .. }, .. })
1947 | Node::ImplItem(hir::ImplItem { kind: hir::ImplItemKind::Fn(fn_sig, _), .. })
1948 | Node::TraitItem(hir::TraitItem {
1949 kind: hir::TraitItemKind::Fn(fn_sig, _), ..
1950 }) = self.tcx.hir_node_by_def_id(parent)
1951 {
1952 span = fn_sig.decl.output.span();
1957 err.span(span);
1958 }
1959 let body = self.tcx.hir_body_owned_by(obligation.cause.body_id);
1960
1961 let mut visitor = ReturnsVisitor::default();
1962 visitor.visit_body(&body);
1963
1964 let (pre, impl_span) = if let Ok(snip) = self.tcx.sess.source_map().span_to_snippet(span)
1965 && snip.starts_with("dyn ")
1966 {
1967 ("", span.with_hi(span.lo() + BytePos(4)))
1968 } else {
1969 ("dyn ", span.shrink_to_lo())
1970 };
1971
1972 err.span_suggestion_verbose(
1973 impl_span,
1974 "consider returning an `impl Trait` instead of a `dyn Trait`",
1975 "impl ",
1976 Applicability::MaybeIncorrect,
1977 );
1978
1979 let mut sugg = <[_]>::into_vec(::alloc::boxed::box_new([(span.shrink_to_lo(),
::alloc::__export::must_use({
::alloc::fmt::format(format_args!("Box<{0}", pre))
})), (span.shrink_to_hi(), ">".to_string())]))vec![
1980 (span.shrink_to_lo(), format!("Box<{pre}")),
1981 (span.shrink_to_hi(), ">".to_string()),
1982 ];
1983 sugg.extend(visitor.returns.into_iter().flat_map(|expr| {
1984 let span =
1985 expr.span.find_ancestor_in_same_ctxt(obligation.cause.span).unwrap_or(expr.span);
1986 if !span.can_be_used_for_suggestions() {
1987 ::alloc::vec::Vec::new()vec![]
1988 } else if let hir::ExprKind::Call(path, ..) = expr.kind
1989 && let hir::ExprKind::Path(hir::QPath::TypeRelative(ty, method)) = path.kind
1990 && method.ident.name == sym::new
1991 && let hir::TyKind::Path(hir::QPath::Resolved(.., box_path)) = ty.kind
1992 && box_path
1993 .res
1994 .opt_def_id()
1995 .is_some_and(|def_id| self.tcx.is_lang_item(def_id, LangItem::OwnedBox))
1996 {
1997 ::alloc::vec::Vec::new()vec![]
1999 } else {
2000 <[_]>::into_vec(::alloc::boxed::box_new([(span.shrink_to_lo(),
"Box::new(".to_string()),
(span.shrink_to_hi(), ")".to_string())]))vec![
2001 (span.shrink_to_lo(), "Box::new(".to_string()),
2002 (span.shrink_to_hi(), ")".to_string()),
2003 ]
2004 }
2005 }));
2006
2007 err.multipart_suggestion(
2008 ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("alternatively, box the return type, and wrap all of the returned values in `Box::new`"))
})format!(
2009 "alternatively, box the return type, and wrap all of the returned values in \
2010 `Box::new`",
2011 ),
2012 sugg,
2013 Applicability::MaybeIncorrect,
2014 );
2015
2016 true
2017 }
2018
2019 pub(super) fn report_closure_arg_mismatch(
2020 &self,
2021 span: Span,
2022 found_span: Option<Span>,
2023 found: ty::TraitRef<'tcx>,
2024 expected: ty::TraitRef<'tcx>,
2025 cause: &ObligationCauseCode<'tcx>,
2026 found_node: Option<Node<'_>>,
2027 param_env: ty::ParamEnv<'tcx>,
2028 ) -> Diag<'a> {
2029 pub(crate) fn build_fn_sig_ty<'tcx>(
2030 infcx: &InferCtxt<'tcx>,
2031 trait_ref: ty::TraitRef<'tcx>,
2032 ) -> Ty<'tcx> {
2033 let inputs = trait_ref.args.type_at(1);
2034 let sig = match inputs.kind() {
2035 ty::Tuple(inputs) if infcx.tcx.is_fn_trait(trait_ref.def_id) => {
2036 infcx.tcx.mk_fn_sig(
2037 *inputs,
2038 infcx.next_ty_var(DUMMY_SP),
2039 false,
2040 hir::Safety::Safe,
2041 ExternAbi::Rust,
2042 )
2043 }
2044 _ => infcx.tcx.mk_fn_sig(
2045 [inputs],
2046 infcx.next_ty_var(DUMMY_SP),
2047 false,
2048 hir::Safety::Safe,
2049 ExternAbi::Rust,
2050 ),
2051 };
2052
2053 Ty::new_fn_ptr(infcx.tcx, ty::Binder::dummy(sig))
2054 }
2055
2056 let argument_kind = match expected.self_ty().kind() {
2057 ty::Closure(..) => "closure",
2058 ty::Coroutine(..) => "coroutine",
2059 _ => "function",
2060 };
2061 let mut err = {
self.dcx().struct_span_err(span,
::alloc::__export::must_use({
::alloc::fmt::format(format_args!("type mismatch in {0} arguments",
argument_kind))
})).with_code(E0631)
}struct_span_code_err!(
2062 self.dcx(),
2063 span,
2064 E0631,
2065 "type mismatch in {argument_kind} arguments",
2066 );
2067
2068 err.span_label(span, "expected due to this");
2069
2070 let found_span = found_span.unwrap_or(span);
2071 err.span_label(found_span, "found signature defined here");
2072
2073 let expected = build_fn_sig_ty(self, expected);
2074 let found = build_fn_sig_ty(self, found);
2075
2076 let (expected_str, found_str) = self.cmp(expected, found);
2077
2078 let signature_kind = ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("{0} signature", argument_kind))
})format!("{argument_kind} signature");
2079 err.note_expected_found(&signature_kind, expected_str, &signature_kind, found_str);
2080
2081 self.note_conflicting_fn_args(&mut err, cause, expected, found, param_env);
2082 self.note_conflicting_closure_bounds(cause, &mut err);
2083
2084 if let Some(found_node) = found_node {
2085 hint_missing_borrow(self, param_env, span, found, expected, found_node, &mut err);
2086 }
2087
2088 err
2089 }
2090
2091 fn note_conflicting_fn_args(
2092 &self,
2093 err: &mut Diag<'_>,
2094 cause: &ObligationCauseCode<'tcx>,
2095 expected: Ty<'tcx>,
2096 found: Ty<'tcx>,
2097 param_env: ty::ParamEnv<'tcx>,
2098 ) {
2099 let ObligationCauseCode::FunctionArg { arg_hir_id, .. } = cause else {
2100 return;
2101 };
2102 let ty::FnPtr(sig_tys, hdr) = expected.kind() else {
2103 return;
2104 };
2105 let expected = sig_tys.with(*hdr);
2106 let ty::FnPtr(sig_tys, hdr) = found.kind() else {
2107 return;
2108 };
2109 let found = sig_tys.with(*hdr);
2110 let Node::Expr(arg) = self.tcx.hir_node(*arg_hir_id) else {
2111 return;
2112 };
2113 let hir::ExprKind::Path(path) = arg.kind else {
2114 return;
2115 };
2116 let expected_inputs = self.tcx.instantiate_bound_regions_with_erased(expected).inputs();
2117 let found_inputs = self.tcx.instantiate_bound_regions_with_erased(found).inputs();
2118 let both_tys = expected_inputs.iter().copied().zip(found_inputs.iter().copied());
2119
2120 let arg_expr = |infcx: &InferCtxt<'tcx>, name, expected: Ty<'tcx>, found: Ty<'tcx>| {
2121 let (expected_ty, expected_refs) = get_deref_type_and_refs(expected);
2122 let (found_ty, found_refs) = get_deref_type_and_refs(found);
2123
2124 if infcx.can_eq(param_env, found_ty, expected_ty) {
2125 if found_refs.len() == expected_refs.len()
2126 && found_refs.iter().eq(expected_refs.iter())
2127 {
2128 name
2129 } else if found_refs.len() > expected_refs.len() {
2130 let refs = &found_refs[..found_refs.len() - expected_refs.len()];
2131 if found_refs[..expected_refs.len()].iter().eq(expected_refs.iter()) {
2132 ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("{0}{1}",
refs.iter().map(|mutbl|
::alloc::__export::must_use({
::alloc::fmt::format(format_args!("&{0}",
mutbl.prefix_str()))
})).collect::<Vec<_>>().join(""), name))
})format!(
2133 "{}{name}",
2134 refs.iter()
2135 .map(|mutbl| format!("&{}", mutbl.prefix_str()))
2136 .collect::<Vec<_>>()
2137 .join(""),
2138 )
2139 } else {
2140 ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("{0}*{1}",
refs.iter().map(|mutbl|
::alloc::__export::must_use({
::alloc::fmt::format(format_args!("&{0}",
mutbl.prefix_str()))
})).collect::<Vec<_>>().join(""), name))
})format!(
2142 "{}*{name}",
2143 refs.iter()
2144 .map(|mutbl| format!("&{}", mutbl.prefix_str()))
2145 .collect::<Vec<_>>()
2146 .join(""),
2147 )
2148 }
2149 } else if expected_refs.len() > found_refs.len() {
2150 ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("{0}{1}",
(0..(expected_refs.len() -
found_refs.len())).map(|_|
"*").collect::<Vec<_>>().join(""), name))
})format!(
2151 "{}{name}",
2152 (0..(expected_refs.len() - found_refs.len()))
2153 .map(|_| "*")
2154 .collect::<Vec<_>>()
2155 .join(""),
2156 )
2157 } else {
2158 ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("{0}{1}",
found_refs.iter().map(|mutbl|
::alloc::__export::must_use({
::alloc::fmt::format(format_args!("&{0}",
mutbl.prefix_str()))
})).chain(found_refs.iter().map(|_|
"*".to_string())).collect::<Vec<_>>().join(""), name))
})format!(
2159 "{}{name}",
2160 found_refs
2161 .iter()
2162 .map(|mutbl| format!("&{}", mutbl.prefix_str()))
2163 .chain(found_refs.iter().map(|_| "*".to_string()))
2164 .collect::<Vec<_>>()
2165 .join(""),
2166 )
2167 }
2168 } else {
2169 ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("/* {0} */", found))
})format!("/* {found} */")
2170 }
2171 };
2172 let args_have_same_underlying_type = both_tys.clone().all(|(expected, found)| {
2173 let (expected_ty, _) = get_deref_type_and_refs(expected);
2174 let (found_ty, _) = get_deref_type_and_refs(found);
2175 self.can_eq(param_env, found_ty, expected_ty)
2176 });
2177 let (closure_names, call_names): (Vec<_>, Vec<_>) = if args_have_same_underlying_type
2178 && !expected_inputs.is_empty()
2179 && expected_inputs.len() == found_inputs.len()
2180 && let Some(typeck) = &self.typeck_results
2181 && let Res::Def(res_kind, fn_def_id) = typeck.qpath_res(&path, *arg_hir_id)
2182 && res_kind.is_fn_like()
2183 {
2184 let closure: Vec<_> = self
2185 .tcx
2186 .fn_arg_idents(fn_def_id)
2187 .iter()
2188 .enumerate()
2189 .map(|(i, ident)| {
2190 if let Some(ident) = ident
2191 && !#[allow(non_exhaustive_omitted_patterns)] match ident {
Ident { name: kw::Underscore | kw::SelfLower, .. } => true,
_ => false,
}matches!(ident, Ident { name: kw::Underscore | kw::SelfLower, .. })
2192 {
2193 ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("{0}", ident))
})format!("{ident}")
2194 } else {
2195 ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("arg{0}", i))
})format!("arg{i}")
2196 }
2197 })
2198 .collect();
2199 let args = closure
2200 .iter()
2201 .zip(both_tys)
2202 .map(|(name, (expected, found))| {
2203 arg_expr(self.infcx, name.to_owned(), expected, found)
2204 })
2205 .collect();
2206 (closure, args)
2207 } else {
2208 let closure_args = expected_inputs
2209 .iter()
2210 .enumerate()
2211 .map(|(i, _)| ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("arg{0}", i))
})format!("arg{i}"))
2212 .collect::<Vec<_>>();
2213 let call_args = both_tys
2214 .enumerate()
2215 .map(|(i, (expected, found))| {
2216 arg_expr(self.infcx, ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("arg{0}", i))
})format!("arg{i}"), expected, found)
2217 })
2218 .collect::<Vec<_>>();
2219 (closure_args, call_args)
2220 };
2221 let closure_names: Vec<_> = closure_names
2222 .into_iter()
2223 .zip(expected_inputs.iter())
2224 .map(|(name, ty)| {
2225 ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("{1}{0}",
if ty.has_infer_types() {
String::new()
} else if ty.references_error() {
": /* type */".to_string()
} else {
::alloc::__export::must_use({
::alloc::fmt::format(format_args!(": {0}", ty))
})
}, name))
})format!(
2226 "{name}{}",
2227 if ty.has_infer_types() {
2228 String::new()
2229 } else if ty.references_error() {
2230 ": /* type */".to_string()
2231 } else {
2232 format!(": {ty}")
2233 }
2234 )
2235 })
2236 .collect();
2237 err.multipart_suggestion(
2238 "consider wrapping the function in a closure",
2239 <[_]>::into_vec(::alloc::boxed::box_new([(arg.span.shrink_to_lo(),
::alloc::__export::must_use({
::alloc::fmt::format(format_args!("|{0}| ",
closure_names.join(", ")))
})),
(arg.span.shrink_to_hi(),
::alloc::__export::must_use({
::alloc::fmt::format(format_args!("({0})",
call_names.join(", ")))
}))]))vec![
2240 (arg.span.shrink_to_lo(), format!("|{}| ", closure_names.join(", "))),
2241 (arg.span.shrink_to_hi(), format!("({})", call_names.join(", "))),
2242 ],
2243 Applicability::MaybeIncorrect,
2244 );
2245 }
2246
2247 fn note_conflicting_closure_bounds(
2250 &self,
2251 cause: &ObligationCauseCode<'tcx>,
2252 err: &mut Diag<'_>,
2253 ) {
2254 if let ObligationCauseCode::WhereClauseInExpr(def_id, _, _, idx) = cause
2258 && let predicates = self.tcx.predicates_of(def_id).instantiate_identity(self.tcx)
2259 && let Some(pred) = predicates.predicates.get(*idx)
2260 && let ty::ClauseKind::Trait(trait_pred) = pred.kind().skip_binder()
2261 && self.tcx.is_fn_trait(trait_pred.def_id())
2262 {
2263 let expected_self =
2264 self.tcx.anonymize_bound_vars(pred.kind().rebind(trait_pred.self_ty()));
2265 let expected_args =
2266 self.tcx.anonymize_bound_vars(pred.kind().rebind(trait_pred.trait_ref.args));
2267
2268 let other_pred = predicates.into_iter().enumerate().find(|(other_idx, (pred, _))| {
2271 match pred.kind().skip_binder() {
2272 ty::ClauseKind::Trait(trait_pred)
2273 if self.tcx.is_fn_trait(trait_pred.def_id())
2274 && other_idx != idx
2275 && expected_self
2278 == self.tcx.anonymize_bound_vars(
2279 pred.kind().rebind(trait_pred.self_ty()),
2280 )
2281 && expected_args
2283 != self.tcx.anonymize_bound_vars(
2284 pred.kind().rebind(trait_pred.trait_ref.args),
2285 ) =>
2286 {
2287 true
2288 }
2289 _ => false,
2290 }
2291 });
2292 if let Some((_, (_, other_pred_span))) = other_pred {
2294 err.span_note(
2295 other_pred_span,
2296 "closure inferred to have a different signature due to this bound",
2297 );
2298 }
2299 }
2300 }
2301
2302 pub(super) fn suggest_fully_qualified_path(
2303 &self,
2304 err: &mut Diag<'_>,
2305 item_def_id: DefId,
2306 span: Span,
2307 trait_ref: DefId,
2308 ) {
2309 if let Some(assoc_item) = self.tcx.opt_associated_item(item_def_id)
2310 && let ty::AssocKind::Const { .. } | ty::AssocKind::Type { .. } = assoc_item.kind
2311 {
2312 err.note(::alloc::__export::must_use({
::alloc::fmt::format(format_args!("{0}s cannot be accessed directly on a `trait`, they can only be accessed through a specific `impl`",
self.tcx.def_kind_descr(assoc_item.as_def_kind(),
item_def_id)))
})format!(
2313 "{}s cannot be accessed directly on a `trait`, they can only be \
2314 accessed through a specific `impl`",
2315 self.tcx.def_kind_descr(assoc_item.as_def_kind(), item_def_id)
2316 ));
2317
2318 if !assoc_item.is_impl_trait_in_trait() {
2319 err.span_suggestion_verbose(
2320 span,
2321 "use the fully qualified path to an implementation",
2322 ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("<Type as {0}>::{1}",
self.tcx.def_path_str(trait_ref), assoc_item.name()))
})format!(
2323 "<Type as {}>::{}",
2324 self.tcx.def_path_str(trait_ref),
2325 assoc_item.name()
2326 ),
2327 Applicability::HasPlaceholders,
2328 );
2329 }
2330 }
2331 }
2332
2333 #[allow(clippy :: suspicious_else_formatting)]
{
let __tracing_attr_span;
let __tracing_attr_guard;
if ::tracing::Level::DEBUG <= ::tracing::level_filters::STATIC_MAX_LEVEL
&&
::tracing::Level::DEBUG <=
::tracing::level_filters::LevelFilter::current() ||
{ false } {
__tracing_attr_span =
{
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("maybe_note_obligation_cause_for_async_await",
"rustc_trait_selection::error_reporting::traits::suggestions",
::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs"),
::tracing_core::__macro_support::Option::Some(2375u32),
::tracing_core::__macro_support::Option::Some("rustc_trait_selection::error_reporting::traits::suggestions"),
::tracing_core::field::FieldSet::new(&["obligation.predicate",
"obligation.cause.span"],
::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::SPAN)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let mut interest = ::tracing::subscriber::Interest::never();
if ::tracing::Level::DEBUG <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::DEBUG <=
::tracing::level_filters::LevelFilter::current() &&
{ interest = __CALLSITE.interest(); !interest.is_never() }
&&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest) {
let meta = __CALLSITE.metadata();
::tracing::Span::new(meta,
&{
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
let mut iter = meta.fields().iter();
meta.fields().value_set(&[(&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
::tracing::__macro_support::Option::Some(&debug(&obligation.predicate)
as &dyn Value)),
(&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
::tracing::__macro_support::Option::Some(&debug(&obligation.cause.span)
as &dyn Value))])
})
} else {
let span =
::tracing::__macro_support::__disabled_span(__CALLSITE.metadata());
{};
span
}
};
__tracing_attr_guard = __tracing_attr_span.enter();
}
#[warn(clippy :: suspicious_else_formatting)]
{
#[allow(unknown_lints, unreachable_code, clippy ::
diverging_sub_expression, clippy :: empty_loop, clippy ::
let_unit_value, clippy :: let_with_type_underscore, clippy ::
needless_return, clippy :: unreachable)]
if false {
let __tracing_attr_fake_return: bool = loop {};
return __tracing_attr_fake_return;
}
{
let (mut trait_ref, mut target_ty) =
match obligation.predicate.kind().skip_binder() {
ty::PredicateKind::Clause(ty::ClauseKind::Trait(p)) =>
(Some(p), Some(p.self_ty())),
_ => (None, None),
};
let mut coroutine = None;
let mut outer_coroutine = None;
let mut next_code = Some(obligation.cause.code());
let mut seen_upvar_tys_infer_tuple = false;
while let Some(code) = next_code {
{
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/traits/suggestions.rs:2414",
"rustc_trait_selection::error_reporting::traits::suggestions",
::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs"),
::tracing_core::__macro_support::Option::Some(2414u32),
::tracing_core::__macro_support::Option::Some("rustc_trait_selection::error_reporting::traits::suggestions"),
::tracing_core::field::FieldSet::new(&["code"],
::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(&debug(&code) as
&dyn Value))])
});
} else { ; }
};
match code {
ObligationCauseCode::FunctionArg { parent_code, .. } => {
next_code = Some(parent_code);
}
ObligationCauseCode::ImplDerived(cause) => {
let ty =
cause.derived.parent_trait_pred.skip_binder().self_ty();
{
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/traits/suggestions.rs:2421",
"rustc_trait_selection::error_reporting::traits::suggestions",
::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs"),
::tracing_core::__macro_support::Option::Some(2421u32),
::tracing_core::__macro_support::Option::Some("rustc_trait_selection::error_reporting::traits::suggestions"),
::tracing_core::field::FieldSet::new(&["message",
"parent_trait_ref", "self_ty.kind"],
::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!("ImplDerived")
as &dyn Value)),
(&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
::tracing::__macro_support::Option::Some(&debug(&cause.derived.parent_trait_pred)
as &dyn Value)),
(&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
::tracing::__macro_support::Option::Some(&debug(&ty.kind())
as &dyn Value))])
});
} else { ; }
};
match *ty.kind() {
ty::Coroutine(did, ..) | ty::CoroutineWitness(did, _) => {
coroutine = coroutine.or(Some(did));
outer_coroutine = Some(did);
}
ty::Tuple(_) if !seen_upvar_tys_infer_tuple => {
seen_upvar_tys_infer_tuple = true;
}
_ if coroutine.is_none() => {
trait_ref =
Some(cause.derived.parent_trait_pred.skip_binder());
target_ty = Some(ty);
}
_ => {}
}
next_code = Some(&cause.derived.parent_code);
}
ObligationCauseCode::WellFormedDerived(derived_obligation) |
ObligationCauseCode::BuiltinDerived(derived_obligation) => {
let ty =
derived_obligation.parent_trait_pred.skip_binder().self_ty();
{
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/traits/suggestions.rs:2451",
"rustc_trait_selection::error_reporting::traits::suggestions",
::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs"),
::tracing_core::__macro_support::Option::Some(2451u32),
::tracing_core::__macro_support::Option::Some("rustc_trait_selection::error_reporting::traits::suggestions"),
::tracing_core::field::FieldSet::new(&["parent_trait_ref",
"self_ty.kind"],
::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(&debug(&derived_obligation.parent_trait_pred)
as &dyn Value)),
(&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
::tracing::__macro_support::Option::Some(&debug(&ty.kind())
as &dyn Value))])
});
} else { ; }
};
match *ty.kind() {
ty::Coroutine(did, ..) | ty::CoroutineWitness(did, ..) => {
coroutine = coroutine.or(Some(did));
outer_coroutine = Some(did);
}
ty::Tuple(_) if !seen_upvar_tys_infer_tuple => {
seen_upvar_tys_infer_tuple = true;
}
_ if coroutine.is_none() => {
trait_ref =
Some(derived_obligation.parent_trait_pred.skip_binder());
target_ty = Some(ty);
}
_ => {}
}
next_code = Some(&derived_obligation.parent_code);
}
_ => break,
}
}
{
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/traits/suggestions.rs:2482",
"rustc_trait_selection::error_reporting::traits::suggestions",
::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs"),
::tracing_core::__macro_support::Option::Some(2482u32),
::tracing_core::__macro_support::Option::Some("rustc_trait_selection::error_reporting::traits::suggestions"),
::tracing_core::field::FieldSet::new(&["coroutine",
"trait_ref", "target_ty"],
::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(&debug(&coroutine)
as &dyn Value)),
(&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
::tracing::__macro_support::Option::Some(&debug(&trait_ref)
as &dyn Value)),
(&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
::tracing::__macro_support::Option::Some(&debug(&target_ty)
as &dyn Value))])
});
} else { ; }
};
let (Some(coroutine_did), Some(trait_ref), Some(target_ty)) =
(coroutine, trait_ref, target_ty) else { return false; };
let span = self.tcx.def_span(coroutine_did);
let coroutine_did_root =
self.tcx.typeck_root_def_id(coroutine_did);
{
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/traits/suggestions.rs:2492",
"rustc_trait_selection::error_reporting::traits::suggestions",
::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs"),
::tracing_core::__macro_support::Option::Some(2492u32),
::tracing_core::__macro_support::Option::Some("rustc_trait_selection::error_reporting::traits::suggestions"),
::tracing_core::field::FieldSet::new(&["coroutine_did",
"coroutine_did_root", "typeck_results.hir_owner", "span"],
::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(&debug(&coroutine_did)
as &dyn Value)),
(&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
::tracing::__macro_support::Option::Some(&debug(&coroutine_did_root)
as &dyn Value)),
(&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
::tracing::__macro_support::Option::Some(&debug(&self.typeck_results.as_ref().map(|t|
t.hir_owner)) as &dyn Value)),
(&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
::tracing::__macro_support::Option::Some(&debug(&span) as
&dyn Value))])
});
} else { ; }
};
let coroutine_body =
coroutine_did.as_local().and_then(|def_id|
self.tcx.hir_maybe_body_owned_by(def_id));
let mut visitor = AwaitsVisitor::default();
if let Some(body) = coroutine_body { visitor.visit_body(&body); }
{
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/traits/suggestions.rs:2505",
"rustc_trait_selection::error_reporting::traits::suggestions",
::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs"),
::tracing_core::__macro_support::Option::Some(2505u32),
::tracing_core::__macro_support::Option::Some("rustc_trait_selection::error_reporting::traits::suggestions"),
::tracing_core::field::FieldSet::new(&["awaits"],
::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(&debug(&visitor.awaits)
as &dyn Value))])
});
} else { ; }
};
let target_ty_erased =
self.tcx.erase_and_anonymize_regions(target_ty);
let ty_matches =
|ty| -> bool
{
let ty_erased =
self.tcx.instantiate_bound_regions_with_erased(ty);
let ty_erased =
self.tcx.erase_and_anonymize_regions(ty_erased);
let eq = ty_erased == target_ty_erased;
{
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/traits/suggestions.rs:2526",
"rustc_trait_selection::error_reporting::traits::suggestions",
::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs"),
::tracing_core::__macro_support::Option::Some(2526u32),
::tracing_core::__macro_support::Option::Some("rustc_trait_selection::error_reporting::traits::suggestions"),
::tracing_core::field::FieldSet::new(&["ty_erased",
"target_ty_erased", "eq"],
::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(&debug(&ty_erased)
as &dyn Value)),
(&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
::tracing::__macro_support::Option::Some(&debug(&target_ty_erased)
as &dyn Value)),
(&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
::tracing::__macro_support::Option::Some(&debug(&eq) as
&dyn Value))])
});
} else { ; }
};
eq
};
let coroutine_data =
match &self.typeck_results {
Some(t) if t.hir_owner.to_def_id() == coroutine_did_root =>
CoroutineData(t),
_ if coroutine_did.is_local() => {
CoroutineData(self.tcx.typeck(coroutine_did.expect_local()))
}
_ => return false,
};
let coroutine_within_in_progress_typeck =
match &self.typeck_results {
Some(t) => t.hir_owner.to_def_id() == coroutine_did_root,
_ => false,
};
let mut interior_or_upvar_span = None;
let from_awaited_ty =
coroutine_data.get_from_await_ty(visitor, self.tcx,
ty_matches);
{
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/traits/suggestions.rs:2550",
"rustc_trait_selection::error_reporting::traits::suggestions",
::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs"),
::tracing_core::__macro_support::Option::Some(2550u32),
::tracing_core::__macro_support::Option::Some("rustc_trait_selection::error_reporting::traits::suggestions"),
::tracing_core::field::FieldSet::new(&["from_awaited_ty"],
::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(&debug(&from_awaited_ty)
as &dyn Value))])
});
} else { ; }
};
if coroutine_did.is_local() &&
!coroutine_within_in_progress_typeck &&
let Some(coroutine_info) =
self.tcx.mir_coroutine_witnesses(coroutine_did) {
{
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/traits/suggestions.rs:2558",
"rustc_trait_selection::error_reporting::traits::suggestions",
::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs"),
::tracing_core::__macro_support::Option::Some(2558u32),
::tracing_core::__macro_support::Option::Some("rustc_trait_selection::error_reporting::traits::suggestions"),
::tracing_core::field::FieldSet::new(&["coroutine_info"],
::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(&debug(&coroutine_info)
as &dyn Value))])
});
} else { ; }
};
'find_source:
for (variant, source_info) in
coroutine_info.variant_fields.iter().zip(&coroutine_info.variant_source_info)
{
{
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/traits/suggestions.rs:2562",
"rustc_trait_selection::error_reporting::traits::suggestions",
::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs"),
::tracing_core::__macro_support::Option::Some(2562u32),
::tracing_core::__macro_support::Option::Some("rustc_trait_selection::error_reporting::traits::suggestions"),
::tracing_core::field::FieldSet::new(&["variant"],
::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(&debug(&variant) as
&dyn Value))])
});
} else { ; }
};
for &local in variant {
let decl = &coroutine_info.field_tys[local];
{
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/traits/suggestions.rs:2565",
"rustc_trait_selection::error_reporting::traits::suggestions",
::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs"),
::tracing_core::__macro_support::Option::Some(2565u32),
::tracing_core::__macro_support::Option::Some("rustc_trait_selection::error_reporting::traits::suggestions"),
::tracing_core::field::FieldSet::new(&["decl"],
::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(&debug(&decl) as
&dyn Value))])
});
} else { ; }
};
if ty_matches(ty::Binder::dummy(decl.ty)) &&
!decl.ignore_for_traits {
interior_or_upvar_span =
Some(CoroutineInteriorOrUpvar::Interior(decl.source_info.span,
Some((source_info.span, from_awaited_ty))));
break 'find_source;
}
}
}
}
if interior_or_upvar_span.is_none() {
interior_or_upvar_span =
coroutine_data.try_get_upvar_span(self, coroutine_did,
ty_matches);
}
if interior_or_upvar_span.is_none() && !coroutine_did.is_local() {
interior_or_upvar_span =
Some(CoroutineInteriorOrUpvar::Interior(span, None));
}
{
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/traits/suggestions.rs:2586",
"rustc_trait_selection::error_reporting::traits::suggestions",
::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs"),
::tracing_core::__macro_support::Option::Some(2586u32),
::tracing_core::__macro_support::Option::Some("rustc_trait_selection::error_reporting::traits::suggestions"),
::tracing_core::field::FieldSet::new(&["interior_or_upvar_span"],
::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(&debug(&interior_or_upvar_span)
as &dyn Value))])
});
} else { ; }
};
if let Some(interior_or_upvar_span) = interior_or_upvar_span {
let is_async = self.tcx.coroutine_is_async(coroutine_did);
self.note_obligation_cause_for_async_await(err,
interior_or_upvar_span, is_async, outer_coroutine,
trait_ref, target_ty, obligation, next_code);
true
} else { false }
}
}
}#[instrument(level = "debug", skip_all, fields(?obligation.predicate, ?obligation.cause.span))]
2376 pub fn maybe_note_obligation_cause_for_async_await<G: EmissionGuarantee>(
2377 &self,
2378 err: &mut Diag<'_, G>,
2379 obligation: &PredicateObligation<'tcx>,
2380 ) -> bool {
2381 let (mut trait_ref, mut target_ty) = match obligation.predicate.kind().skip_binder() {
2404 ty::PredicateKind::Clause(ty::ClauseKind::Trait(p)) => (Some(p), Some(p.self_ty())),
2405 _ => (None, None),
2406 };
2407 let mut coroutine = None;
2408 let mut outer_coroutine = None;
2409 let mut next_code = Some(obligation.cause.code());
2410
2411 let mut seen_upvar_tys_infer_tuple = false;
2412
2413 while let Some(code) = next_code {
2414 debug!(?code);
2415 match code {
2416 ObligationCauseCode::FunctionArg { parent_code, .. } => {
2417 next_code = Some(parent_code);
2418 }
2419 ObligationCauseCode::ImplDerived(cause) => {
2420 let ty = cause.derived.parent_trait_pred.skip_binder().self_ty();
2421 debug!(
2422 parent_trait_ref = ?cause.derived.parent_trait_pred,
2423 self_ty.kind = ?ty.kind(),
2424 "ImplDerived",
2425 );
2426
2427 match *ty.kind() {
2428 ty::Coroutine(did, ..) | ty::CoroutineWitness(did, _) => {
2429 coroutine = coroutine.or(Some(did));
2430 outer_coroutine = Some(did);
2431 }
2432 ty::Tuple(_) if !seen_upvar_tys_infer_tuple => {
2433 seen_upvar_tys_infer_tuple = true;
2438 }
2439 _ if coroutine.is_none() => {
2440 trait_ref = Some(cause.derived.parent_trait_pred.skip_binder());
2441 target_ty = Some(ty);
2442 }
2443 _ => {}
2444 }
2445
2446 next_code = Some(&cause.derived.parent_code);
2447 }
2448 ObligationCauseCode::WellFormedDerived(derived_obligation)
2449 | ObligationCauseCode::BuiltinDerived(derived_obligation) => {
2450 let ty = derived_obligation.parent_trait_pred.skip_binder().self_ty();
2451 debug!(
2452 parent_trait_ref = ?derived_obligation.parent_trait_pred,
2453 self_ty.kind = ?ty.kind(),
2454 );
2455
2456 match *ty.kind() {
2457 ty::Coroutine(did, ..) | ty::CoroutineWitness(did, ..) => {
2458 coroutine = coroutine.or(Some(did));
2459 outer_coroutine = Some(did);
2460 }
2461 ty::Tuple(_) if !seen_upvar_tys_infer_tuple => {
2462 seen_upvar_tys_infer_tuple = true;
2467 }
2468 _ if coroutine.is_none() => {
2469 trait_ref = Some(derived_obligation.parent_trait_pred.skip_binder());
2470 target_ty = Some(ty);
2471 }
2472 _ => {}
2473 }
2474
2475 next_code = Some(&derived_obligation.parent_code);
2476 }
2477 _ => break,
2478 }
2479 }
2480
2481 debug!(?coroutine, ?trait_ref, ?target_ty);
2483 let (Some(coroutine_did), Some(trait_ref), Some(target_ty)) =
2484 (coroutine, trait_ref, target_ty)
2485 else {
2486 return false;
2487 };
2488
2489 let span = self.tcx.def_span(coroutine_did);
2490
2491 let coroutine_did_root = self.tcx.typeck_root_def_id(coroutine_did);
2492 debug!(
2493 ?coroutine_did,
2494 ?coroutine_did_root,
2495 typeck_results.hir_owner = ?self.typeck_results.as_ref().map(|t| t.hir_owner),
2496 ?span,
2497 );
2498
2499 let coroutine_body =
2500 coroutine_did.as_local().and_then(|def_id| self.tcx.hir_maybe_body_owned_by(def_id));
2501 let mut visitor = AwaitsVisitor::default();
2502 if let Some(body) = coroutine_body {
2503 visitor.visit_body(&body);
2504 }
2505 debug!(awaits = ?visitor.awaits);
2506
2507 let target_ty_erased = self.tcx.erase_and_anonymize_regions(target_ty);
2510 let ty_matches = |ty| -> bool {
2511 let ty_erased = self.tcx.instantiate_bound_regions_with_erased(ty);
2524 let ty_erased = self.tcx.erase_and_anonymize_regions(ty_erased);
2525 let eq = ty_erased == target_ty_erased;
2526 debug!(?ty_erased, ?target_ty_erased, ?eq);
2527 eq
2528 };
2529
2530 let coroutine_data = match &self.typeck_results {
2535 Some(t) if t.hir_owner.to_def_id() == coroutine_did_root => CoroutineData(t),
2536 _ if coroutine_did.is_local() => {
2537 CoroutineData(self.tcx.typeck(coroutine_did.expect_local()))
2538 }
2539 _ => return false,
2540 };
2541
2542 let coroutine_within_in_progress_typeck = match &self.typeck_results {
2543 Some(t) => t.hir_owner.to_def_id() == coroutine_did_root,
2544 _ => false,
2545 };
2546
2547 let mut interior_or_upvar_span = None;
2548
2549 let from_awaited_ty = coroutine_data.get_from_await_ty(visitor, self.tcx, ty_matches);
2550 debug!(?from_awaited_ty);
2551
2552 if coroutine_did.is_local()
2554 && !coroutine_within_in_progress_typeck
2556 && let Some(coroutine_info) = self.tcx.mir_coroutine_witnesses(coroutine_did)
2557 {
2558 debug!(?coroutine_info);
2559 'find_source: for (variant, source_info) in
2560 coroutine_info.variant_fields.iter().zip(&coroutine_info.variant_source_info)
2561 {
2562 debug!(?variant);
2563 for &local in variant {
2564 let decl = &coroutine_info.field_tys[local];
2565 debug!(?decl);
2566 if ty_matches(ty::Binder::dummy(decl.ty)) && !decl.ignore_for_traits {
2567 interior_or_upvar_span = Some(CoroutineInteriorOrUpvar::Interior(
2568 decl.source_info.span,
2569 Some((source_info.span, from_awaited_ty)),
2570 ));
2571 break 'find_source;
2572 }
2573 }
2574 }
2575 }
2576
2577 if interior_or_upvar_span.is_none() {
2578 interior_or_upvar_span =
2579 coroutine_data.try_get_upvar_span(self, coroutine_did, ty_matches);
2580 }
2581
2582 if interior_or_upvar_span.is_none() && !coroutine_did.is_local() {
2583 interior_or_upvar_span = Some(CoroutineInteriorOrUpvar::Interior(span, None));
2584 }
2585
2586 debug!(?interior_or_upvar_span);
2587 if let Some(interior_or_upvar_span) = interior_or_upvar_span {
2588 let is_async = self.tcx.coroutine_is_async(coroutine_did);
2589 self.note_obligation_cause_for_async_await(
2590 err,
2591 interior_or_upvar_span,
2592 is_async,
2593 outer_coroutine,
2594 trait_ref,
2595 target_ty,
2596 obligation,
2597 next_code,
2598 );
2599 true
2600 } else {
2601 false
2602 }
2603 }
2604
2605 #[allow(clippy :: suspicious_else_formatting)]
{
let __tracing_attr_span;
let __tracing_attr_guard;
if ::tracing::Level::DEBUG <= ::tracing::level_filters::STATIC_MAX_LEVEL
&&
::tracing::Level::DEBUG <=
::tracing::level_filters::LevelFilter::current() ||
{ false } {
__tracing_attr_span =
{
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("note_obligation_cause_for_async_await",
"rustc_trait_selection::error_reporting::traits::suggestions",
::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs"),
::tracing_core::__macro_support::Option::Some(2607u32),
::tracing_core::__macro_support::Option::Some("rustc_trait_selection::error_reporting::traits::suggestions"),
::tracing_core::field::FieldSet::new(&[],
::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::SPAN)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let mut interest = ::tracing::subscriber::Interest::never();
if ::tracing::Level::DEBUG <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::DEBUG <=
::tracing::level_filters::LevelFilter::current() &&
{ interest = __CALLSITE.interest(); !interest.is_never() }
&&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest) {
let meta = __CALLSITE.metadata();
::tracing::Span::new(meta,
&{ meta.fields().value_set(&[]) })
} else {
let span =
::tracing::__macro_support::__disabled_span(__CALLSITE.metadata());
{};
span
}
};
__tracing_attr_guard = __tracing_attr_span.enter();
}
#[warn(clippy :: suspicious_else_formatting)]
{
#[allow(unknown_lints, unreachable_code, clippy ::
diverging_sub_expression, clippy :: empty_loop, clippy ::
let_unit_value, clippy :: let_with_type_underscore, clippy ::
needless_return, clippy :: unreachable)]
if false {
let __tracing_attr_fake_return: () = loop {};
return __tracing_attr_fake_return;
}
{
let source_map = self.tcx.sess.source_map();
let (await_or_yield, an_await_or_yield) =
if is_async {
("await", "an await")
} else { ("yield", "a yield") };
let future_or_coroutine =
if is_async { "future" } else { "coroutine" };
let trait_explanation =
if let Some(name @ (sym::Send | sym::Sync)) =
self.tcx.get_diagnostic_name(trait_pred.def_id()) {
let (trait_name, trait_verb) =
if name == sym::Send {
("`Send`", "sent")
} else { ("`Sync`", "shared") };
err.code = None;
err.primary_message(::alloc::__export::must_use({
::alloc::fmt::format(format_args!("{0} cannot be {1} between threads safely",
future_or_coroutine, trait_verb))
}));
let original_span = err.span.primary_span().unwrap();
let mut span = MultiSpan::from_span(original_span);
let message =
outer_coroutine.and_then(|coroutine_did|
{
Some(match self.tcx.coroutine_kind(coroutine_did).unwrap() {
CoroutineKind::Coroutine(_) =>
::alloc::__export::must_use({
::alloc::fmt::format(format_args!("coroutine is not {0}",
trait_name))
}),
CoroutineKind::Desugared(CoroutineDesugaring::Async,
CoroutineSource::Fn) =>
self.tcx.parent(coroutine_did).as_local().map(|parent_did|
self.tcx.local_def_id_to_hir_id(parent_did)).and_then(|parent_hir_id|
self.tcx.hir_opt_name(parent_hir_id)).map(|name|
{
::alloc::__export::must_use({
::alloc::fmt::format(format_args!("future returned by `{0}` is not {1}",
name, trait_name))
})
})?,
CoroutineKind::Desugared(CoroutineDesugaring::Async,
CoroutineSource::Block) => {
::alloc::__export::must_use({
::alloc::fmt::format(format_args!("future created by async block is not {0}",
trait_name))
})
}
CoroutineKind::Desugared(CoroutineDesugaring::Async,
CoroutineSource::Closure) => {
::alloc::__export::must_use({
::alloc::fmt::format(format_args!("future created by async closure is not {0}",
trait_name))
})
}
CoroutineKind::Desugared(CoroutineDesugaring::AsyncGen,
CoroutineSource::Fn) =>
self.tcx.parent(coroutine_did).as_local().map(|parent_did|
self.tcx.local_def_id_to_hir_id(parent_did)).and_then(|parent_hir_id|
self.tcx.hir_opt_name(parent_hir_id)).map(|name|
{
::alloc::__export::must_use({
::alloc::fmt::format(format_args!("async iterator returned by `{0}` is not {1}",
name, trait_name))
})
})?,
CoroutineKind::Desugared(CoroutineDesugaring::AsyncGen,
CoroutineSource::Block) => {
::alloc::__export::must_use({
::alloc::fmt::format(format_args!("async iterator created by async gen block is not {0}",
trait_name))
})
}
CoroutineKind::Desugared(CoroutineDesugaring::AsyncGen,
CoroutineSource::Closure) => {
::alloc::__export::must_use({
::alloc::fmt::format(format_args!("async iterator created by async gen closure is not {0}",
trait_name))
})
}
CoroutineKind::Desugared(CoroutineDesugaring::Gen,
CoroutineSource::Fn) => {
self.tcx.parent(coroutine_did).as_local().map(|parent_did|
self.tcx.local_def_id_to_hir_id(parent_did)).and_then(|parent_hir_id|
self.tcx.hir_opt_name(parent_hir_id)).map(|name|
{
::alloc::__export::must_use({
::alloc::fmt::format(format_args!("iterator returned by `{0}` is not {1}",
name, trait_name))
})
})?
}
CoroutineKind::Desugared(CoroutineDesugaring::Gen,
CoroutineSource::Block) => {
::alloc::__export::must_use({
::alloc::fmt::format(format_args!("iterator created by gen block is not {0}",
trait_name))
})
}
CoroutineKind::Desugared(CoroutineDesugaring::Gen,
CoroutineSource::Closure) => {
::alloc::__export::must_use({
::alloc::fmt::format(format_args!("iterator created by gen closure is not {0}",
trait_name))
})
}
})
}).unwrap_or_else(||
::alloc::__export::must_use({
::alloc::fmt::format(format_args!("{0} is not {1}",
future_or_coroutine, trait_name))
}));
span.push_span_label(original_span, message);
err.span(span);
::alloc::__export::must_use({
::alloc::fmt::format(format_args!("is not {0}", trait_name))
})
} else {
::alloc::__export::must_use({
::alloc::fmt::format(format_args!("does not implement `{0}`",
trait_pred.print_modifiers_and_trait_path()))
})
};
let mut explain_yield =
|interior_span: Span, yield_span: Span|
{
let mut span = MultiSpan::from_span(yield_span);
let snippet =
match source_map.span_to_snippet(interior_span) {
Ok(snippet) if !snippet.contains('\n') =>
::alloc::__export::must_use({
::alloc::fmt::format(format_args!("`{0}`", snippet))
}),
_ => "the value".to_string(),
};
span.push_span_label(yield_span,
::alloc::__export::must_use({
::alloc::fmt::format(format_args!("{0} occurs here, with {1} maybe used later",
await_or_yield, snippet))
}));
span.push_span_label(interior_span,
::alloc::__export::must_use({
::alloc::fmt::format(format_args!("has type `{0}` which {1}",
target_ty, trait_explanation))
}));
err.span_note(span,
::alloc::__export::must_use({
::alloc::fmt::format(format_args!("{0} {1} as this value is used across {2}",
future_or_coroutine, trait_explanation, an_await_or_yield))
}));
};
match interior_or_upvar_span {
CoroutineInteriorOrUpvar::Interior(interior_span,
interior_extra_info) => {
if let Some((yield_span, from_awaited_ty)) =
interior_extra_info {
if let Some(await_span) = from_awaited_ty {
let mut span = MultiSpan::from_span(await_span);
span.push_span_label(await_span,
::alloc::__export::must_use({
::alloc::fmt::format(format_args!("await occurs here on type `{0}`, which {1}",
target_ty, trait_explanation))
}));
err.span_note(span,
::alloc::__export::must_use({
::alloc::fmt::format(format_args!("future {0} as it awaits another future which {0}",
trait_explanation))
}));
} else { explain_yield(interior_span, yield_span); }
}
}
CoroutineInteriorOrUpvar::Upvar(upvar_span) => {
let non_send =
match target_ty.kind() {
ty::Ref(_, ref_ty, mutability) =>
match self.evaluate_obligation(obligation) {
Ok(eval) if !eval.may_apply() =>
Some((ref_ty, mutability.is_mut())),
_ => None,
},
_ => None,
};
let (span_label, span_note) =
match non_send {
Some((ref_ty, is_mut)) => {
let ref_ty_trait = if is_mut { "Send" } else { "Sync" };
let ref_kind = if is_mut { "&mut" } else { "&" };
(::alloc::__export::must_use({
::alloc::fmt::format(format_args!("has type `{0}` which {1}, because `{2}` is not `{3}`",
target_ty, trait_explanation, ref_ty, ref_ty_trait))
}),
::alloc::__export::must_use({
::alloc::fmt::format(format_args!("captured value {0} because `{1}` references cannot be sent unless their referent is `{2}`",
trait_explanation, ref_kind, ref_ty_trait))
}))
}
None =>
(::alloc::__export::must_use({
::alloc::fmt::format(format_args!("has type `{0}` which {1}",
target_ty, trait_explanation))
}),
::alloc::__export::must_use({
::alloc::fmt::format(format_args!("captured value {0}",
trait_explanation))
})),
};
let mut span = MultiSpan::from_span(upvar_span);
span.push_span_label(upvar_span, span_label);
err.span_note(span, span_note);
}
}
{
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/traits/suggestions.rs:2830",
"rustc_trait_selection::error_reporting::traits::suggestions",
::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs"),
::tracing_core::__macro_support::Option::Some(2830u32),
::tracing_core::__macro_support::Option::Some("rustc_trait_selection::error_reporting::traits::suggestions"),
::tracing_core::field::FieldSet::new(&["next_code"],
::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(&debug(&next_code)
as &dyn Value))])
});
} else { ; }
};
self.note_obligation_cause_code(obligation.cause.body_id, err,
obligation.predicate, obligation.param_env,
next_code.unwrap(), &mut Vec::new(), &mut Default::default());
}
}
}#[instrument(level = "debug", skip_all)]
2608 fn note_obligation_cause_for_async_await<G: EmissionGuarantee>(
2609 &self,
2610 err: &mut Diag<'_, G>,
2611 interior_or_upvar_span: CoroutineInteriorOrUpvar,
2612 is_async: bool,
2613 outer_coroutine: Option<DefId>,
2614 trait_pred: ty::TraitPredicate<'tcx>,
2615 target_ty: Ty<'tcx>,
2616 obligation: &PredicateObligation<'tcx>,
2617 next_code: Option<&ObligationCauseCode<'tcx>>,
2618 ) {
2619 let source_map = self.tcx.sess.source_map();
2620
2621 let (await_or_yield, an_await_or_yield) =
2622 if is_async { ("await", "an await") } else { ("yield", "a yield") };
2623 let future_or_coroutine = if is_async { "future" } else { "coroutine" };
2624
2625 let trait_explanation = if let Some(name @ (sym::Send | sym::Sync)) =
2628 self.tcx.get_diagnostic_name(trait_pred.def_id())
2629 {
2630 let (trait_name, trait_verb) =
2631 if name == sym::Send { ("`Send`", "sent") } else { ("`Sync`", "shared") };
2632
2633 err.code = None;
2634 err.primary_message(format!(
2635 "{future_or_coroutine} cannot be {trait_verb} between threads safely"
2636 ));
2637
2638 let original_span = err.span.primary_span().unwrap();
2639 let mut span = MultiSpan::from_span(original_span);
2640
2641 let message = outer_coroutine
2642 .and_then(|coroutine_did| {
2643 Some(match self.tcx.coroutine_kind(coroutine_did).unwrap() {
2644 CoroutineKind::Coroutine(_) => format!("coroutine is not {trait_name}"),
2645 CoroutineKind::Desugared(
2646 CoroutineDesugaring::Async,
2647 CoroutineSource::Fn,
2648 ) => self
2649 .tcx
2650 .parent(coroutine_did)
2651 .as_local()
2652 .map(|parent_did| self.tcx.local_def_id_to_hir_id(parent_did))
2653 .and_then(|parent_hir_id| self.tcx.hir_opt_name(parent_hir_id))
2654 .map(|name| {
2655 format!("future returned by `{name}` is not {trait_name}")
2656 })?,
2657 CoroutineKind::Desugared(
2658 CoroutineDesugaring::Async,
2659 CoroutineSource::Block,
2660 ) => {
2661 format!("future created by async block is not {trait_name}")
2662 }
2663 CoroutineKind::Desugared(
2664 CoroutineDesugaring::Async,
2665 CoroutineSource::Closure,
2666 ) => {
2667 format!("future created by async closure is not {trait_name}")
2668 }
2669 CoroutineKind::Desugared(
2670 CoroutineDesugaring::AsyncGen,
2671 CoroutineSource::Fn,
2672 ) => self
2673 .tcx
2674 .parent(coroutine_did)
2675 .as_local()
2676 .map(|parent_did| self.tcx.local_def_id_to_hir_id(parent_did))
2677 .and_then(|parent_hir_id| self.tcx.hir_opt_name(parent_hir_id))
2678 .map(|name| {
2679 format!("async iterator returned by `{name}` is not {trait_name}")
2680 })?,
2681 CoroutineKind::Desugared(
2682 CoroutineDesugaring::AsyncGen,
2683 CoroutineSource::Block,
2684 ) => {
2685 format!("async iterator created by async gen block is not {trait_name}")
2686 }
2687 CoroutineKind::Desugared(
2688 CoroutineDesugaring::AsyncGen,
2689 CoroutineSource::Closure,
2690 ) => {
2691 format!(
2692 "async iterator created by async gen closure is not {trait_name}"
2693 )
2694 }
2695 CoroutineKind::Desugared(CoroutineDesugaring::Gen, CoroutineSource::Fn) => {
2696 self.tcx
2697 .parent(coroutine_did)
2698 .as_local()
2699 .map(|parent_did| self.tcx.local_def_id_to_hir_id(parent_did))
2700 .and_then(|parent_hir_id| self.tcx.hir_opt_name(parent_hir_id))
2701 .map(|name| {
2702 format!("iterator returned by `{name}` is not {trait_name}")
2703 })?
2704 }
2705 CoroutineKind::Desugared(
2706 CoroutineDesugaring::Gen,
2707 CoroutineSource::Block,
2708 ) => {
2709 format!("iterator created by gen block is not {trait_name}")
2710 }
2711 CoroutineKind::Desugared(
2712 CoroutineDesugaring::Gen,
2713 CoroutineSource::Closure,
2714 ) => {
2715 format!("iterator created by gen closure is not {trait_name}")
2716 }
2717 })
2718 })
2719 .unwrap_or_else(|| format!("{future_or_coroutine} is not {trait_name}"));
2720
2721 span.push_span_label(original_span, message);
2722 err.span(span);
2723
2724 format!("is not {trait_name}")
2725 } else {
2726 format!("does not implement `{}`", trait_pred.print_modifiers_and_trait_path())
2727 };
2728
2729 let mut explain_yield = |interior_span: Span, yield_span: Span| {
2730 let mut span = MultiSpan::from_span(yield_span);
2731 let snippet = match source_map.span_to_snippet(interior_span) {
2732 Ok(snippet) if !snippet.contains('\n') => format!("`{snippet}`"),
2735 _ => "the value".to_string(),
2736 };
2737 span.push_span_label(
2754 yield_span,
2755 format!("{await_or_yield} occurs here, with {snippet} maybe used later"),
2756 );
2757 span.push_span_label(
2758 interior_span,
2759 format!("has type `{target_ty}` which {trait_explanation}"),
2760 );
2761 err.span_note(
2762 span,
2763 format!("{future_or_coroutine} {trait_explanation} as this value is used across {an_await_or_yield}"),
2764 );
2765 };
2766 match interior_or_upvar_span {
2767 CoroutineInteriorOrUpvar::Interior(interior_span, interior_extra_info) => {
2768 if let Some((yield_span, from_awaited_ty)) = interior_extra_info {
2769 if let Some(await_span) = from_awaited_ty {
2770 let mut span = MultiSpan::from_span(await_span);
2772 span.push_span_label(
2773 await_span,
2774 format!(
2775 "await occurs here on type `{target_ty}`, which {trait_explanation}"
2776 ),
2777 );
2778 err.span_note(
2779 span,
2780 format!(
2781 "future {trait_explanation} as it awaits another future which {trait_explanation}"
2782 ),
2783 );
2784 } else {
2785 explain_yield(interior_span, yield_span);
2787 }
2788 }
2789 }
2790 CoroutineInteriorOrUpvar::Upvar(upvar_span) => {
2791 let non_send = match target_ty.kind() {
2793 ty::Ref(_, ref_ty, mutability) => match self.evaluate_obligation(obligation) {
2794 Ok(eval) if !eval.may_apply() => Some((ref_ty, mutability.is_mut())),
2795 _ => None,
2796 },
2797 _ => None,
2798 };
2799
2800 let (span_label, span_note) = match non_send {
2801 Some((ref_ty, is_mut)) => {
2805 let ref_ty_trait = if is_mut { "Send" } else { "Sync" };
2806 let ref_kind = if is_mut { "&mut" } else { "&" };
2807 (
2808 format!(
2809 "has type `{target_ty}` which {trait_explanation}, because `{ref_ty}` is not `{ref_ty_trait}`"
2810 ),
2811 format!(
2812 "captured value {trait_explanation} because `{ref_kind}` references cannot be sent unless their referent is `{ref_ty_trait}`"
2813 ),
2814 )
2815 }
2816 None => (
2817 format!("has type `{target_ty}` which {trait_explanation}"),
2818 format!("captured value {trait_explanation}"),
2819 ),
2820 };
2821
2822 let mut span = MultiSpan::from_span(upvar_span);
2823 span.push_span_label(upvar_span, span_label);
2824 err.span_note(span, span_note);
2825 }
2826 }
2827
2828 debug!(?next_code);
2831 self.note_obligation_cause_code(
2832 obligation.cause.body_id,
2833 err,
2834 obligation.predicate,
2835 obligation.param_env,
2836 next_code.unwrap(),
2837 &mut Vec::new(),
2838 &mut Default::default(),
2839 );
2840 }
2841
2842 pub(super) fn note_obligation_cause_code<G: EmissionGuarantee, T>(
2843 &self,
2844 body_id: LocalDefId,
2845 err: &mut Diag<'_, G>,
2846 predicate: T,
2847 param_env: ty::ParamEnv<'tcx>,
2848 cause_code: &ObligationCauseCode<'tcx>,
2849 obligated_types: &mut Vec<Ty<'tcx>>,
2850 seen_requirements: &mut FxHashSet<DefId>,
2851 ) where
2852 T: Upcast<TyCtxt<'tcx>, ty::Predicate<'tcx>>,
2853 {
2854 let tcx = self.tcx;
2855 let predicate = predicate.upcast(tcx);
2856 let suggest_remove_deref = |err: &mut Diag<'_, G>, expr: &hir::Expr<'_>| {
2857 if let Some(pred) = predicate.as_trait_clause()
2858 && tcx.is_lang_item(pred.def_id(), LangItem::Sized)
2859 && let hir::ExprKind::Unary(hir::UnOp::Deref, inner) = expr.kind
2860 {
2861 err.span_suggestion_verbose(
2862 expr.span.until(inner.span),
2863 "references are always `Sized`, even if they point to unsized data; consider \
2864 not dereferencing the expression",
2865 String::new(),
2866 Applicability::MaybeIncorrect,
2867 );
2868 }
2869 };
2870 match *cause_code {
2871 ObligationCauseCode::ExprAssignable
2872 | ObligationCauseCode::MatchExpressionArm { .. }
2873 | ObligationCauseCode::Pattern { .. }
2874 | ObligationCauseCode::IfExpression { .. }
2875 | ObligationCauseCode::IfExpressionWithNoElse
2876 | ObligationCauseCode::MainFunctionType
2877 | ObligationCauseCode::LangFunctionType(_)
2878 | ObligationCauseCode::IntrinsicType
2879 | ObligationCauseCode::MethodReceiver
2880 | ObligationCauseCode::ReturnNoExpression
2881 | ObligationCauseCode::Misc
2882 | ObligationCauseCode::WellFormed(..)
2883 | ObligationCauseCode::MatchImpl(..)
2884 | ObligationCauseCode::ReturnValue(_)
2885 | ObligationCauseCode::BlockTailExpression(..)
2886 | ObligationCauseCode::AwaitableExpr(_)
2887 | ObligationCauseCode::ForLoopIterator
2888 | ObligationCauseCode::QuestionMark
2889 | ObligationCauseCode::CheckAssociatedTypeBounds { .. }
2890 | ObligationCauseCode::LetElse
2891 | ObligationCauseCode::UnOp { .. }
2892 | ObligationCauseCode::BinOp { .. }
2893 | ObligationCauseCode::AscribeUserTypeProvePredicate(..)
2894 | ObligationCauseCode::AlwaysApplicableImpl
2895 | ObligationCauseCode::ConstParam(_)
2896 | ObligationCauseCode::ReferenceOutlivesReferent(..)
2897 | ObligationCauseCode::ObjectTypeBound(..) => {}
2898 ObligationCauseCode::RustCall => {
2899 if let Some(pred) = predicate.as_trait_clause()
2900 && tcx.is_lang_item(pred.def_id(), LangItem::Sized)
2901 {
2902 err.note("argument required to be sized due to `extern \"rust-call\"` ABI");
2903 }
2904 }
2905 ObligationCauseCode::SliceOrArrayElem => {
2906 err.note("slice and array elements must have `Sized` type");
2907 }
2908 ObligationCauseCode::ArrayLen(array_ty) => {
2909 err.note(::alloc::__export::must_use({
::alloc::fmt::format(format_args!("the length of array `{0}` must be type `usize`",
array_ty))
})format!("the length of array `{array_ty}` must be type `usize`"));
2910 }
2911 ObligationCauseCode::TupleElem => {
2912 err.note("only the last element of a tuple may have a dynamically sized type");
2913 }
2914 ObligationCauseCode::DynCompatible(span) => {
2915 err.multipart_suggestion(
2916 "you might have meant to use `Self` to refer to the implementing type",
2917 <[_]>::into_vec(::alloc::boxed::box_new([(span, "Self".into())]))vec![(span, "Self".into())],
2918 Applicability::MachineApplicable,
2919 );
2920 }
2921 ObligationCauseCode::WhereClause(item_def_id, span)
2922 | ObligationCauseCode::WhereClauseInExpr(item_def_id, span, ..)
2923 | ObligationCauseCode::HostEffectInExpr(item_def_id, span, ..)
2924 if !span.is_dummy() =>
2925 {
2926 if let ObligationCauseCode::WhereClauseInExpr(_, _, hir_id, pos) = &cause_code {
2927 if let Node::Expr(expr) = tcx.parent_hir_node(*hir_id)
2928 && let hir::ExprKind::Call(_, args) = expr.kind
2929 && let Some(expr) = args.get(*pos)
2930 {
2931 suggest_remove_deref(err, &expr);
2932 } else if let Node::Expr(expr) = self.tcx.hir_node(*hir_id)
2933 && let hir::ExprKind::MethodCall(_, _, args, _) = expr.kind
2934 && let Some(expr) = args.get(*pos)
2935 {
2936 suggest_remove_deref(err, &expr);
2937 }
2938 }
2939 let item_name = tcx.def_path_str(item_def_id);
2940 let short_item_name = { let _guard = ForceTrimmedGuard::new(); tcx.def_path_str(item_def_id) }with_forced_trimmed_paths!(tcx.def_path_str(item_def_id));
2941 let mut multispan = MultiSpan::from(span);
2942 let sm = tcx.sess.source_map();
2943 if let Some(ident) = tcx.opt_item_ident(item_def_id) {
2944 let same_line =
2945 match (sm.lookup_line(ident.span.hi()), sm.lookup_line(span.lo())) {
2946 (Ok(l), Ok(r)) => l.line == r.line,
2947 _ => true,
2948 };
2949 if ident.span.is_visible(sm) && !ident.span.overlaps(span) && !same_line {
2950 multispan.push_span_label(
2951 ident.span,
2952 ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("required by a bound in this {0}",
tcx.def_kind(item_def_id).descr(item_def_id)))
})format!(
2953 "required by a bound in this {}",
2954 tcx.def_kind(item_def_id).descr(item_def_id)
2955 ),
2956 );
2957 }
2958 }
2959 let mut a = "a";
2960 let mut this = "this bound";
2961 let mut note = None;
2962 let mut help = None;
2963 if let ty::PredicateKind::Clause(clause) = predicate.kind().skip_binder() {
2964 match clause {
2965 ty::ClauseKind::Trait(trait_pred) => {
2966 let def_id = trait_pred.def_id();
2967 let visible_item = if let Some(local) = def_id.as_local() {
2968 let ty = trait_pred.self_ty();
2969 if let ty::Adt(adt, _) = ty.kind() {
2973 let visibilities = &tcx.resolutions(()).effective_visibilities;
2974 visibilities.effective_vis(local).is_none_or(|v| {
2975 v.at_level(Level::Reexported)
2976 .is_accessible_from(adt.did(), tcx)
2977 })
2978 } else {
2979 true
2981 }
2982 } else {
2983 tcx.visible_parent_map(()).get(&def_id).is_some()
2985 };
2986 if tcx.is_lang_item(def_id, LangItem::Sized) {
2987 if tcx
2989 .generics_of(item_def_id)
2990 .own_params
2991 .iter()
2992 .any(|param| tcx.def_span(param.def_id) == span)
2993 {
2994 a = "an implicit `Sized`";
2995 this =
2996 "the implicit `Sized` requirement on this type parameter";
2997 }
2998 if let Some(hir::Node::TraitItem(hir::TraitItem {
2999 generics,
3000 kind: hir::TraitItemKind::Type(bounds, None),
3001 ..
3002 })) = tcx.hir_get_if_local(item_def_id)
3003 && !bounds.iter()
3005 .filter_map(|bound| bound.trait_ref())
3006 .any(|tr| tr.trait_def_id().is_some_and(|def_id| tcx.is_lang_item(def_id, LangItem::Sized)))
3007 {
3008 let (span, separator) = if let [.., last] = bounds {
3009 (last.span().shrink_to_hi(), " +")
3010 } else {
3011 (generics.span.shrink_to_hi(), ":")
3012 };
3013 err.span_suggestion_verbose(
3014 span,
3015 "consider relaxing the implicit `Sized` restriction",
3016 ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("{0} ?Sized", separator))
})format!("{separator} ?Sized"),
3017 Applicability::MachineApplicable,
3018 );
3019 }
3020 }
3021 if let DefKind::Trait = tcx.def_kind(item_def_id)
3022 && !visible_item
3023 {
3024 note = Some(::alloc::__export::must_use({
::alloc::fmt::format(format_args!("`{1}` is a \"sealed trait\", because to implement it you also need to implement `{0}`, which is not accessible; this is usually done to force you to use one of the provided types that already implement it",
{
let _guard = NoTrimmedGuard::new();
tcx.def_path_str(def_id)
}, short_item_name))
})format!(
3025 "`{short_item_name}` is a \"sealed trait\", because to implement it \
3026 you also need to implement `{}`, which is not accessible; this is \
3027 usually done to force you to use one of the provided types that \
3028 already implement it",
3029 with_no_trimmed_paths!(tcx.def_path_str(def_id)),
3030 ));
3031 let impls_of = tcx.trait_impls_of(def_id);
3032 let impls = impls_of
3033 .non_blanket_impls()
3034 .values()
3035 .flatten()
3036 .chain(impls_of.blanket_impls().iter())
3037 .collect::<Vec<_>>();
3038 if !impls.is_empty() {
3039 let len = impls.len();
3040 let mut types = impls
3041 .iter()
3042 .map(|t| {
3043 {
let _guard = NoTrimmedGuard::new();
::alloc::__export::must_use({
::alloc::fmt::format(format_args!(" {0}",
tcx.type_of(*t).instantiate_identity()))
})
}with_no_trimmed_paths!(format!(
3044 " {}",
3045 tcx.type_of(*t).instantiate_identity(),
3046 ))
3047 })
3048 .collect::<Vec<_>>();
3049 let post = if types.len() > 9 {
3050 types.truncate(8);
3051 ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("\nand {0} others", len - 8))
})format!("\nand {} others", len - 8)
3052 } else {
3053 String::new()
3054 };
3055 help = Some(::alloc::__export::must_use({
::alloc::fmt::format(format_args!("the following type{0} implement{1} the trait:\n{2}{3}",
if len == 1 { "" } else { "s" },
if len == 1 { "s" } else { "" }, types.join("\n"), post))
})format!(
3056 "the following type{} implement{} the trait:\n{}{post}",
3057 pluralize!(len),
3058 if len == 1 { "s" } else { "" },
3059 types.join("\n"),
3060 ));
3061 }
3062 }
3063 }
3064 ty::ClauseKind::ConstArgHasType(..) => {
3065 let descr =
3066 ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("required by a const generic parameter in `{0}`",
item_name))
})format!("required by a const generic parameter in `{item_name}`");
3067 if span.is_visible(sm) {
3068 let msg = ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("required by this const generic parameter in `{0}`",
short_item_name))
})format!(
3069 "required by this const generic parameter in `{short_item_name}`"
3070 );
3071 multispan.push_span_label(span, msg);
3072 err.span_note(multispan, descr);
3073 } else {
3074 err.span_note(tcx.def_span(item_def_id), descr);
3075 }
3076 return;
3077 }
3078 _ => (),
3079 }
3080 }
3081
3082 let is_in_fmt_lit = if let Some(s) = err.span.primary_span() {
3085 #[allow(non_exhaustive_omitted_patterns)] match s.desugaring_kind() {
Some(DesugaringKind::FormatLiteral { .. }) => true,
_ => false,
}matches!(s.desugaring_kind(), Some(DesugaringKind::FormatLiteral { .. }))
3086 } else {
3087 false
3088 };
3089 if !is_in_fmt_lit {
3090 let descr = ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("required by {0} bound in `{1}`", a,
item_name))
})format!("required by {a} bound in `{item_name}`");
3091 if span.is_visible(sm) {
3092 let msg = ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("required by {0} in `{1}`", this,
short_item_name))
})format!("required by {this} in `{short_item_name}`");
3093 multispan.push_span_label(span, msg);
3094 err.span_note(multispan, descr);
3095 } else {
3096 err.span_note(tcx.def_span(item_def_id), descr);
3097 }
3098 }
3099 if let Some(note) = note {
3100 err.note(note);
3101 }
3102 if let Some(help) = help {
3103 err.help(help);
3104 }
3105 }
3106 ObligationCauseCode::WhereClause(..)
3107 | ObligationCauseCode::WhereClauseInExpr(..)
3108 | ObligationCauseCode::HostEffectInExpr(..) => {
3109 }
3112 ObligationCauseCode::OpaqueTypeBound(span, definition_def_id) => {
3113 err.span_note(span, "required by a bound in an opaque type");
3114 if let Some(definition_def_id) = definition_def_id
3115 && self.tcx.typeck(definition_def_id).coroutine_stalled_predicates.is_empty()
3119 {
3120 err.span_note(
3123 tcx.def_span(definition_def_id),
3124 "this definition site has more where clauses than the opaque type",
3125 );
3126 }
3127 }
3128 ObligationCauseCode::Coercion { source, target } => {
3129 let source =
3130 tcx.short_string(self.resolve_vars_if_possible(source), err.long_ty_path());
3131 let target =
3132 tcx.short_string(self.resolve_vars_if_possible(target), err.long_ty_path());
3133 err.note({
let _guard = ForceTrimmedGuard::new();
::alloc::__export::must_use({
::alloc::fmt::format(format_args!("required for the cast from `{0}` to `{1}`",
source, target))
})
}with_forced_trimmed_paths!(format!(
3134 "required for the cast from `{source}` to `{target}`",
3135 )));
3136 }
3137 ObligationCauseCode::RepeatElementCopy { is_constable, elt_span } => {
3138 err.note(
3139 "the `Copy` trait is required because this value will be copied for each element of the array",
3140 );
3141 let sm = tcx.sess.source_map();
3142 if #[allow(non_exhaustive_omitted_patterns)] match is_constable {
IsConstable::Fn | IsConstable::Ctor => true,
_ => false,
}matches!(is_constable, IsConstable::Fn | IsConstable::Ctor)
3143 && let Ok(_) = sm.span_to_snippet(elt_span)
3144 {
3145 err.multipart_suggestion(
3146 "create an inline `const` block",
3147 <[_]>::into_vec(::alloc::boxed::box_new([(elt_span.shrink_to_lo(),
"const { ".to_string()),
(elt_span.shrink_to_hi(), " }".to_string())]))vec![
3148 (elt_span.shrink_to_lo(), "const { ".to_string()),
3149 (elt_span.shrink_to_hi(), " }".to_string()),
3150 ],
3151 Applicability::MachineApplicable,
3152 );
3153 } else {
3154 err.help("consider using `core::array::from_fn` to initialize the array");
3156 err.help("see https://doc.rust-lang.org/stable/std/array/fn.from_fn.html for more information");
3157 }
3158 }
3159 ObligationCauseCode::VariableType(hir_id) => {
3160 if let Some(typeck_results) = &self.typeck_results
3161 && let Some(ty) = typeck_results.node_type_opt(hir_id)
3162 && let ty::Error(_) = ty.kind()
3163 {
3164 err.note(::alloc::__export::must_use({
::alloc::fmt::format(format_args!("`{0}` isn\'t satisfied, but the type of this pattern is `{{type error}}`",
predicate))
})format!(
3165 "`{predicate}` isn't satisfied, but the type of this pattern is \
3166 `{{type error}}`",
3167 ));
3168 err.downgrade_to_delayed_bug();
3169 }
3170 let mut local = true;
3171 match tcx.parent_hir_node(hir_id) {
3172 Node::LetStmt(hir::LetStmt { ty: Some(ty), .. }) => {
3173 err.span_suggestion_verbose(
3174 ty.span.shrink_to_lo(),
3175 "consider borrowing here",
3176 "&",
3177 Applicability::MachineApplicable,
3178 );
3179 }
3180 Node::LetStmt(hir::LetStmt {
3181 init: Some(hir::Expr { kind: hir::ExprKind::Index(..), span, .. }),
3182 ..
3183 }) => {
3184 err.span_suggestion_verbose(
3188 span.shrink_to_lo(),
3189 "consider borrowing here",
3190 "&",
3191 Applicability::MachineApplicable,
3192 );
3193 }
3194 Node::LetStmt(hir::LetStmt { init: Some(expr), .. }) => {
3195 suggest_remove_deref(err, &expr);
3198 }
3199 Node::Param(param) => {
3200 err.span_suggestion_verbose(
3201 param.ty_span.shrink_to_lo(),
3202 "function arguments must have a statically known size, borrowed types \
3203 always have a known size",
3204 "&",
3205 Applicability::MachineApplicable,
3206 );
3207 local = false;
3208 }
3209 _ => {}
3210 }
3211 if local {
3212 err.note("all local variables must have a statically known size");
3213 }
3214 }
3215 ObligationCauseCode::SizedArgumentType(hir_id) => {
3216 let mut ty = None;
3217 let borrowed_msg = "function arguments must have a statically known size, borrowed \
3218 types always have a known size";
3219 if let Some(hir_id) = hir_id
3220 && let hir::Node::Param(param) = self.tcx.hir_node(hir_id)
3221 && let Some(decl) = self.tcx.parent_hir_node(hir_id).fn_decl()
3222 && let Some(t) = decl.inputs.iter().find(|t| param.ty_span.contains(t.span))
3223 {
3224 ty = Some(t);
3232 } else if let Some(hir_id) = hir_id
3233 && let hir::Node::Ty(t) = self.tcx.hir_node(hir_id)
3234 {
3235 ty = Some(t);
3236 }
3237 if let Some(ty) = ty {
3238 match ty.kind {
3239 hir::TyKind::TraitObject(traits, _) => {
3240 let (span, kw) = match traits {
3241 [first, ..] if first.span.lo() == ty.span.lo() => {
3242 (ty.span.shrink_to_lo(), "dyn ")
3244 }
3245 [first, ..] => (ty.span.until(first.span), ""),
3246 [] => ::rustc_middle::util::bug::span_bug_fmt(ty.span,
format_args!("trait object with no traits: {0:?}", ty))span_bug!(ty.span, "trait object with no traits: {ty:?}"),
3247 };
3248 let needs_parens = traits.len() != 1;
3249 if let Some(hir_id) = hir_id
3251 && #[allow(non_exhaustive_omitted_patterns)] match self.tcx.parent_hir_node(hir_id)
{
hir::Node::Item(hir::Item { kind: hir::ItemKind::Fn { .. }, .. }) => true,
_ => false,
}matches!(
3252 self.tcx.parent_hir_node(hir_id),
3253 hir::Node::Item(hir::Item {
3254 kind: hir::ItemKind::Fn { .. },
3255 ..
3256 })
3257 )
3258 {
3259 err.span_suggestion_verbose(
3260 span,
3261 "you can use `impl Trait` as the argument type",
3262 "impl ",
3263 Applicability::MaybeIncorrect,
3264 );
3265 }
3266 let sugg = if !needs_parens {
3267 <[_]>::into_vec(::alloc::boxed::box_new([(span.shrink_to_lo(),
::alloc::__export::must_use({
::alloc::fmt::format(format_args!("&{0}", kw))
}))]))vec![(span.shrink_to_lo(), format!("&{kw}"))]
3268 } else {
3269 <[_]>::into_vec(::alloc::boxed::box_new([(span.shrink_to_lo(),
::alloc::__export::must_use({
::alloc::fmt::format(format_args!("&({0}", kw))
})), (ty.span.shrink_to_hi(), ")".to_string())]))vec![
3270 (span.shrink_to_lo(), format!("&({kw}")),
3271 (ty.span.shrink_to_hi(), ")".to_string()),
3272 ]
3273 };
3274 err.multipart_suggestion_verbose(
3275 borrowed_msg,
3276 sugg,
3277 Applicability::MachineApplicable,
3278 );
3279 }
3280 hir::TyKind::Slice(_ty) => {
3281 err.span_suggestion_verbose(
3282 ty.span.shrink_to_lo(),
3283 "function arguments must have a statically known size, borrowed \
3284 slices always have a known size",
3285 "&",
3286 Applicability::MachineApplicable,
3287 );
3288 }
3289 hir::TyKind::Path(_) => {
3290 err.span_suggestion_verbose(
3291 ty.span.shrink_to_lo(),
3292 borrowed_msg,
3293 "&",
3294 Applicability::MachineApplicable,
3295 );
3296 }
3297 _ => {}
3298 }
3299 } else {
3300 err.note("all function arguments must have a statically known size");
3301 }
3302 if tcx.sess.opts.unstable_features.is_nightly_build()
3303 && !tcx.features().unsized_fn_params()
3304 {
3305 err.help("unsized fn params are gated as an unstable feature");
3306 }
3307 }
3308 ObligationCauseCode::SizedReturnType | ObligationCauseCode::SizedCallReturnType => {
3309 err.note("the return type of a function must have a statically known size");
3310 }
3311 ObligationCauseCode::SizedYieldType => {
3312 err.note("the yield type of a coroutine must have a statically known size");
3313 }
3314 ObligationCauseCode::AssignmentLhsSized => {
3315 err.note("the left-hand-side of an assignment must have a statically known size");
3316 }
3317 ObligationCauseCode::TupleInitializerSized => {
3318 err.note("tuples must have a statically known size to be initialized");
3319 }
3320 ObligationCauseCode::StructInitializerSized => {
3321 err.note("structs must have a statically known size to be initialized");
3322 }
3323 ObligationCauseCode::FieldSized { adt_kind: ref item, last, span } => {
3324 match *item {
3325 AdtKind::Struct => {
3326 if last {
3327 err.note(
3328 "the last field of a packed struct may only have a \
3329 dynamically sized type if it does not need drop to be run",
3330 );
3331 } else {
3332 err.note(
3333 "only the last field of a struct may have a dynamically sized type",
3334 );
3335 }
3336 }
3337 AdtKind::Union => {
3338 err.note("no field of a union may have a dynamically sized type");
3339 }
3340 AdtKind::Enum => {
3341 err.note("no field of an enum variant may have a dynamically sized type");
3342 }
3343 }
3344 err.help("change the field's type to have a statically known size");
3345 err.span_suggestion_verbose(
3346 span.shrink_to_lo(),
3347 "borrowed types always have a statically known size",
3348 "&",
3349 Applicability::MachineApplicable,
3350 );
3351 err.multipart_suggestion_verbose(
3352 "the `Box` type always has a statically known size and allocates its contents \
3353 in the heap",
3354 <[_]>::into_vec(::alloc::boxed::box_new([(span.shrink_to_lo(),
"Box<".to_string()),
(span.shrink_to_hi(), ">".to_string())]))vec![
3355 (span.shrink_to_lo(), "Box<".to_string()),
3356 (span.shrink_to_hi(), ">".to_string()),
3357 ],
3358 Applicability::MachineApplicable,
3359 );
3360 }
3361 ObligationCauseCode::SizedConstOrStatic => {
3362 err.note("statics and constants must have a statically known size");
3363 }
3364 ObligationCauseCode::InlineAsmSized => {
3365 err.note("all inline asm arguments must have a statically known size");
3366 }
3367 ObligationCauseCode::SizedClosureCapture(closure_def_id) => {
3368 err.note(
3369 "all values captured by value by a closure must have a statically known size",
3370 );
3371 let hir::ExprKind::Closure(closure) =
3372 tcx.hir_node_by_def_id(closure_def_id).expect_expr().kind
3373 else {
3374 ::rustc_middle::util::bug::bug_fmt(format_args!("expected closure in SizedClosureCapture obligation"));bug!("expected closure in SizedClosureCapture obligation");
3375 };
3376 if let hir::CaptureBy::Value { .. } = closure.capture_clause
3377 && let Some(span) = closure.fn_arg_span
3378 {
3379 err.span_label(span, "this closure captures all values by move");
3380 }
3381 }
3382 ObligationCauseCode::SizedCoroutineInterior(coroutine_def_id) => {
3383 let what = match tcx.coroutine_kind(coroutine_def_id) {
3384 None
3385 | Some(hir::CoroutineKind::Coroutine(_))
3386 | Some(hir::CoroutineKind::Desugared(hir::CoroutineDesugaring::Gen, _)) => {
3387 "yield"
3388 }
3389 Some(hir::CoroutineKind::Desugared(hir::CoroutineDesugaring::Async, _)) => {
3390 "await"
3391 }
3392 Some(hir::CoroutineKind::Desugared(hir::CoroutineDesugaring::AsyncGen, _)) => {
3393 "yield`/`await"
3394 }
3395 };
3396 err.note(::alloc::__export::must_use({
::alloc::fmt::format(format_args!("all values live across `{0}` must have a statically known size",
what))
})format!(
3397 "all values live across `{what}` must have a statically known size"
3398 ));
3399 }
3400 ObligationCauseCode::SharedStatic => {
3401 err.note("shared static variables must have a type that implements `Sync`");
3402 }
3403 ObligationCauseCode::BuiltinDerived(ref data) => {
3404 let parent_trait_ref = self.resolve_vars_if_possible(data.parent_trait_pred);
3405 let ty = parent_trait_ref.skip_binder().self_ty();
3406 if parent_trait_ref.references_error() {
3407 err.downgrade_to_delayed_bug();
3410 return;
3411 }
3412
3413 let is_upvar_tys_infer_tuple = if !#[allow(non_exhaustive_omitted_patterns)] match ty.kind() {
ty::Tuple(..) => true,
_ => false,
}matches!(ty.kind(), ty::Tuple(..)) {
3416 false
3417 } else if let ObligationCauseCode::BuiltinDerived(data) = &*data.parent_code {
3418 let parent_trait_ref = self.resolve_vars_if_possible(data.parent_trait_pred);
3419 let nested_ty = parent_trait_ref.skip_binder().self_ty();
3420 #[allow(non_exhaustive_omitted_patterns)] match nested_ty.kind() {
ty::Coroutine(..) => true,
_ => false,
}matches!(nested_ty.kind(), ty::Coroutine(..))
3421 || #[allow(non_exhaustive_omitted_patterns)] match nested_ty.kind() {
ty::Closure(..) => true,
_ => false,
}matches!(nested_ty.kind(), ty::Closure(..))
3422 } else {
3423 false
3424 };
3425
3426 let is_builtin_async_fn_trait =
3427 tcx.async_fn_trait_kind_from_def_id(data.parent_trait_pred.def_id()).is_some();
3428
3429 if !is_upvar_tys_infer_tuple && !is_builtin_async_fn_trait {
3430 let mut msg = || {
3431 let ty_str = tcx.short_string(ty, err.long_ty_path());
3432 ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("required because it appears within the type `{0}`",
ty_str))
})format!("required because it appears within the type `{ty_str}`")
3433 };
3434 match ty.kind() {
3435 ty::Adt(def, _) => {
3436 let msg = msg();
3437 match tcx.opt_item_ident(def.did()) {
3438 Some(ident) => {
3439 err.span_note(ident.span, msg);
3440 }
3441 None => {
3442 err.note(msg);
3443 }
3444 }
3445 }
3446 ty::Alias(ty::Opaque, ty::AliasTy { def_id, .. }) => {
3447 let is_future = tcx.ty_is_opaque_future(ty);
3450 {
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/traits/suggestions.rs:3450",
"rustc_trait_selection::error_reporting::traits::suggestions",
::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs"),
::tracing_core::__macro_support::Option::Some(3450u32),
::tracing_core::__macro_support::Option::Some("rustc_trait_selection::error_reporting::traits::suggestions"),
::tracing_core::field::FieldSet::new(&["message",
"obligated_types", "is_future"],
::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!("note_obligation_cause_code: check for async fn")
as &dyn Value)),
(&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
::tracing::__macro_support::Option::Some(&debug(&obligated_types)
as &dyn Value)),
(&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
::tracing::__macro_support::Option::Some(&debug(&is_future)
as &dyn Value))])
});
} else { ; }
};debug!(
3451 ?obligated_types,
3452 ?is_future,
3453 "note_obligation_cause_code: check for async fn"
3454 );
3455 if is_future
3456 && obligated_types.last().is_some_and(|ty| match ty.kind() {
3457 ty::Coroutine(last_def_id, ..) => {
3458 tcx.coroutine_is_async(*last_def_id)
3459 }
3460 _ => false,
3461 })
3462 {
3463 } else {
3465 let msg = msg();
3466 err.span_note(tcx.def_span(def_id), msg);
3467 }
3468 }
3469 ty::Coroutine(def_id, _) => {
3470 let sp = tcx.def_span(def_id);
3471
3472 let kind = tcx.coroutine_kind(def_id).unwrap();
3474 err.span_note(
3475 sp,
3476 {
let _guard = ForceTrimmedGuard::new();
::alloc::__export::must_use({
::alloc::fmt::format(format_args!("required because it\'s used within this {0:#}",
kind))
})
}with_forced_trimmed_paths!(format!(
3477 "required because it's used within this {kind:#}",
3478 )),
3479 );
3480 }
3481 ty::CoroutineWitness(..) => {
3482 }
3485 ty::Closure(def_id, _) | ty::CoroutineClosure(def_id, _) => {
3486 err.span_note(
3487 tcx.def_span(def_id),
3488 "required because it's used within this closure",
3489 );
3490 }
3491 ty::Str => {
3492 err.note("`str` is considered to contain a `[u8]` slice for auto trait purposes");
3493 }
3494 _ => {
3495 let msg = msg();
3496 err.note(msg);
3497 }
3498 };
3499 }
3500
3501 obligated_types.push(ty);
3502
3503 let parent_predicate = parent_trait_ref;
3504 if !self.is_recursive_obligation(obligated_types, &data.parent_code) {
3505 ensure_sufficient_stack(|| {
3507 self.note_obligation_cause_code(
3508 body_id,
3509 err,
3510 parent_predicate,
3511 param_env,
3512 &data.parent_code,
3513 obligated_types,
3514 seen_requirements,
3515 )
3516 });
3517 } else {
3518 ensure_sufficient_stack(|| {
3519 self.note_obligation_cause_code(
3520 body_id,
3521 err,
3522 parent_predicate,
3523 param_env,
3524 cause_code.peel_derives(),
3525 obligated_types,
3526 seen_requirements,
3527 )
3528 });
3529 }
3530 }
3531 ObligationCauseCode::ImplDerived(ref data) => {
3532 let mut parent_trait_pred =
3533 self.resolve_vars_if_possible(data.derived.parent_trait_pred);
3534 let parent_def_id = parent_trait_pred.def_id();
3535 if tcx.is_diagnostic_item(sym::FromResidual, parent_def_id)
3536 && !tcx.features().enabled(sym::try_trait_v2)
3537 {
3538 return;
3542 }
3543 if tcx.is_diagnostic_item(sym::PinDerefMutHelper, parent_def_id) {
3544 let parent_predicate =
3545 self.resolve_vars_if_possible(data.derived.parent_trait_pred);
3546
3547 ensure_sufficient_stack(|| {
3549 self.note_obligation_cause_code(
3550 body_id,
3551 err,
3552 parent_predicate,
3553 param_env,
3554 &data.derived.parent_code,
3555 obligated_types,
3556 seen_requirements,
3557 )
3558 });
3559 return;
3560 }
3561 let self_ty_str =
3562 tcx.short_string(parent_trait_pred.skip_binder().self_ty(), err.long_ty_path());
3563 let trait_name = tcx.short_string(
3564 parent_trait_pred.print_modifiers_and_trait_path(),
3565 err.long_ty_path(),
3566 );
3567 let msg = ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("required for `{0}` to implement `{1}`",
self_ty_str, trait_name))
})format!("required for `{self_ty_str}` to implement `{trait_name}`");
3568 let mut is_auto_trait = false;
3569 match tcx.hir_get_if_local(data.impl_or_alias_def_id) {
3570 Some(Node::Item(hir::Item {
3571 kind: hir::ItemKind::Trait(_, is_auto, _, ident, ..),
3572 ..
3573 })) => {
3574 is_auto_trait = #[allow(non_exhaustive_omitted_patterns)] match is_auto {
hir::IsAuto::Yes => true,
_ => false,
}matches!(is_auto, hir::IsAuto::Yes);
3577 err.span_note(ident.span, msg);
3578 }
3579 Some(Node::Item(hir::Item {
3580 kind: hir::ItemKind::Impl(hir::Impl { of_trait, self_ty, generics, .. }),
3581 ..
3582 })) => {
3583 let mut spans = Vec::with_capacity(2);
3584 if let Some(of_trait) = of_trait {
3585 spans.push(of_trait.trait_ref.path.span);
3586 }
3587 spans.push(self_ty.span);
3588 let mut spans: MultiSpan = spans.into();
3589 if #[allow(non_exhaustive_omitted_patterns)] match self_ty.span.ctxt().outer_expn_data().kind
{
ExpnKind::Macro(MacroKind::Derive, _) => true,
_ => false,
}matches!(
3590 self_ty.span.ctxt().outer_expn_data().kind,
3591 ExpnKind::Macro(MacroKind::Derive, _)
3592 ) || #[allow(non_exhaustive_omitted_patterns)] match of_trait.map(|t|
t.trait_ref.path.span.ctxt().outer_expn_data().kind) {
Some(ExpnKind::Macro(MacroKind::Derive, _)) => true,
_ => false,
}matches!(
3593 of_trait.map(|t| t.trait_ref.path.span.ctxt().outer_expn_data().kind),
3594 Some(ExpnKind::Macro(MacroKind::Derive, _))
3595 ) {
3596 spans.push_span_label(
3597 data.span,
3598 "unsatisfied trait bound introduced in this `derive` macro",
3599 );
3600 } else if !data.span.is_dummy() && !data.span.overlaps(self_ty.span) {
3601 if let Some(pred) = predicate.as_trait_clause()
3604 && self.tcx.is_lang_item(pred.def_id(), LangItem::Sized)
3605 && self
3606 .tcx
3607 .generics_of(data.impl_or_alias_def_id)
3608 .own_params
3609 .iter()
3610 .any(|param| self.tcx.def_span(param.def_id) == data.span)
3611 {
3612 spans.push_span_label(
3613 data.span,
3614 "unsatisfied trait bound implicitly introduced here",
3615 );
3616 } else {
3617 spans.push_span_label(
3618 data.span,
3619 "unsatisfied trait bound introduced here",
3620 );
3621 }
3622 }
3623 err.span_note(spans, msg);
3624 point_at_assoc_type_restriction(
3625 tcx,
3626 err,
3627 &self_ty_str,
3628 &trait_name,
3629 predicate,
3630 &generics,
3631 &data,
3632 );
3633 }
3634 _ => {
3635 err.note(msg);
3636 }
3637 };
3638
3639 let mut parent_predicate = parent_trait_pred;
3640 let mut data = &data.derived;
3641 let mut count = 0;
3642 seen_requirements.insert(parent_def_id);
3643 if is_auto_trait {
3644 while let ObligationCauseCode::BuiltinDerived(derived) = &*data.parent_code {
3647 let child_trait_ref =
3648 self.resolve_vars_if_possible(derived.parent_trait_pred);
3649 let child_def_id = child_trait_ref.def_id();
3650 if seen_requirements.insert(child_def_id) {
3651 break;
3652 }
3653 data = derived;
3654 parent_predicate = child_trait_ref.upcast(tcx);
3655 parent_trait_pred = child_trait_ref;
3656 }
3657 }
3658 while let ObligationCauseCode::ImplDerived(child) = &*data.parent_code {
3659 let child_trait_pred =
3661 self.resolve_vars_if_possible(child.derived.parent_trait_pred);
3662 let child_def_id = child_trait_pred.def_id();
3663 if seen_requirements.insert(child_def_id) {
3664 break;
3665 }
3666 count += 1;
3667 data = &child.derived;
3668 parent_predicate = child_trait_pred.upcast(tcx);
3669 parent_trait_pred = child_trait_pred;
3670 }
3671 if count > 0 {
3672 err.note(::alloc::__export::must_use({
::alloc::fmt::format(format_args!("{0} redundant requirement{1} hidden",
count, if count == 1 { "" } else { "s" }))
})format!(
3673 "{} redundant requirement{} hidden",
3674 count,
3675 pluralize!(count)
3676 ));
3677 let self_ty = tcx.short_string(
3678 parent_trait_pred.skip_binder().self_ty(),
3679 err.long_ty_path(),
3680 );
3681 let trait_path = tcx.short_string(
3682 parent_trait_pred.print_modifiers_and_trait_path(),
3683 err.long_ty_path(),
3684 );
3685 err.note(::alloc::__export::must_use({
::alloc::fmt::format(format_args!("required for `{0}` to implement `{1}`",
self_ty, trait_path))
})format!("required for `{self_ty}` to implement `{trait_path}`"));
3686 }
3687 ensure_sufficient_stack(|| {
3689 self.note_obligation_cause_code(
3690 body_id,
3691 err,
3692 parent_predicate,
3693 param_env,
3694 &data.parent_code,
3695 obligated_types,
3696 seen_requirements,
3697 )
3698 });
3699 }
3700 ObligationCauseCode::ImplDerivedHost(ref data) => {
3701 let self_ty = tcx.short_string(
3702 self.resolve_vars_if_possible(data.derived.parent_host_pred.self_ty()),
3703 err.long_ty_path(),
3704 );
3705 let trait_path = tcx.short_string(
3706 data.derived
3707 .parent_host_pred
3708 .map_bound(|pred| pred.trait_ref)
3709 .print_only_trait_path(),
3710 err.long_ty_path(),
3711 );
3712 let msg = ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("required for `{1}` to implement `{0} {2}`",
data.derived.parent_host_pred.skip_binder().constness,
self_ty, trait_path))
})format!(
3713 "required for `{self_ty}` to implement `{} {trait_path}`",
3714 data.derived.parent_host_pred.skip_binder().constness,
3715 );
3716 match tcx.hir_get_if_local(data.impl_def_id) {
3717 Some(Node::Item(hir::Item {
3718 kind: hir::ItemKind::Impl(hir::Impl { of_trait, self_ty, .. }),
3719 ..
3720 })) => {
3721 let mut spans = <[_]>::into_vec(::alloc::boxed::box_new([self_ty.span]))vec![self_ty.span];
3722 spans.extend(of_trait.map(|t| t.trait_ref.path.span));
3723 let mut spans: MultiSpan = spans.into();
3724 spans.push_span_label(data.span, "unsatisfied trait bound introduced here");
3725 err.span_note(spans, msg);
3726 }
3727 _ => {
3728 err.note(msg);
3729 }
3730 }
3731 ensure_sufficient_stack(|| {
3732 self.note_obligation_cause_code(
3733 body_id,
3734 err,
3735 data.derived.parent_host_pred,
3736 param_env,
3737 &data.derived.parent_code,
3738 obligated_types,
3739 seen_requirements,
3740 )
3741 });
3742 }
3743 ObligationCauseCode::BuiltinDerivedHost(ref data) => {
3744 ensure_sufficient_stack(|| {
3745 self.note_obligation_cause_code(
3746 body_id,
3747 err,
3748 data.parent_host_pred,
3749 param_env,
3750 &data.parent_code,
3751 obligated_types,
3752 seen_requirements,
3753 )
3754 });
3755 }
3756 ObligationCauseCode::WellFormedDerived(ref data) => {
3757 let parent_trait_ref = self.resolve_vars_if_possible(data.parent_trait_pred);
3758 let parent_predicate = parent_trait_ref;
3759 ensure_sufficient_stack(|| {
3761 self.note_obligation_cause_code(
3762 body_id,
3763 err,
3764 parent_predicate,
3765 param_env,
3766 &data.parent_code,
3767 obligated_types,
3768 seen_requirements,
3769 )
3770 });
3771 }
3772 ObligationCauseCode::TypeAlias(ref nested, span, def_id) => {
3773 ensure_sufficient_stack(|| {
3775 self.note_obligation_cause_code(
3776 body_id,
3777 err,
3778 predicate,
3779 param_env,
3780 nested,
3781 obligated_types,
3782 seen_requirements,
3783 )
3784 });
3785 let mut multispan = MultiSpan::from(span);
3786 multispan.push_span_label(span, "required by this bound");
3787 err.span_note(
3788 multispan,
3789 ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("required by a bound on the type alias `{0}`",
tcx.item_name(def_id)))
})format!("required by a bound on the type alias `{}`", tcx.item_name(def_id)),
3790 );
3791 }
3792 ObligationCauseCode::FunctionArg {
3793 arg_hir_id, call_hir_id, ref parent_code, ..
3794 } => {
3795 self.note_function_argument_obligation(
3796 body_id,
3797 err,
3798 arg_hir_id,
3799 parent_code,
3800 param_env,
3801 predicate,
3802 call_hir_id,
3803 );
3804 ensure_sufficient_stack(|| {
3805 self.note_obligation_cause_code(
3806 body_id,
3807 err,
3808 predicate,
3809 param_env,
3810 parent_code,
3811 obligated_types,
3812 seen_requirements,
3813 )
3814 });
3815 }
3816 ObligationCauseCode::CompareImplItem { trait_item_def_id, .. }
3819 if tcx.is_impl_trait_in_trait(trait_item_def_id) => {}
3820 ObligationCauseCode::CompareImplItem { trait_item_def_id, kind, .. } => {
3821 let item_name = tcx.item_name(trait_item_def_id);
3822 let msg = ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("the requirement `{0}` appears on the `impl`\'s {1} `{2}` but not on the corresponding trait\'s {1}",
predicate, kind, item_name))
})format!(
3823 "the requirement `{predicate}` appears on the `impl`'s {kind} \
3824 `{item_name}` but not on the corresponding trait's {kind}",
3825 );
3826 let sp = tcx
3827 .opt_item_ident(trait_item_def_id)
3828 .map(|i| i.span)
3829 .unwrap_or_else(|| tcx.def_span(trait_item_def_id));
3830 let mut assoc_span: MultiSpan = sp.into();
3831 assoc_span.push_span_label(
3832 sp,
3833 ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("this trait\'s {0} doesn\'t have the requirement `{1}`",
kind, predicate))
})format!("this trait's {kind} doesn't have the requirement `{predicate}`"),
3834 );
3835 if let Some(ident) = tcx
3836 .opt_associated_item(trait_item_def_id)
3837 .and_then(|i| tcx.opt_item_ident(i.container_id(tcx)))
3838 {
3839 assoc_span.push_span_label(ident.span, "in this trait");
3840 }
3841 err.span_note(assoc_span, msg);
3842 }
3843 ObligationCauseCode::TrivialBound => {
3844 err.help("see issue #48214");
3845 tcx.disabled_nightly_features(err, [(String::new(), sym::trivial_bounds)]);
3846 }
3847 ObligationCauseCode::OpaqueReturnType(expr_info) => {
3848 let (expr_ty, expr) = if let Some((expr_ty, hir_id)) = expr_info {
3849 let expr_ty = tcx.short_string(expr_ty, err.long_ty_path());
3850 let expr = tcx.hir_expect_expr(hir_id);
3851 (expr_ty, expr)
3852 } else if let Some(body_id) = tcx.hir_node_by_def_id(body_id).body_id()
3853 && let body = tcx.hir_body(body_id)
3854 && let hir::ExprKind::Block(block, _) = body.value.kind
3855 && let Some(expr) = block.expr
3856 && let Some(expr_ty) = self
3857 .typeck_results
3858 .as_ref()
3859 .and_then(|typeck| typeck.node_type_opt(expr.hir_id))
3860 && let Some(pred) = predicate.as_clause()
3861 && let ty::ClauseKind::Trait(pred) = pred.kind().skip_binder()
3862 && self.can_eq(param_env, pred.self_ty(), expr_ty)
3863 {
3864 let expr_ty = tcx.short_string(expr_ty, err.long_ty_path());
3865 (expr_ty, expr)
3866 } else {
3867 return;
3868 };
3869 err.span_label(
3870 expr.span,
3871 {
let _guard = ForceTrimmedGuard::new();
::alloc::__export::must_use({
::alloc::fmt::format(format_args!("return type was inferred to be `{0}` here",
expr_ty))
})
}with_forced_trimmed_paths!(format!(
3872 "return type was inferred to be `{expr_ty}` here",
3873 )),
3874 );
3875 suggest_remove_deref(err, &expr);
3876 }
3877 ObligationCauseCode::UnsizedNonPlaceExpr(span) => {
3878 err.span_note(
3879 span,
3880 "unsized values must be place expressions and cannot be put in temporaries",
3881 );
3882 }
3883 ObligationCauseCode::CompareEii { .. } => {
3884 {
::core::panicking::panic_fmt(format_args!("trait bounds on EII not yet supported "));
}panic!("trait bounds on EII not yet supported ")
3885 }
3886 }
3887 }
3888
3889 #[allow(clippy :: suspicious_else_formatting)]
{
let __tracing_attr_span;
let __tracing_attr_guard;
if ::tracing::Level::DEBUG <= ::tracing::level_filters::STATIC_MAX_LEVEL
&&
::tracing::Level::DEBUG <=
::tracing::level_filters::LevelFilter::current() ||
{ false } {
__tracing_attr_span =
{
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("suggest_await_before_try",
"rustc_trait_selection::error_reporting::traits::suggestions",
::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs"),
::tracing_core::__macro_support::Option::Some(3889u32),
::tracing_core::__macro_support::Option::Some("rustc_trait_selection::error_reporting::traits::suggestions"),
::tracing_core::field::FieldSet::new(&["obligation",
"trait_pred", "span", "trait_pred.self_ty"],
::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::SPAN)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let mut interest = ::tracing::subscriber::Interest::never();
if ::tracing::Level::DEBUG <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::DEBUG <=
::tracing::level_filters::LevelFilter::current() &&
{ interest = __CALLSITE.interest(); !interest.is_never() }
&&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest) {
let meta = __CALLSITE.metadata();
::tracing::Span::new(meta,
&{
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
let mut iter = meta.fields().iter();
meta.fields().value_set(&[(&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
::tracing::__macro_support::Option::Some(&::tracing::field::debug(&obligation)
as &dyn Value)),
(&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
::tracing::__macro_support::Option::Some(&::tracing::field::debug(&trait_pred)
as &dyn Value)),
(&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
::tracing::__macro_support::Option::Some(&::tracing::field::debug(&span)
as &dyn Value)),
(&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
::tracing::__macro_support::Option::Some(&debug(&trait_pred.self_ty())
as &dyn Value))])
})
} else {
let span =
::tracing::__macro_support::__disabled_span(__CALLSITE.metadata());
{};
span
}
};
__tracing_attr_guard = __tracing_attr_span.enter();
}
#[warn(clippy :: suspicious_else_formatting)]
{
#[allow(unknown_lints, unreachable_code, clippy ::
diverging_sub_expression, clippy :: empty_loop, clippy ::
let_unit_value, clippy :: let_with_type_underscore, clippy ::
needless_return, clippy :: unreachable)]
if false {
let __tracing_attr_fake_return: () = loop {};
return __tracing_attr_fake_return;
}
{
let future_trait =
self.tcx.require_lang_item(LangItem::Future, span);
let self_ty = self.resolve_vars_if_possible(trait_pred.self_ty());
let impls_future =
self.type_implements_trait(future_trait,
[self.tcx.instantiate_bound_regions_with_erased(self_ty)],
obligation.param_env);
if !impls_future.must_apply_modulo_regions() { return; }
let item_def_id =
self.tcx.associated_item_def_ids(future_trait)[0];
let projection_ty =
trait_pred.map_bound(|trait_pred|
{
Ty::new_projection(self.tcx, item_def_id,
[trait_pred.self_ty()])
});
let InferOk { value: projection_ty, .. } =
self.at(&obligation.cause,
obligation.param_env).normalize(projection_ty);
{
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/traits/suggestions.rs:3924",
"rustc_trait_selection::error_reporting::traits::suggestions",
::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs"),
::tracing_core::__macro_support::Option::Some(3924u32),
::tracing_core::__macro_support::Option::Some("rustc_trait_selection::error_reporting::traits::suggestions"),
::tracing_core::field::FieldSet::new(&["normalized_projection_type"],
::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(&debug(&self.resolve_vars_if_possible(projection_ty))
as &dyn Value))])
});
} else { ; }
};
let try_obligation =
self.mk_trait_obligation_with_new_self_ty(obligation.param_env,
trait_pred.map_bound(|trait_pred|
(trait_pred, projection_ty.skip_binder())));
{
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/traits/suggestions.rs:3931",
"rustc_trait_selection::error_reporting::traits::suggestions",
::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs"),
::tracing_core::__macro_support::Option::Some(3931u32),
::tracing_core::__macro_support::Option::Some("rustc_trait_selection::error_reporting::traits::suggestions"),
::tracing_core::field::FieldSet::new(&["try_trait_obligation"],
::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(&debug(&try_obligation)
as &dyn Value))])
});
} else { ; }
};
if self.predicate_may_hold(&try_obligation) &&
let Ok(snippet) =
self.tcx.sess.source_map().span_to_snippet(span) &&
snippet.ends_with('?') {
match self.tcx.coroutine_kind(obligation.cause.body_id) {
Some(hir::CoroutineKind::Desugared(hir::CoroutineDesugaring::Async,
_)) => {
err.span_suggestion_verbose(span.with_hi(span.hi() -
BytePos(1)).shrink_to_hi(),
"consider `await`ing on the `Future`", ".await",
Applicability::MaybeIncorrect);
}
_ => {
let mut span: MultiSpan =
span.with_lo(span.hi() - BytePos(1)).into();
span.push_span_label(self.tcx.def_span(obligation.cause.body_id),
"this is not `async`");
err.span_note(span,
"this implements `Future` and its output type supports \
`?`, but the future cannot be awaited in a synchronous function");
}
}
}
}
}
}#[instrument(
3890 level = "debug", skip(self, err), fields(trait_pred.self_ty = ?trait_pred.self_ty())
3891 )]
3892 pub(super) fn suggest_await_before_try(
3893 &self,
3894 err: &mut Diag<'_>,
3895 obligation: &PredicateObligation<'tcx>,
3896 trait_pred: ty::PolyTraitPredicate<'tcx>,
3897 span: Span,
3898 ) {
3899 let future_trait = self.tcx.require_lang_item(LangItem::Future, span);
3900
3901 let self_ty = self.resolve_vars_if_possible(trait_pred.self_ty());
3902 let impls_future = self.type_implements_trait(
3903 future_trait,
3904 [self.tcx.instantiate_bound_regions_with_erased(self_ty)],
3905 obligation.param_env,
3906 );
3907 if !impls_future.must_apply_modulo_regions() {
3908 return;
3909 }
3910
3911 let item_def_id = self.tcx.associated_item_def_ids(future_trait)[0];
3912 let projection_ty = trait_pred.map_bound(|trait_pred| {
3914 Ty::new_projection(
3915 self.tcx,
3916 item_def_id,
3917 [trait_pred.self_ty()],
3919 )
3920 });
3921 let InferOk { value: projection_ty, .. } =
3922 self.at(&obligation.cause, obligation.param_env).normalize(projection_ty);
3923
3924 debug!(
3925 normalized_projection_type = ?self.resolve_vars_if_possible(projection_ty)
3926 );
3927 let try_obligation = self.mk_trait_obligation_with_new_self_ty(
3928 obligation.param_env,
3929 trait_pred.map_bound(|trait_pred| (trait_pred, projection_ty.skip_binder())),
3930 );
3931 debug!(try_trait_obligation = ?try_obligation);
3932 if self.predicate_may_hold(&try_obligation)
3933 && let Ok(snippet) = self.tcx.sess.source_map().span_to_snippet(span)
3934 && snippet.ends_with('?')
3935 {
3936 match self.tcx.coroutine_kind(obligation.cause.body_id) {
3937 Some(hir::CoroutineKind::Desugared(hir::CoroutineDesugaring::Async, _)) => {
3938 err.span_suggestion_verbose(
3939 span.with_hi(span.hi() - BytePos(1)).shrink_to_hi(),
3940 "consider `await`ing on the `Future`",
3941 ".await",
3942 Applicability::MaybeIncorrect,
3943 );
3944 }
3945 _ => {
3946 let mut span: MultiSpan = span.with_lo(span.hi() - BytePos(1)).into();
3947 span.push_span_label(
3948 self.tcx.def_span(obligation.cause.body_id),
3949 "this is not `async`",
3950 );
3951 err.span_note(
3952 span,
3953 "this implements `Future` and its output type supports \
3954 `?`, but the future cannot be awaited in a synchronous function",
3955 );
3956 }
3957 }
3958 }
3959 }
3960
3961 pub(super) fn suggest_floating_point_literal(
3962 &self,
3963 obligation: &PredicateObligation<'tcx>,
3964 err: &mut Diag<'_>,
3965 trait_pred: ty::PolyTraitPredicate<'tcx>,
3966 ) {
3967 let rhs_span = match obligation.cause.code() {
3968 ObligationCauseCode::BinOp { rhs_span, rhs_is_lit, .. } if *rhs_is_lit => rhs_span,
3969 _ => return,
3970 };
3971 if let ty::Float(_) = trait_pred.skip_binder().self_ty().kind()
3972 && let ty::Infer(InferTy::IntVar(_)) =
3973 trait_pred.skip_binder().trait_ref.args.type_at(1).kind()
3974 {
3975 err.span_suggestion_verbose(
3976 rhs_span.shrink_to_hi(),
3977 "consider using a floating-point literal by writing it with `.0`",
3978 ".0",
3979 Applicability::MaybeIncorrect,
3980 );
3981 }
3982 }
3983
3984 pub fn can_suggest_derive(
3985 &self,
3986 obligation: &PredicateObligation<'tcx>,
3987 trait_pred: ty::PolyTraitPredicate<'tcx>,
3988 ) -> bool {
3989 if trait_pred.polarity() == ty::PredicatePolarity::Negative {
3990 return false;
3991 }
3992 let Some(diagnostic_name) = self.tcx.get_diagnostic_name(trait_pred.def_id()) else {
3993 return false;
3994 };
3995 let (adt, args) = match trait_pred.skip_binder().self_ty().kind() {
3996 ty::Adt(adt, args) if adt.did().is_local() => (adt, args),
3997 _ => return false,
3998 };
3999 let is_derivable_trait = match diagnostic_name {
4000 sym::Default => !adt.is_enum(),
4001 sym::PartialEq | sym::PartialOrd => {
4002 let rhs_ty = trait_pred.skip_binder().trait_ref.args.type_at(1);
4003 trait_pred.skip_binder().self_ty() == rhs_ty
4004 }
4005 sym::Eq | sym::Ord | sym::Clone | sym::Copy | sym::Hash | sym::Debug => true,
4006 _ => false,
4007 };
4008 is_derivable_trait &&
4009 adt.all_fields().all(|field| {
4011 let field_ty = ty::GenericArg::from(field.ty(self.tcx, args));
4012 let trait_args = match diagnostic_name {
4013 sym::PartialEq | sym::PartialOrd => {
4014 Some(field_ty)
4015 }
4016 _ => None,
4017 };
4018 let trait_pred = trait_pred.map_bound_ref(|tr| ty::TraitPredicate {
4019 trait_ref: ty::TraitRef::new(self.tcx,
4020 trait_pred.def_id(),
4021 [field_ty].into_iter().chain(trait_args),
4022 ),
4023 ..*tr
4024 });
4025 let field_obl = Obligation::new(
4026 self.tcx,
4027 obligation.cause.clone(),
4028 obligation.param_env,
4029 trait_pred,
4030 );
4031 self.predicate_must_hold_modulo_regions(&field_obl)
4032 })
4033 }
4034
4035 pub fn suggest_derive(
4036 &self,
4037 obligation: &PredicateObligation<'tcx>,
4038 err: &mut Diag<'_>,
4039 trait_pred: ty::PolyTraitPredicate<'tcx>,
4040 ) {
4041 let Some(diagnostic_name) = self.tcx.get_diagnostic_name(trait_pred.def_id()) else {
4042 return;
4043 };
4044 let adt = match trait_pred.skip_binder().self_ty().kind() {
4045 ty::Adt(adt, _) if adt.did().is_local() => adt,
4046 _ => return,
4047 };
4048 if self.can_suggest_derive(obligation, trait_pred) {
4049 err.span_suggestion_verbose(
4050 self.tcx.def_span(adt.did()).shrink_to_lo(),
4051 ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("consider annotating `{0}` with `#[derive({1})]`",
trait_pred.skip_binder().self_ty(), diagnostic_name))
})format!(
4052 "consider annotating `{}` with `#[derive({})]`",
4053 trait_pred.skip_binder().self_ty(),
4054 diagnostic_name,
4055 ),
4056 ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("#[derive({0})]\n",
diagnostic_name))
})format!("#[derive({diagnostic_name})]\n"),
4058 Applicability::MaybeIncorrect,
4059 );
4060 }
4061 }
4062
4063 pub(super) fn suggest_dereferencing_index(
4064 &self,
4065 obligation: &PredicateObligation<'tcx>,
4066 err: &mut Diag<'_>,
4067 trait_pred: ty::PolyTraitPredicate<'tcx>,
4068 ) {
4069 if let ObligationCauseCode::ImplDerived(_) = obligation.cause.code()
4070 && self
4071 .tcx
4072 .is_diagnostic_item(sym::SliceIndex, trait_pred.skip_binder().trait_ref.def_id)
4073 && let ty::Slice(_) = trait_pred.skip_binder().trait_ref.args.type_at(1).kind()
4074 && let ty::Ref(_, inner_ty, _) = trait_pred.skip_binder().self_ty().kind()
4075 && let ty::Uint(ty::UintTy::Usize) = inner_ty.kind()
4076 {
4077 err.span_suggestion_verbose(
4078 obligation.cause.span.shrink_to_lo(),
4079 "dereference this index",
4080 '*',
4081 Applicability::MachineApplicable,
4082 );
4083 }
4084 }
4085
4086 fn note_function_argument_obligation<G: EmissionGuarantee>(
4087 &self,
4088 body_id: LocalDefId,
4089 err: &mut Diag<'_, G>,
4090 arg_hir_id: HirId,
4091 parent_code: &ObligationCauseCode<'tcx>,
4092 param_env: ty::ParamEnv<'tcx>,
4093 failed_pred: ty::Predicate<'tcx>,
4094 call_hir_id: HirId,
4095 ) {
4096 let tcx = self.tcx;
4097 if let Node::Expr(expr) = tcx.hir_node(arg_hir_id)
4098 && let Some(typeck_results) = &self.typeck_results
4099 {
4100 if let hir::Expr { kind: hir::ExprKind::MethodCall(_, rcvr, _, _), .. } = expr
4101 && let Some(ty) = typeck_results.node_type_opt(rcvr.hir_id)
4102 && let Some(failed_pred) = failed_pred.as_trait_clause()
4103 && let pred = failed_pred.map_bound(|pred| pred.with_replaced_self_ty(tcx, ty))
4104 && self.predicate_must_hold_modulo_regions(&Obligation::misc(
4105 tcx, expr.span, body_id, param_env, pred,
4106 ))
4107 && expr.span.hi() != rcvr.span.hi()
4108 {
4109 let should_sugg = match tcx.hir_node(call_hir_id) {
4110 Node::Expr(hir::Expr {
4111 kind: hir::ExprKind::MethodCall(_, call_receiver, _, _),
4112 ..
4113 }) if let Some((DefKind::AssocFn, did)) =
4114 typeck_results.type_dependent_def(call_hir_id)
4115 && call_receiver.hir_id == arg_hir_id =>
4116 {
4117 if tcx.inherent_impl_of_assoc(did).is_some() {
4121 Some(ty) == typeck_results.node_type_opt(arg_hir_id)
4123 } else {
4124 let trait_id = tcx
4126 .trait_of_assoc(did)
4127 .unwrap_or_else(|| tcx.impl_trait_id(tcx.parent(did)));
4128 let args = typeck_results.node_args(call_hir_id);
4129 let tr = ty::TraitRef::from_assoc(tcx, trait_id, args)
4130 .with_replaced_self_ty(tcx, ty);
4131 self.type_implements_trait(tr.def_id, tr.args, param_env)
4132 .must_apply_modulo_regions()
4133 }
4134 }
4135 _ => true,
4136 };
4137
4138 if should_sugg {
4139 err.span_suggestion_verbose(
4140 expr.span.with_lo(rcvr.span.hi()),
4141 ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("consider removing this method call, as the receiver has type `{0}` and `{1}` trivially holds",
ty, pred))
})format!(
4142 "consider removing this method call, as the receiver has type `{ty}` and \
4143 `{pred}` trivially holds",
4144 ),
4145 "",
4146 Applicability::MaybeIncorrect,
4147 );
4148 }
4149 }
4150 if let hir::Expr { kind: hir::ExprKind::Block(block, _), .. } = expr {
4151 let inner_expr = expr.peel_blocks();
4152 let ty = typeck_results
4153 .expr_ty_adjusted_opt(inner_expr)
4154 .unwrap_or(Ty::new_misc_error(tcx));
4155 let span = inner_expr.span;
4156 if Some(span) != err.span.primary_span()
4157 && !span.in_external_macro(tcx.sess.source_map())
4158 {
4159 err.span_label(
4160 span,
4161 if ty.references_error() {
4162 String::new()
4163 } else {
4164 let ty = { let _guard = ForceTrimmedGuard::new(); self.ty_to_string(ty) }with_forced_trimmed_paths!(self.ty_to_string(ty));
4165 ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("this tail expression is of type `{0}`",
ty))
})format!("this tail expression is of type `{ty}`")
4166 },
4167 );
4168 if let ty::PredicateKind::Clause(clause) = failed_pred.kind().skip_binder()
4169 && let ty::ClauseKind::Trait(pred) = clause
4170 && tcx.fn_trait_kind_from_def_id(pred.def_id()).is_some()
4171 {
4172 if let [stmt, ..] = block.stmts
4173 && let hir::StmtKind::Semi(value) = stmt.kind
4174 && let hir::ExprKind::Closure(hir::Closure {
4175 body, fn_decl_span, ..
4176 }) = value.kind
4177 && let body = tcx.hir_body(*body)
4178 && !#[allow(non_exhaustive_omitted_patterns)] match body.value.kind {
hir::ExprKind::Block(..) => true,
_ => false,
}matches!(body.value.kind, hir::ExprKind::Block(..))
4179 {
4180 err.multipart_suggestion(
4183 "you might have meant to open the closure body instead of placing \
4184 a closure within a block",
4185 <[_]>::into_vec(::alloc::boxed::box_new([(expr.span.with_hi(value.span.lo()),
String::new()),
(fn_decl_span.shrink_to_hi(), " {".to_string())]))vec![
4186 (expr.span.with_hi(value.span.lo()), String::new()),
4187 (fn_decl_span.shrink_to_hi(), " {".to_string()),
4188 ],
4189 Applicability::MaybeIncorrect,
4190 );
4191 } else {
4192 err.span_suggestion_verbose(
4194 expr.span.shrink_to_lo(),
4195 "you might have meant to create the closure instead of a block",
4196 ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("|{0}| ",
(0..pred.trait_ref.args.len() -
1).map(|_| "_").collect::<Vec<_>>().join(", ")))
})format!(
4197 "|{}| ",
4198 (0..pred.trait_ref.args.len() - 1)
4199 .map(|_| "_")
4200 .collect::<Vec<_>>()
4201 .join(", ")
4202 ),
4203 Applicability::MaybeIncorrect,
4204 );
4205 }
4206 }
4207 }
4208 }
4209
4210 let mut type_diffs = ::alloc::vec::Vec::new()vec![];
4215 if let ObligationCauseCode::WhereClauseInExpr(def_id, _, _, idx) = parent_code
4216 && let Some(node_args) = typeck_results.node_args_opt(call_hir_id)
4217 && let where_clauses =
4218 self.tcx.predicates_of(def_id).instantiate(self.tcx, node_args)
4219 && let Some(where_pred) = where_clauses.predicates.get(*idx)
4220 {
4221 if let Some(where_pred) = where_pred.as_trait_clause()
4222 && let Some(failed_pred) = failed_pred.as_trait_clause()
4223 && where_pred.def_id() == failed_pred.def_id()
4224 {
4225 self.enter_forall(where_pred, |where_pred| {
4226 let failed_pred = self.instantiate_binder_with_fresh_vars(
4227 expr.span,
4228 BoundRegionConversionTime::FnCall,
4229 failed_pred,
4230 );
4231
4232 let zipped =
4233 iter::zip(where_pred.trait_ref.args, failed_pred.trait_ref.args);
4234 for (expected, actual) in zipped {
4235 self.probe(|_| {
4236 match self
4237 .at(&ObligationCause::misc(expr.span, body_id), param_env)
4238 .eq(DefineOpaqueTypes::Yes, expected, actual)
4241 {
4242 Ok(_) => (), Err(err) => type_diffs.push(err),
4244 }
4245 })
4246 }
4247 })
4248 } else if let Some(where_pred) = where_pred.as_projection_clause()
4249 && let Some(failed_pred) = failed_pred.as_projection_clause()
4250 && let Some(found) = failed_pred.skip_binder().term.as_type()
4251 {
4252 type_diffs = <[_]>::into_vec(::alloc::boxed::box_new([TypeError::Sorts(ty::error::ExpectedFound {
expected: where_pred.skip_binder().projection_term.expect_ty(self.tcx).to_ty(self.tcx),
found,
})]))vec![TypeError::Sorts(ty::error::ExpectedFound {
4253 expected: where_pred
4254 .skip_binder()
4255 .projection_term
4256 .expect_ty(self.tcx)
4257 .to_ty(self.tcx),
4258 found,
4259 })];
4260 }
4261 }
4262 if let hir::ExprKind::Path(hir::QPath::Resolved(None, path)) = expr.kind
4263 && let hir::Path { res: Res::Local(hir_id), .. } = path
4264 && let hir::Node::Pat(binding) = self.tcx.hir_node(*hir_id)
4265 && let hir::Node::LetStmt(local) = self.tcx.parent_hir_node(binding.hir_id)
4266 && let Some(binding_expr) = local.init
4267 {
4268 self.point_at_chain(binding_expr, typeck_results, type_diffs, param_env, err);
4272 } else {
4273 self.point_at_chain(expr, typeck_results, type_diffs, param_env, err);
4274 }
4275 }
4276 let call_node = tcx.hir_node(call_hir_id);
4277 if let Node::Expr(hir::Expr { kind: hir::ExprKind::MethodCall(path, rcvr, ..), .. }) =
4278 call_node
4279 {
4280 if Some(rcvr.span) == err.span.primary_span() {
4281 err.replace_span_with(path.ident.span, true);
4282 }
4283 }
4284
4285 if let Node::Expr(expr) = call_node {
4286 if let hir::ExprKind::Call(hir::Expr { span, .. }, _)
4287 | hir::ExprKind::MethodCall(
4288 hir::PathSegment { ident: Ident { span, .. }, .. },
4289 ..,
4290 ) = expr.kind
4291 {
4292 if Some(*span) != err.span.primary_span() {
4293 let msg = if span.is_desugaring(DesugaringKind::FormatLiteral { source: true })
4294 {
4295 "required by this formatting parameter"
4296 } else if span.is_desugaring(DesugaringKind::FormatLiteral { source: false }) {
4297 "required by a formatting parameter in this expression"
4298 } else {
4299 "required by a bound introduced by this call"
4300 };
4301 err.span_label(*span, msg);
4302 }
4303 }
4304
4305 if let hir::ExprKind::MethodCall(_, expr, ..) = expr.kind {
4306 self.suggest_option_method_if_applicable(failed_pred, param_env, err, expr);
4307 }
4308 }
4309 }
4310
4311 fn suggest_option_method_if_applicable<G: EmissionGuarantee>(
4312 &self,
4313 failed_pred: ty::Predicate<'tcx>,
4314 param_env: ty::ParamEnv<'tcx>,
4315 err: &mut Diag<'_, G>,
4316 expr: &hir::Expr<'_>,
4317 ) {
4318 let tcx = self.tcx;
4319 let infcx = self.infcx;
4320 let Some(typeck_results) = self.typeck_results.as_ref() else { return };
4321
4322 let Some(option_ty_adt) = typeck_results.expr_ty_adjusted(expr).ty_adt_def() else {
4324 return;
4325 };
4326 if !tcx.is_diagnostic_item(sym::Option, option_ty_adt.did()) {
4327 return;
4328 }
4329
4330 if let ty::PredicateKind::Clause(ty::ClauseKind::Trait(ty::TraitPredicate { trait_ref, .. }))
4333 = failed_pred.kind().skip_binder()
4334 && tcx.is_fn_trait(trait_ref.def_id)
4335 && let [self_ty, found_ty] = trait_ref.args.as_slice()
4336 && let Some(fn_ty) = self_ty.as_type().filter(|ty| ty.is_fn())
4337 && let fn_sig @ ty::FnSig {
4338 abi: ExternAbi::Rust,
4339 c_variadic: false,
4340 safety: hir::Safety::Safe,
4341 ..
4342 } = fn_ty.fn_sig(tcx).skip_binder()
4343
4344 && let Some(&ty::Ref(_, target_ty, needs_mut)) = fn_sig.inputs().first().map(|t| t.kind())
4346 && !target_ty.has_escaping_bound_vars()
4347
4348 && let Some(ty::Tuple(tys)) = found_ty.as_type().map(Ty::kind)
4350 && let &[found_ty] = tys.as_slice()
4351 && !found_ty.has_escaping_bound_vars()
4352
4353 && let Some(deref_target_did) = tcx.lang_items().deref_target()
4355 && let projection = Ty::new_projection_from_args(tcx,deref_target_did, tcx.mk_args(&[ty::GenericArg::from(found_ty)]))
4356 && let InferOk { value: deref_target, obligations } = infcx.at(&ObligationCause::dummy(), param_env).normalize(projection)
4357 && obligations.iter().all(|obligation| infcx.predicate_must_hold_modulo_regions(obligation))
4358 && infcx.can_eq(param_env, deref_target, target_ty)
4359 {
4360 let help = if let hir::Mutability::Mut = needs_mut
4361 && let Some(deref_mut_did) = tcx.lang_items().deref_mut_trait()
4362 && infcx
4363 .type_implements_trait(deref_mut_did, iter::once(found_ty), param_env)
4364 .must_apply_modulo_regions()
4365 {
4366 Some(("call `Option::as_deref_mut()` first", ".as_deref_mut()"))
4367 } else if let hir::Mutability::Not = needs_mut {
4368 Some(("call `Option::as_deref()` first", ".as_deref()"))
4369 } else {
4370 None
4371 };
4372
4373 if let Some((msg, sugg)) = help {
4374 err.span_suggestion_with_style(
4375 expr.span.shrink_to_hi(),
4376 msg,
4377 sugg,
4378 Applicability::MaybeIncorrect,
4379 SuggestionStyle::ShowAlways,
4380 );
4381 }
4382 }
4383 }
4384
4385 fn look_for_iterator_item_mistakes<G: EmissionGuarantee>(
4386 &self,
4387 assocs_in_this_method: &[Option<(Span, (DefId, Ty<'tcx>))>],
4388 typeck_results: &TypeckResults<'tcx>,
4389 type_diffs: &[TypeError<'tcx>],
4390 param_env: ty::ParamEnv<'tcx>,
4391 path_segment: &hir::PathSegment<'_>,
4392 args: &[hir::Expr<'_>],
4393 prev_ty: Ty<'_>,
4394 err: &mut Diag<'_, G>,
4395 ) {
4396 let tcx = self.tcx;
4397 for entry in assocs_in_this_method {
4400 let Some((_span, (def_id, ty))) = entry else {
4401 continue;
4402 };
4403 for diff in type_diffs {
4404 let TypeError::Sorts(expected_found) = diff else {
4405 continue;
4406 };
4407 if tcx.is_diagnostic_item(sym::IntoIteratorItem, *def_id)
4408 && path_segment.ident.name == sym::iter
4409 && self.can_eq(
4410 param_env,
4411 Ty::new_ref(
4412 tcx,
4413 tcx.lifetimes.re_erased,
4414 expected_found.found,
4415 ty::Mutability::Not,
4416 ),
4417 *ty,
4418 )
4419 && let [] = args
4420 {
4421 err.span_suggestion_verbose(
4423 path_segment.ident.span,
4424 ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("consider consuming the `{0}` to construct the `Iterator`",
prev_ty))
})format!("consider consuming the `{prev_ty}` to construct the `Iterator`"),
4425 "into_iter".to_string(),
4426 Applicability::MachineApplicable,
4427 );
4428 }
4429 if tcx.is_diagnostic_item(sym::IntoIteratorItem, *def_id)
4430 && path_segment.ident.name == sym::into_iter
4431 && self.can_eq(
4432 param_env,
4433 expected_found.found,
4434 Ty::new_ref(tcx, tcx.lifetimes.re_erased, *ty, ty::Mutability::Not),
4435 )
4436 && let [] = args
4437 {
4438 err.span_suggestion_verbose(
4440 path_segment.ident.span,
4441 ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("consider not consuming the `{0}` to construct the `Iterator`",
prev_ty))
})format!(
4442 "consider not consuming the `{prev_ty}` to construct the `Iterator`"
4443 ),
4444 "iter".to_string(),
4445 Applicability::MachineApplicable,
4446 );
4447 }
4448 if tcx.is_diagnostic_item(sym::IteratorItem, *def_id)
4449 && path_segment.ident.name == sym::map
4450 && self.can_eq(param_env, expected_found.found, *ty)
4451 && let [arg] = args
4452 && let hir::ExprKind::Closure(closure) = arg.kind
4453 {
4454 let body = tcx.hir_body(closure.body);
4455 if let hir::ExprKind::Block(block, None) = body.value.kind
4456 && let None = block.expr
4457 && let [.., stmt] = block.stmts
4458 && let hir::StmtKind::Semi(expr) = stmt.kind
4459 && expected_found.found.is_unit()
4463 && expr.span.hi() != stmt.span.hi()
4468 {
4469 err.span_suggestion_verbose(
4470 expr.span.shrink_to_hi().with_hi(stmt.span.hi()),
4471 "consider removing this semicolon",
4472 String::new(),
4473 Applicability::MachineApplicable,
4474 );
4475 }
4476 let expr = if let hir::ExprKind::Block(block, None) = body.value.kind
4477 && let Some(expr) = block.expr
4478 {
4479 expr
4480 } else {
4481 body.value
4482 };
4483 if let hir::ExprKind::MethodCall(path_segment, rcvr, [], span) = expr.kind
4484 && path_segment.ident.name == sym::clone
4485 && let Some(expr_ty) = typeck_results.expr_ty_opt(expr)
4486 && let Some(rcvr_ty) = typeck_results.expr_ty_opt(rcvr)
4487 && self.can_eq(param_env, expr_ty, rcvr_ty)
4488 && let ty::Ref(_, ty, _) = expr_ty.kind()
4489 {
4490 err.span_label(
4491 span,
4492 ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("this method call is cloning the reference `{0}`, not `{1}` which doesn\'t implement `Clone`",
expr_ty, ty))
})format!(
4493 "this method call is cloning the reference `{expr_ty}`, not \
4494 `{ty}` which doesn't implement `Clone`",
4495 ),
4496 );
4497 let ty::Param(..) = ty.kind() else {
4498 continue;
4499 };
4500 let node =
4501 tcx.hir_node_by_def_id(tcx.hir_get_parent_item(expr.hir_id).def_id);
4502
4503 let pred = ty::Binder::dummy(ty::TraitPredicate {
4504 trait_ref: ty::TraitRef::new(
4505 tcx,
4506 tcx.require_lang_item(LangItem::Clone, span),
4507 [*ty],
4508 ),
4509 polarity: ty::PredicatePolarity::Positive,
4510 });
4511 let Some(generics) = node.generics() else {
4512 continue;
4513 };
4514 let Some(body_id) = node.body_id() else {
4515 continue;
4516 };
4517 suggest_restriction(
4518 tcx,
4519 tcx.hir_body_owner_def_id(body_id),
4520 generics,
4521 &::alloc::__export::must_use({
::alloc::fmt::format(format_args!("type parameter `{0}`", ty))
})format!("type parameter `{ty}`"),
4522 err,
4523 node.fn_sig(),
4524 None,
4525 pred,
4526 None,
4527 );
4528 }
4529 }
4530 }
4531 }
4532 }
4533
4534 fn point_at_chain<G: EmissionGuarantee>(
4535 &self,
4536 expr: &hir::Expr<'_>,
4537 typeck_results: &TypeckResults<'tcx>,
4538 type_diffs: Vec<TypeError<'tcx>>,
4539 param_env: ty::ParamEnv<'tcx>,
4540 err: &mut Diag<'_, G>,
4541 ) {
4542 let mut primary_spans = ::alloc::vec::Vec::new()vec![];
4543 let mut span_labels = ::alloc::vec::Vec::new()vec![];
4544
4545 let tcx = self.tcx;
4546
4547 let mut print_root_expr = true;
4548 let mut assocs = ::alloc::vec::Vec::new()vec![];
4549 let mut expr = expr;
4550 let mut prev_ty = self.resolve_vars_if_possible(
4551 typeck_results.expr_ty_adjusted_opt(expr).unwrap_or(Ty::new_misc_error(tcx)),
4552 );
4553 while let hir::ExprKind::MethodCall(path_segment, rcvr_expr, args, span) = expr.kind {
4554 expr = rcvr_expr;
4558 let assocs_in_this_method =
4559 self.probe_assoc_types_at_expr(&type_diffs, span, prev_ty, expr.hir_id, param_env);
4560 prev_ty = self.resolve_vars_if_possible(
4561 typeck_results.expr_ty_adjusted_opt(expr).unwrap_or(Ty::new_misc_error(tcx)),
4562 );
4563 self.look_for_iterator_item_mistakes(
4564 &assocs_in_this_method,
4565 typeck_results,
4566 &type_diffs,
4567 param_env,
4568 path_segment,
4569 args,
4570 prev_ty,
4571 err,
4572 );
4573 assocs.push(assocs_in_this_method);
4574
4575 if let hir::ExprKind::Path(hir::QPath::Resolved(None, path)) = expr.kind
4576 && let hir::Path { res: Res::Local(hir_id), .. } = path
4577 && let hir::Node::Pat(binding) = self.tcx.hir_node(*hir_id)
4578 {
4579 let parent = self.tcx.parent_hir_node(binding.hir_id);
4580 if let hir::Node::LetStmt(local) = parent
4582 && let Some(binding_expr) = local.init
4583 {
4584 expr = binding_expr;
4586 }
4587 if let hir::Node::Param(param) = parent {
4588 let prev_ty = self.resolve_vars_if_possible(
4590 typeck_results
4591 .node_type_opt(param.hir_id)
4592 .unwrap_or(Ty::new_misc_error(tcx)),
4593 );
4594 let assocs_in_this_method = self.probe_assoc_types_at_expr(
4595 &type_diffs,
4596 param.ty_span,
4597 prev_ty,
4598 param.hir_id,
4599 param_env,
4600 );
4601 if assocs_in_this_method.iter().any(|a| a.is_some()) {
4602 assocs.push(assocs_in_this_method);
4603 print_root_expr = false;
4604 }
4605 break;
4606 }
4607 }
4608 }
4609 if let Some(ty) = typeck_results.expr_ty_opt(expr)
4612 && print_root_expr
4613 {
4614 let ty = { let _guard = ForceTrimmedGuard::new(); self.ty_to_string(ty) }with_forced_trimmed_paths!(self.ty_to_string(ty));
4615 span_labels.push((expr.span, ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("this expression has type `{0}`",
ty))
})format!("this expression has type `{ty}`")));
4619 };
4620 let mut assocs = assocs.into_iter().peekable();
4623 while let Some(assocs_in_method) = assocs.next() {
4624 let Some(prev_assoc_in_method) = assocs.peek() else {
4625 for entry in assocs_in_method {
4626 let Some((span, (assoc, ty))) = entry else {
4627 continue;
4628 };
4629 if primary_spans.is_empty()
4630 || type_diffs.iter().any(|diff| {
4631 let TypeError::Sorts(expected_found) = diff else {
4632 return false;
4633 };
4634 self.can_eq(param_env, expected_found.found, ty)
4635 })
4636 {
4637 primary_spans.push(span);
4643 }
4644 span_labels.push((
4645 span,
4646 {
let _guard = ForceTrimmedGuard::new();
::alloc::__export::must_use({
::alloc::fmt::format(format_args!("`{0}` is `{1}` here",
self.tcx.def_path_str(assoc), ty))
})
}with_forced_trimmed_paths!(format!(
4647 "`{}` is `{ty}` here",
4648 self.tcx.def_path_str(assoc),
4649 )),
4650 ));
4651 }
4652 break;
4653 };
4654 for (entry, prev_entry) in
4655 assocs_in_method.into_iter().zip(prev_assoc_in_method.into_iter())
4656 {
4657 match (entry, prev_entry) {
4658 (Some((span, (assoc, ty))), Some((_, (_, prev_ty)))) => {
4659 let ty_str = { let _guard = ForceTrimmedGuard::new(); self.ty_to_string(ty) }with_forced_trimmed_paths!(self.ty_to_string(ty));
4660
4661 let assoc = { let _guard = ForceTrimmedGuard::new(); self.tcx.def_path_str(assoc) }with_forced_trimmed_paths!(self.tcx.def_path_str(assoc));
4662 if !self.can_eq(param_env, ty, *prev_ty) {
4663 if type_diffs.iter().any(|diff| {
4664 let TypeError::Sorts(expected_found) = diff else {
4665 return false;
4666 };
4667 self.can_eq(param_env, expected_found.found, ty)
4668 }) {
4669 primary_spans.push(span);
4670 }
4671 span_labels
4672 .push((span, ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("`{0}` changed to `{1}` here",
assoc, ty_str))
})format!("`{assoc}` changed to `{ty_str}` here")));
4673 } else {
4674 span_labels.push((span, ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("`{0}` remains `{1}` here", assoc,
ty_str))
})format!("`{assoc}` remains `{ty_str}` here")));
4675 }
4676 }
4677 (Some((span, (assoc, ty))), None) => {
4678 span_labels.push((
4679 span,
4680 {
let _guard = ForceTrimmedGuard::new();
::alloc::__export::must_use({
::alloc::fmt::format(format_args!("`{0}` is `{1}` here",
self.tcx.def_path_str(assoc), self.ty_to_string(ty)))
})
}with_forced_trimmed_paths!(format!(
4681 "`{}` is `{}` here",
4682 self.tcx.def_path_str(assoc),
4683 self.ty_to_string(ty),
4684 )),
4685 ));
4686 }
4687 (None, Some(_)) | (None, None) => {}
4688 }
4689 }
4690 }
4691 if !primary_spans.is_empty() {
4692 let mut multi_span: MultiSpan = primary_spans.into();
4693 for (span, label) in span_labels {
4694 multi_span.push_span_label(span, label);
4695 }
4696 err.span_note(
4697 multi_span,
4698 "the method call chain might not have had the expected associated types",
4699 );
4700 }
4701 }
4702
4703 fn probe_assoc_types_at_expr(
4704 &self,
4705 type_diffs: &[TypeError<'tcx>],
4706 span: Span,
4707 prev_ty: Ty<'tcx>,
4708 body_id: HirId,
4709 param_env: ty::ParamEnv<'tcx>,
4710 ) -> Vec<Option<(Span, (DefId, Ty<'tcx>))>> {
4711 let ocx = ObligationCtxt::new(self.infcx);
4712 let mut assocs_in_this_method = Vec::with_capacity(type_diffs.len());
4713 for diff in type_diffs {
4714 let TypeError::Sorts(expected_found) = diff else {
4715 continue;
4716 };
4717 let ty::Alias(ty::Projection, proj) = expected_found.expected.kind() else {
4718 continue;
4719 };
4720
4721 let args = GenericArgs::for_item(self.tcx, proj.def_id, |param, _| {
4725 if param.index == 0 {
4726 if true {
match param.kind {
ty::GenericParamDefKind::Type { .. } => {}
ref left_val => {
::core::panicking::assert_matches_failed(left_val,
"ty::GenericParamDefKind::Type { .. }",
::core::option::Option::None);
}
};
};debug_assert_matches!(param.kind, ty::GenericParamDefKind::Type { .. });
4727 return prev_ty.into();
4728 }
4729 self.var_for_def(span, param)
4730 });
4731 let ty = self.infcx.next_ty_var(span);
4735 let projection = ty::Binder::dummy(ty::PredicateKind::Clause(
4737 ty::ClauseKind::Projection(ty::ProjectionPredicate {
4738 projection_term: ty::AliasTerm::new_from_args(self.tcx, proj.def_id, args),
4739 term: ty.into(),
4740 }),
4741 ));
4742 let body_def_id = self.tcx.hir_enclosing_body_owner(body_id);
4743 ocx.register_obligation(Obligation::misc(
4745 self.tcx,
4746 span,
4747 body_def_id,
4748 param_env,
4749 projection,
4750 ));
4751 if ocx.try_evaluate_obligations().is_empty()
4752 && let ty = self.resolve_vars_if_possible(ty)
4753 && !ty.is_ty_var()
4754 {
4755 assocs_in_this_method.push(Some((span, (proj.def_id, ty))));
4756 } else {
4757 assocs_in_this_method.push(None);
4762 }
4763 }
4764 assocs_in_this_method
4765 }
4766
4767 pub(super) fn suggest_convert_to_slice(
4771 &self,
4772 err: &mut Diag<'_>,
4773 obligation: &PredicateObligation<'tcx>,
4774 trait_pred: ty::PolyTraitPredicate<'tcx>,
4775 candidate_impls: &[ImplCandidate<'tcx>],
4776 span: Span,
4777 ) {
4778 let (ObligationCauseCode::BinOp { .. } | ObligationCauseCode::FunctionArg { .. }) =
4781 obligation.cause.code()
4782 else {
4783 return;
4784 };
4785
4786 let (element_ty, mut mutability) = match *trait_pred.skip_binder().self_ty().kind() {
4791 ty::Array(element_ty, _) => (element_ty, None),
4792
4793 ty::Ref(_, pointee_ty, mutability) => match *pointee_ty.kind() {
4794 ty::Array(element_ty, _) => (element_ty, Some(mutability)),
4795 _ => return,
4796 },
4797
4798 _ => return,
4799 };
4800
4801 let mut is_slice = |candidate: Ty<'tcx>| match *candidate.kind() {
4804 ty::RawPtr(t, m) | ty::Ref(_, t, m) => {
4805 if let ty::Slice(e) = *t.kind()
4806 && e == element_ty
4807 && m == mutability.unwrap_or(m)
4808 {
4809 mutability = Some(m);
4811 true
4812 } else {
4813 false
4814 }
4815 }
4816 _ => false,
4817 };
4818
4819 if let Some(slice_ty) = candidate_impls
4821 .iter()
4822 .map(|trait_ref| trait_ref.trait_ref.self_ty())
4823 .find(|t| is_slice(*t))
4824 {
4825 let msg = ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("convert the array to a `{0}` slice instead",
slice_ty))
})format!("convert the array to a `{slice_ty}` slice instead");
4826
4827 if let Ok(snippet) = self.tcx.sess.source_map().span_to_snippet(span) {
4828 let mut suggestions = ::alloc::vec::Vec::new()vec![];
4829 if snippet.starts_with('&') {
4830 } else if let Some(hir::Mutability::Mut) = mutability {
4831 suggestions.push((span.shrink_to_lo(), "&mut ".into()));
4832 } else {
4833 suggestions.push((span.shrink_to_lo(), "&".into()));
4834 }
4835 suggestions.push((span.shrink_to_hi(), "[..]".into()));
4836 err.multipart_suggestion_verbose(msg, suggestions, Applicability::MaybeIncorrect);
4837 } else {
4838 err.span_help(span, msg);
4839 }
4840 }
4841 }
4842
4843 pub(super) fn suggest_tuple_wrapping(
4848 &self,
4849 err: &mut Diag<'_>,
4850 root_obligation: &PredicateObligation<'tcx>,
4851 obligation: &PredicateObligation<'tcx>,
4852 ) {
4853 let ObligationCauseCode::FunctionArg { arg_hir_id, .. } = obligation.cause.code() else {
4854 return;
4855 };
4856
4857 let Some(root_pred) = root_obligation.predicate.as_trait_clause() else { return };
4858
4859 let trait_ref = root_pred.map_bound(|root_pred| {
4860 root_pred.trait_ref.with_replaced_self_ty(
4861 self.tcx,
4862 Ty::new_tup(self.tcx, &[root_pred.trait_ref.self_ty()]),
4863 )
4864 });
4865
4866 let obligation =
4867 Obligation::new(self.tcx, obligation.cause.clone(), obligation.param_env, trait_ref);
4868
4869 if self.predicate_must_hold_modulo_regions(&obligation) {
4870 let arg_span = self.tcx.hir_span(*arg_hir_id);
4871 err.multipart_suggestion_verbose(
4872 ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("use a unary tuple instead"))
})format!("use a unary tuple instead"),
4873 <[_]>::into_vec(::alloc::boxed::box_new([(arg_span.shrink_to_lo(),
"(".into()), (arg_span.shrink_to_hi(), ",)".into())]))vec![(arg_span.shrink_to_lo(), "(".into()), (arg_span.shrink_to_hi(), ",)".into())],
4874 Applicability::MaybeIncorrect,
4875 );
4876 }
4877 }
4878
4879 pub(super) fn explain_hrtb_projection(
4880 &self,
4881 diag: &mut Diag<'_>,
4882 pred: ty::PolyTraitPredicate<'tcx>,
4883 param_env: ty::ParamEnv<'tcx>,
4884 cause: &ObligationCause<'tcx>,
4885 ) {
4886 if pred.skip_binder().has_escaping_bound_vars() && pred.skip_binder().has_non_region_infer()
4887 {
4888 self.probe(|_| {
4889 let ocx = ObligationCtxt::new(self);
4890 self.enter_forall(pred, |pred| {
4891 let pred = ocx.normalize(&ObligationCause::dummy(), param_env, pred);
4892 ocx.register_obligation(Obligation::new(
4893 self.tcx,
4894 ObligationCause::dummy(),
4895 param_env,
4896 pred,
4897 ));
4898 });
4899 if !ocx.try_evaluate_obligations().is_empty() {
4900 return;
4902 }
4903
4904 if let ObligationCauseCode::FunctionArg {
4905 call_hir_id,
4906 arg_hir_id,
4907 parent_code: _,
4908 } = cause.code()
4909 {
4910 let arg_span = self.tcx.hir_span(*arg_hir_id);
4911 let mut sp: MultiSpan = arg_span.into();
4912
4913 sp.push_span_label(
4914 arg_span,
4915 "the trait solver is unable to infer the \
4916 generic types that should be inferred from this argument",
4917 );
4918 sp.push_span_label(
4919 self.tcx.hir_span(*call_hir_id),
4920 "add turbofish arguments to this call to \
4921 specify the types manually, even if it's redundant",
4922 );
4923 diag.span_note(
4924 sp,
4925 "this is a known limitation of the trait solver that \
4926 will be lifted in the future",
4927 );
4928 } else {
4929 let mut sp: MultiSpan = cause.span.into();
4930 sp.push_span_label(
4931 cause.span,
4932 "try adding turbofish arguments to this expression to \
4933 specify the types manually, even if it's redundant",
4934 );
4935 diag.span_note(
4936 sp,
4937 "this is a known limitation of the trait solver that \
4938 will be lifted in the future",
4939 );
4940 }
4941 });
4942 }
4943 }
4944
4945 pub(super) fn suggest_desugaring_async_fn_in_trait(
4946 &self,
4947 err: &mut Diag<'_>,
4948 trait_pred: ty::PolyTraitPredicate<'tcx>,
4949 ) {
4950 if self.tcx.features().return_type_notation() {
4952 return;
4953 }
4954
4955 let trait_def_id = trait_pred.def_id();
4956
4957 if !self.tcx.trait_is_auto(trait_def_id) {
4959 return;
4960 }
4961
4962 let ty::Alias(ty::Projection, alias_ty) = trait_pred.self_ty().skip_binder().kind() else {
4964 return;
4965 };
4966 let Some(ty::ImplTraitInTraitData::Trait { fn_def_id, opaque_def_id }) =
4967 self.tcx.opt_rpitit_info(alias_ty.def_id)
4968 else {
4969 return;
4970 };
4971
4972 let auto_trait = self.tcx.def_path_str(trait_def_id);
4973 let Some(fn_def_id) = fn_def_id.as_local() else {
4975 if self.tcx.asyncness(fn_def_id).is_async() {
4977 err.span_note(
4978 self.tcx.def_span(fn_def_id),
4979 ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("`{0}::{1}` is an `async fn` in trait, which does not automatically imply that its future is `{2}`",
alias_ty.trait_ref(self.tcx), self.tcx.item_name(fn_def_id),
auto_trait))
})format!(
4980 "`{}::{}` is an `async fn` in trait, which does not \
4981 automatically imply that its future is `{auto_trait}`",
4982 alias_ty.trait_ref(self.tcx),
4983 self.tcx.item_name(fn_def_id)
4984 ),
4985 );
4986 }
4987 return;
4988 };
4989 let hir::Node::TraitItem(item) = self.tcx.hir_node_by_def_id(fn_def_id) else {
4990 return;
4991 };
4992
4993 let (sig, body) = item.expect_fn();
4995 let hir::FnRetTy::Return(hir::Ty { kind: hir::TyKind::OpaqueDef(opaq_def, ..), .. }) =
4996 sig.decl.output
4997 else {
4998 return;
5000 };
5001
5002 if opaq_def.def_id.to_def_id() != opaque_def_id {
5005 return;
5006 }
5007
5008 let Some(sugg) = suggest_desugaring_async_fn_to_impl_future_in_trait(
5009 self.tcx,
5010 *sig,
5011 *body,
5012 opaque_def_id.expect_local(),
5013 &::alloc::__export::must_use({
::alloc::fmt::format(format_args!(" + {0}", auto_trait))
})format!(" + {auto_trait}"),
5014 ) else {
5015 return;
5016 };
5017
5018 let function_name = self.tcx.def_path_str(fn_def_id);
5019 err.multipart_suggestion(
5020 ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("`{0}` can be made part of the associated future\'s guarantees for all implementations of `{1}`",
auto_trait, function_name))
})format!(
5021 "`{auto_trait}` can be made part of the associated future's \
5022 guarantees for all implementations of `{function_name}`"
5023 ),
5024 sugg,
5025 Applicability::MachineApplicable,
5026 );
5027 }
5028
5029 pub fn ty_kind_suggestion(
5030 &self,
5031 param_env: ty::ParamEnv<'tcx>,
5032 ty: Ty<'tcx>,
5033 ) -> Option<String> {
5034 let tcx = self.infcx.tcx;
5035 let implements_default = |ty| {
5036 let Some(default_trait) = tcx.get_diagnostic_item(sym::Default) else {
5037 return false;
5038 };
5039 self.type_implements_trait(default_trait, [ty], param_env).must_apply_modulo_regions()
5040 };
5041
5042 Some(match *ty.kind() {
5043 ty::Never | ty::Error(_) => return None,
5044 ty::Bool => "false".to_string(),
5045 ty::Char => "\'x\'".to_string(),
5046 ty::Int(_) | ty::Uint(_) => "42".into(),
5047 ty::Float(_) => "3.14159".into(),
5048 ty::Slice(_) => "[]".to_string(),
5049 ty::Adt(def, _) if Some(def.did()) == tcx.get_diagnostic_item(sym::Vec) => {
5050 "vec![]".to_string()
5051 }
5052 ty::Adt(def, _) if Some(def.did()) == tcx.get_diagnostic_item(sym::String) => {
5053 "String::new()".to_string()
5054 }
5055 ty::Adt(def, args) if def.is_box() => {
5056 ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("Box::new({0})",
self.ty_kind_suggestion(param_env, args[0].expect_ty())?))
})format!("Box::new({})", self.ty_kind_suggestion(param_env, args[0].expect_ty())?)
5057 }
5058 ty::Adt(def, _) if Some(def.did()) == tcx.get_diagnostic_item(sym::Option) => {
5059 "None".to_string()
5060 }
5061 ty::Adt(def, args) if Some(def.did()) == tcx.get_diagnostic_item(sym::Result) => {
5062 ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("Ok({0})",
self.ty_kind_suggestion(param_env, args[0].expect_ty())?))
})format!("Ok({})", self.ty_kind_suggestion(param_env, args[0].expect_ty())?)
5063 }
5064 ty::Adt(_, _) if implements_default(ty) => "Default::default()".to_string(),
5065 ty::Ref(_, ty, mutability) => {
5066 if let (ty::Str, hir::Mutability::Not) = (ty.kind(), mutability) {
5067 "\"\"".to_string()
5068 } else {
5069 let ty = self.ty_kind_suggestion(param_env, ty)?;
5070 ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("&{0}{1}", mutability.prefix_str(),
ty))
})format!("&{}{ty}", mutability.prefix_str())
5071 }
5072 }
5073 ty::Array(ty, len) if let Some(len) = len.try_to_target_usize(tcx) => {
5074 if len == 0 {
5075 "[]".to_string()
5076 } else if self.type_is_copy_modulo_regions(param_env, ty) || len == 1 {
5077 ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("[{0}; {1}]",
self.ty_kind_suggestion(param_env, ty)?, len))
})format!("[{}; {}]", self.ty_kind_suggestion(param_env, ty)?, len)
5079 } else {
5080 "/* value */".to_string()
5081 }
5082 }
5083 ty::Tuple(tys) => ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("({0}{1})",
tys.iter().map(|ty|
self.ty_kind_suggestion(param_env,
ty)).collect::<Option<Vec<String>>>()?.join(", "),
if tys.len() == 1 { "," } else { "" }))
})format!(
5084 "({}{})",
5085 tys.iter()
5086 .map(|ty| self.ty_kind_suggestion(param_env, ty))
5087 .collect::<Option<Vec<String>>>()?
5088 .join(", "),
5089 if tys.len() == 1 { "," } else { "" }
5090 ),
5091 _ => "/* value */".to_string(),
5092 })
5093 }
5094
5095 pub(super) fn suggest_add_result_as_return_type(
5099 &self,
5100 obligation: &PredicateObligation<'tcx>,
5101 err: &mut Diag<'_>,
5102 trait_pred: ty::PolyTraitPredicate<'tcx>,
5103 ) {
5104 if ObligationCauseCode::QuestionMark != *obligation.cause.code().peel_derives() {
5105 return;
5106 }
5107
5108 fn choose_suggest_items<'tcx, 'hir>(
5115 tcx: TyCtxt<'tcx>,
5116 node: hir::Node<'hir>,
5117 ) -> Option<(&'hir hir::FnDecl<'hir>, hir::BodyId)> {
5118 match node {
5119 hir::Node::Item(item)
5120 if let hir::ItemKind::Fn { sig, body: body_id, .. } = item.kind =>
5121 {
5122 Some((sig.decl, body_id))
5123 }
5124 hir::Node::ImplItem(item)
5125 if let hir::ImplItemKind::Fn(sig, body_id) = item.kind =>
5126 {
5127 let parent = tcx.parent_hir_node(item.hir_id());
5128 if let hir::Node::Item(item) = parent
5129 && let hir::ItemKind::Impl(imp) = item.kind
5130 && imp.of_trait.is_none()
5131 {
5132 return Some((sig.decl, body_id));
5133 }
5134 None
5135 }
5136 _ => None,
5137 }
5138 }
5139
5140 let node = self.tcx.hir_node_by_def_id(obligation.cause.body_id);
5141 if let Some((fn_decl, body_id)) = choose_suggest_items(self.tcx, node)
5142 && let hir::FnRetTy::DefaultReturn(ret_span) = fn_decl.output
5143 && self.tcx.is_diagnostic_item(sym::FromResidual, trait_pred.def_id())
5144 && trait_pred.skip_binder().trait_ref.args.type_at(0).is_unit()
5145 && let ty::Adt(def, _) = trait_pred.skip_binder().trait_ref.args.type_at(1).kind()
5146 && self.tcx.is_diagnostic_item(sym::Result, def.did())
5147 {
5148 let mut sugg_spans =
5149 <[_]>::into_vec(::alloc::boxed::box_new([(ret_span,
" -> Result<(), Box<dyn std::error::Error>>".to_string())]))vec![(ret_span, " -> Result<(), Box<dyn std::error::Error>>".to_string())];
5150 let body = self.tcx.hir_body(body_id);
5151 if let hir::ExprKind::Block(b, _) = body.value.kind
5152 && b.expr.is_none()
5153 {
5154 let span = self.tcx.sess.source_map().end_point(b.span);
5156 sugg_spans.push((
5157 span.shrink_to_lo(),
5158 ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("{0}{1}", " Ok(())\n",
self.tcx.sess.source_map().indentation_before(span).unwrap_or_default()))
})format!(
5159 "{}{}",
5160 " Ok(())\n",
5161 self.tcx.sess.source_map().indentation_before(span).unwrap_or_default(),
5162 ),
5163 ));
5164 }
5165 err.multipart_suggestion_verbose(
5166 ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("consider adding return type"))
})format!("consider adding return type"),
5167 sugg_spans,
5168 Applicability::MaybeIncorrect,
5169 );
5170 }
5171 }
5172
5173 #[allow(clippy :: suspicious_else_formatting)]
{
let __tracing_attr_span;
let __tracing_attr_guard;
if ::tracing::Level::DEBUG <= ::tracing::level_filters::STATIC_MAX_LEVEL
&&
::tracing::Level::DEBUG <=
::tracing::level_filters::LevelFilter::current() ||
{ false } {
__tracing_attr_span =
{
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("suggest_unsized_bound_if_applicable",
"rustc_trait_selection::error_reporting::traits::suggestions",
::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs"),
::tracing_core::__macro_support::Option::Some(5173u32),
::tracing_core::__macro_support::Option::Some("rustc_trait_selection::error_reporting::traits::suggestions"),
::tracing_core::field::FieldSet::new(&[],
::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::SPAN)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let mut interest = ::tracing::subscriber::Interest::never();
if ::tracing::Level::DEBUG <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::DEBUG <=
::tracing::level_filters::LevelFilter::current() &&
{ interest = __CALLSITE.interest(); !interest.is_never() }
&&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest) {
let meta = __CALLSITE.metadata();
::tracing::Span::new(meta,
&{ meta.fields().value_set(&[]) })
} else {
let span =
::tracing::__macro_support::__disabled_span(__CALLSITE.metadata());
{};
span
}
};
__tracing_attr_guard = __tracing_attr_span.enter();
}
#[warn(clippy :: suspicious_else_formatting)]
{
#[allow(unknown_lints, unreachable_code, clippy ::
diverging_sub_expression, clippy :: empty_loop, clippy ::
let_unit_value, clippy :: let_with_type_underscore, clippy ::
needless_return, clippy :: unreachable)]
if false {
let __tracing_attr_fake_return: () = loop {};
return __tracing_attr_fake_return;
}
{
let ty::PredicateKind::Clause(ty::ClauseKind::Trait(pred)) =
obligation.predicate.kind().skip_binder() else { return; };
let (ObligationCauseCode::WhereClause(item_def_id, span) |
ObligationCauseCode::WhereClauseInExpr(item_def_id, span,
..)) =
*obligation.cause.code().peel_derives() else { return; };
if span.is_dummy() { return; }
{
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/traits/suggestions.rs:5193",
"rustc_trait_selection::error_reporting::traits::suggestions",
::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs"),
::tracing_core::__macro_support::Option::Some(5193u32),
::tracing_core::__macro_support::Option::Some("rustc_trait_selection::error_reporting::traits::suggestions"),
::tracing_core::field::FieldSet::new(&["pred",
"item_def_id", "span"],
::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(&debug(&pred) as
&dyn Value)),
(&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
::tracing::__macro_support::Option::Some(&debug(&item_def_id)
as &dyn Value)),
(&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
::tracing::__macro_support::Option::Some(&debug(&span) as
&dyn Value))])
});
} else { ; }
};
let (Some(node), true) =
(self.tcx.hir_get_if_local(item_def_id),
self.tcx.is_lang_item(pred.def_id(),
LangItem::Sized)) else { return; };
let Some(generics) = node.generics() else { return; };
let sized_trait = self.tcx.lang_items().sized_trait();
{
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/traits/suggestions.rs:5206",
"rustc_trait_selection::error_reporting::traits::suggestions",
::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs"),
::tracing_core::__macro_support::Option::Some(5206u32),
::tracing_core::__macro_support::Option::Some("rustc_trait_selection::error_reporting::traits::suggestions"),
::tracing_core::field::FieldSet::new(&["generics.params"],
::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(&debug(&generics.params)
as &dyn Value))])
});
} else { ; }
};
{
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/traits/suggestions.rs:5207",
"rustc_trait_selection::error_reporting::traits::suggestions",
::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs"),
::tracing_core::__macro_support::Option::Some(5207u32),
::tracing_core::__macro_support::Option::Some("rustc_trait_selection::error_reporting::traits::suggestions"),
::tracing_core::field::FieldSet::new(&["generics.predicates"],
::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(&debug(&generics.predicates)
as &dyn Value))])
});
} else { ; }
};
let Some(param) =
generics.params.iter().find(|param|
param.span == span) else { return; };
let explicitly_sized =
generics.bounds_for_param(param.def_id).flat_map(|bp|
bp.bounds).any(|bound|
bound.trait_ref().and_then(|tr| tr.trait_def_id()) ==
sized_trait);
if explicitly_sized { return; }
{
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/traits/suggestions.rs:5220",
"rustc_trait_selection::error_reporting::traits::suggestions",
::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs"),
::tracing_core::__macro_support::Option::Some(5220u32),
::tracing_core::__macro_support::Option::Some("rustc_trait_selection::error_reporting::traits::suggestions"),
::tracing_core::field::FieldSet::new(&["param"],
::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(&debug(¶m) as
&dyn Value))])
});
} else { ; }
};
match node {
hir::Node::Item(item @ hir::Item {
kind: hir::ItemKind::Enum(..) | hir::ItemKind::Struct(..) |
hir::ItemKind::Union(..), .. }) => {
if self.suggest_indirection_for_unsized(err, item, param) {
return;
}
}
_ => {}
};
let (span, separator, open_paren_sp) =
if let Some((s, open_paren_sp)) =
generics.bounds_span_for_suggestions(param.def_id) {
(s, " +", open_paren_sp)
} else {
(param.name.ident().span.shrink_to_hi(), ":", None)
};
let mut suggs = ::alloc::vec::Vec::new();
let suggestion =
::alloc::__export::must_use({
::alloc::fmt::format(format_args!("{0} ?Sized", separator))
});
if let Some(open_paren_sp) = open_paren_sp {
suggs.push((open_paren_sp, "(".to_string()));
suggs.push((span,
::alloc::__export::must_use({
::alloc::fmt::format(format_args!("){0}", suggestion))
})));
} else { suggs.push((span, suggestion)); }
err.multipart_suggestion_verbose("consider relaxing the implicit `Sized` restriction",
suggs, Applicability::MachineApplicable);
}
}
}#[instrument(level = "debug", skip_all)]
5174 pub(super) fn suggest_unsized_bound_if_applicable(
5175 &self,
5176 err: &mut Diag<'_>,
5177 obligation: &PredicateObligation<'tcx>,
5178 ) {
5179 let ty::PredicateKind::Clause(ty::ClauseKind::Trait(pred)) =
5180 obligation.predicate.kind().skip_binder()
5181 else {
5182 return;
5183 };
5184 let (ObligationCauseCode::WhereClause(item_def_id, span)
5185 | ObligationCauseCode::WhereClauseInExpr(item_def_id, span, ..)) =
5186 *obligation.cause.code().peel_derives()
5187 else {
5188 return;
5189 };
5190 if span.is_dummy() {
5191 return;
5192 }
5193 debug!(?pred, ?item_def_id, ?span);
5194
5195 let (Some(node), true) = (
5196 self.tcx.hir_get_if_local(item_def_id),
5197 self.tcx.is_lang_item(pred.def_id(), LangItem::Sized),
5198 ) else {
5199 return;
5200 };
5201
5202 let Some(generics) = node.generics() else {
5203 return;
5204 };
5205 let sized_trait = self.tcx.lang_items().sized_trait();
5206 debug!(?generics.params);
5207 debug!(?generics.predicates);
5208 let Some(param) = generics.params.iter().find(|param| param.span == span) else {
5209 return;
5210 };
5211 let explicitly_sized = generics
5214 .bounds_for_param(param.def_id)
5215 .flat_map(|bp| bp.bounds)
5216 .any(|bound| bound.trait_ref().and_then(|tr| tr.trait_def_id()) == sized_trait);
5217 if explicitly_sized {
5218 return;
5219 }
5220 debug!(?param);
5221 match node {
5222 hir::Node::Item(
5223 item @ hir::Item {
5224 kind:
5226 hir::ItemKind::Enum(..) | hir::ItemKind::Struct(..) | hir::ItemKind::Union(..),
5227 ..
5228 },
5229 ) => {
5230 if self.suggest_indirection_for_unsized(err, item, param) {
5231 return;
5232 }
5233 }
5234 _ => {}
5235 };
5236
5237 let (span, separator, open_paren_sp) =
5239 if let Some((s, open_paren_sp)) = generics.bounds_span_for_suggestions(param.def_id) {
5240 (s, " +", open_paren_sp)
5241 } else {
5242 (param.name.ident().span.shrink_to_hi(), ":", None)
5243 };
5244
5245 let mut suggs = vec![];
5246 let suggestion = format!("{separator} ?Sized");
5247
5248 if let Some(open_paren_sp) = open_paren_sp {
5249 suggs.push((open_paren_sp, "(".to_string()));
5250 suggs.push((span, format!("){suggestion}")));
5251 } else {
5252 suggs.push((span, suggestion));
5253 }
5254
5255 err.multipart_suggestion_verbose(
5256 "consider relaxing the implicit `Sized` restriction",
5257 suggs,
5258 Applicability::MachineApplicable,
5259 );
5260 }
5261
5262 fn suggest_indirection_for_unsized(
5263 &self,
5264 err: &mut Diag<'_>,
5265 item: &hir::Item<'tcx>,
5266 param: &hir::GenericParam<'tcx>,
5267 ) -> bool {
5268 let mut visitor = FindTypeParam { param: param.name.ident().name, .. };
5272 visitor.visit_item(item);
5273 if visitor.invalid_spans.is_empty() {
5274 return false;
5275 }
5276 let mut multispan: MultiSpan = param.span.into();
5277 multispan.push_span_label(
5278 param.span,
5279 ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("this could be changed to `{0}: ?Sized`...",
param.name.ident()))
})format!("this could be changed to `{}: ?Sized`...", param.name.ident()),
5280 );
5281 for sp in visitor.invalid_spans {
5282 multispan.push_span_label(
5283 sp,
5284 ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("...if indirection were used here: `Box<{0}>`",
param.name.ident()))
})format!("...if indirection were used here: `Box<{}>`", param.name.ident()),
5285 );
5286 }
5287 err.span_help(
5288 multispan,
5289 ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("you could relax the implicit `Sized` bound on `{0}` if it were used through indirection like `&{0}` or `Box<{0}>`",
param.name.ident()))
})format!(
5290 "you could relax the implicit `Sized` bound on `{T}` if it were \
5291 used through indirection like `&{T}` or `Box<{T}>`",
5292 T = param.name.ident(),
5293 ),
5294 );
5295 true
5296 }
5297 pub(crate) fn suggest_swapping_lhs_and_rhs<T>(
5298 &self,
5299 err: &mut Diag<'_>,
5300 predicate: T,
5301 param_env: ty::ParamEnv<'tcx>,
5302 cause_code: &ObligationCauseCode<'tcx>,
5303 ) where
5304 T: Upcast<TyCtxt<'tcx>, ty::Predicate<'tcx>>,
5305 {
5306 let tcx = self.tcx;
5307 let predicate = predicate.upcast(tcx);
5308 match *cause_code {
5309 ObligationCauseCode::BinOp { lhs_hir_id, rhs_hir_id, rhs_span, .. }
5310 if let Some(typeck_results) = &self.typeck_results
5311 && let hir::Node::Expr(lhs) = tcx.hir_node(lhs_hir_id)
5312 && let hir::Node::Expr(rhs) = tcx.hir_node(rhs_hir_id)
5313 && let Some(lhs_ty) = typeck_results.expr_ty_opt(lhs)
5314 && let Some(rhs_ty) = typeck_results.expr_ty_opt(rhs) =>
5315 {
5316 if let Some(pred) = predicate.as_trait_clause()
5317 && tcx.is_lang_item(pred.def_id(), LangItem::PartialEq)
5318 && self
5319 .infcx
5320 .type_implements_trait(pred.def_id(), [rhs_ty, lhs_ty], param_env)
5321 .must_apply_modulo_regions()
5322 {
5323 let lhs_span = tcx.hir_span(lhs_hir_id);
5324 let sm = tcx.sess.source_map();
5325 if let Ok(rhs_snippet) = sm.span_to_snippet(rhs_span)
5326 && let Ok(lhs_snippet) = sm.span_to_snippet(lhs_span)
5327 {
5328 err.note(::alloc::__export::must_use({
::alloc::fmt::format(format_args!("`{0}` implements `PartialEq<{1}>`",
rhs_ty, lhs_ty))
})format!("`{rhs_ty}` implements `PartialEq<{lhs_ty}>`"));
5329 err.multipart_suggestion(
5330 "consider swapping the equality",
5331 <[_]>::into_vec(::alloc::boxed::box_new([(lhs_span, rhs_snippet),
(rhs_span, lhs_snippet)]))vec![(lhs_span, rhs_snippet), (rhs_span, lhs_snippet)],
5332 Applicability::MaybeIncorrect,
5333 );
5334 }
5335 }
5336 }
5337 _ => {}
5338 }
5339 }
5340}
5341
5342fn hint_missing_borrow<'tcx>(
5344 infcx: &InferCtxt<'tcx>,
5345 param_env: ty::ParamEnv<'tcx>,
5346 span: Span,
5347 found: Ty<'tcx>,
5348 expected: Ty<'tcx>,
5349 found_node: Node<'_>,
5350 err: &mut Diag<'_>,
5351) {
5352 if #[allow(non_exhaustive_omitted_patterns)] match found_node {
Node::TraitItem(..) => true,
_ => false,
}matches!(found_node, Node::TraitItem(..)) {
5353 return;
5354 }
5355
5356 let found_args = match found.kind() {
5357 ty::FnPtr(sig_tys, _) => infcx.enter_forall(*sig_tys, |sig_tys| sig_tys.inputs().iter()),
5358 kind => {
5359 ::rustc_middle::util::bug::span_bug_fmt(span,
format_args!("found was converted to a FnPtr above but is now {0:?}",
kind))span_bug!(span, "found was converted to a FnPtr above but is now {:?}", kind)
5360 }
5361 };
5362 let expected_args = match expected.kind() {
5363 ty::FnPtr(sig_tys, _) => infcx.enter_forall(*sig_tys, |sig_tys| sig_tys.inputs().iter()),
5364 kind => {
5365 ::rustc_middle::util::bug::span_bug_fmt(span,
format_args!("expected was converted to a FnPtr above but is now {0:?}",
kind))span_bug!(span, "expected was converted to a FnPtr above but is now {:?}", kind)
5366 }
5367 };
5368
5369 let Some(fn_decl) = found_node.fn_decl() else {
5371 return;
5372 };
5373
5374 let args = fn_decl.inputs.iter();
5375
5376 let mut to_borrow = Vec::new();
5377 let mut remove_borrow = Vec::new();
5378
5379 for ((found_arg, expected_arg), arg) in found_args.zip(expected_args).zip(args) {
5380 let (found_ty, found_refs) = get_deref_type_and_refs(*found_arg);
5381 let (expected_ty, expected_refs) = get_deref_type_and_refs(*expected_arg);
5382
5383 if infcx.can_eq(param_env, found_ty, expected_ty) {
5384 if found_refs.len() < expected_refs.len()
5386 && found_refs[..] == expected_refs[expected_refs.len() - found_refs.len()..]
5387 {
5388 to_borrow.push((
5389 arg.span.shrink_to_lo(),
5390 expected_refs[..expected_refs.len() - found_refs.len()]
5391 .iter()
5392 .map(|mutbl| ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("&{0}", mutbl.prefix_str()))
})format!("&{}", mutbl.prefix_str()))
5393 .collect::<Vec<_>>()
5394 .join(""),
5395 ));
5396 } else if found_refs.len() > expected_refs.len() {
5397 let mut span = arg.span.shrink_to_lo();
5398 let mut left = found_refs.len() - expected_refs.len();
5399 let mut ty = arg;
5400 while let hir::TyKind::Ref(_, mut_ty) = &ty.kind
5401 && left > 0
5402 {
5403 span = span.with_hi(mut_ty.ty.span.lo());
5404 ty = mut_ty.ty;
5405 left -= 1;
5406 }
5407 if left == 0 {
5408 remove_borrow.push((span, String::new()));
5409 }
5410 }
5411 }
5412 }
5413
5414 if !to_borrow.is_empty() {
5415 err.subdiagnostic(errors::AdjustSignatureBorrow::Borrow { to_borrow });
5416 }
5417
5418 if !remove_borrow.is_empty() {
5419 err.subdiagnostic(errors::AdjustSignatureBorrow::RemoveBorrow { remove_borrow });
5420 }
5421}
5422
5423#[derive(#[automatically_derived]
impl<'v> ::core::fmt::Debug for SelfVisitor<'v> {
#[inline]
fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
::core::fmt::Formatter::debug_struct_field2_finish(f, "SelfVisitor",
"paths", &self.paths, "name", &&self.name)
}
}Debug)]
5426pub struct SelfVisitor<'v> {
5427 pub paths: Vec<&'v hir::Ty<'v>> = Vec::new(),
5428 pub name: Option<Symbol>,
5429}
5430
5431impl<'v> Visitor<'v> for SelfVisitor<'v> {
5432 fn visit_ty(&mut self, ty: &'v hir::Ty<'v, AmbigArg>) {
5433 if let hir::TyKind::Path(path) = ty.kind
5434 && let hir::QPath::TypeRelative(inner_ty, segment) = path
5435 && (Some(segment.ident.name) == self.name || self.name.is_none())
5436 && let hir::TyKind::Path(inner_path) = inner_ty.kind
5437 && let hir::QPath::Resolved(None, inner_path) = inner_path
5438 && let Res::SelfTyAlias { .. } = inner_path.res
5439 {
5440 self.paths.push(ty.as_unambig_ty());
5441 }
5442 hir::intravisit::walk_ty(self, ty);
5443 }
5444}
5445
5446#[derive(#[automatically_derived]
impl<'v> ::core::default::Default for ReturnsVisitor<'v> {
#[inline]
fn default() -> ReturnsVisitor<'v> {
ReturnsVisitor {
returns: ::core::default::Default::default(),
in_block_tail: ::core::default::Default::default(),
}
}
}Default)]
5449pub struct ReturnsVisitor<'v> {
5450 pub returns: Vec<&'v hir::Expr<'v>>,
5451 in_block_tail: bool,
5452}
5453
5454impl<'v> Visitor<'v> for ReturnsVisitor<'v> {
5455 fn visit_expr(&mut self, ex: &'v hir::Expr<'v>) {
5456 match ex.kind {
5461 hir::ExprKind::Ret(Some(ex)) => {
5462 self.returns.push(ex);
5463 }
5464 hir::ExprKind::Block(block, _) if self.in_block_tail => {
5465 self.in_block_tail = false;
5466 for stmt in block.stmts {
5467 hir::intravisit::walk_stmt(self, stmt);
5468 }
5469 self.in_block_tail = true;
5470 if let Some(expr) = block.expr {
5471 self.visit_expr(expr);
5472 }
5473 }
5474 hir::ExprKind::If(_, then, else_opt) if self.in_block_tail => {
5475 self.visit_expr(then);
5476 if let Some(el) = else_opt {
5477 self.visit_expr(el);
5478 }
5479 }
5480 hir::ExprKind::Match(_, arms, _) if self.in_block_tail => {
5481 for arm in arms {
5482 self.visit_expr(arm.body);
5483 }
5484 }
5485 _ if !self.in_block_tail => hir::intravisit::walk_expr(self, ex),
5487 _ => self.returns.push(ex),
5488 }
5489 }
5490
5491 fn visit_body(&mut self, body: &hir::Body<'v>) {
5492 if !!self.in_block_tail {
::core::panicking::panic("assertion failed: !self.in_block_tail")
};assert!(!self.in_block_tail);
5493 self.in_block_tail = true;
5494 hir::intravisit::walk_body(self, body);
5495 }
5496}
5497
5498#[derive(#[automatically_derived]
impl ::core::default::Default for AwaitsVisitor {
#[inline]
fn default() -> AwaitsVisitor {
AwaitsVisitor { awaits: ::core::default::Default::default() }
}
}Default)]
5500struct AwaitsVisitor {
5501 awaits: Vec<HirId>,
5502}
5503
5504impl<'v> Visitor<'v> for AwaitsVisitor {
5505 fn visit_expr(&mut self, ex: &'v hir::Expr<'v>) {
5506 if let hir::ExprKind::Yield(_, hir::YieldSource::Await { expr: Some(id) }) = ex.kind {
5507 self.awaits.push(id)
5508 }
5509 hir::intravisit::walk_expr(self, ex)
5510 }
5511}
5512
5513pub trait NextTypeParamName {
5517 fn next_type_param_name(&self, name: Option<&str>) -> String;
5518}
5519
5520impl NextTypeParamName for &[hir::GenericParam<'_>] {
5521 fn next_type_param_name(&self, name: Option<&str>) -> String {
5522 let name = name.and_then(|n| n.chars().next()).map(|c| c.to_uppercase().to_string());
5524 let name = name.as_deref();
5525
5526 let possible_names = [name.unwrap_or("T"), "T", "U", "V", "X", "Y", "Z", "A", "B", "C"];
5528
5529 let used_names: Vec<Symbol> = self
5531 .iter()
5532 .filter_map(|param| match param.name {
5533 hir::ParamName::Plain(ident) => Some(ident.name),
5534 _ => None,
5535 })
5536 .collect();
5537
5538 possible_names
5540 .iter()
5541 .find(|n| !used_names.contains(&Symbol::intern(n)))
5542 .unwrap_or(&"ParamName")
5543 .to_string()
5544 }
5545}
5546
5547struct ReplaceImplTraitVisitor<'a> {
5549 ty_spans: &'a mut Vec<Span>,
5550 param_did: DefId,
5551}
5552
5553impl<'a, 'hir> hir::intravisit::Visitor<'hir> for ReplaceImplTraitVisitor<'a> {
5554 fn visit_ty(&mut self, t: &'hir hir::Ty<'hir, AmbigArg>) {
5555 if let hir::TyKind::Path(hir::QPath::Resolved(
5556 None,
5557 hir::Path { res: Res::Def(_, segment_did), .. },
5558 )) = t.kind
5559 {
5560 if self.param_did == *segment_did {
5561 self.ty_spans.push(t.span);
5566 return;
5567 }
5568 }
5569
5570 hir::intravisit::walk_ty(self, t);
5571 }
5572}
5573
5574pub(super) fn get_explanation_based_on_obligation<'tcx>(
5575 tcx: TyCtxt<'tcx>,
5576 obligation: &PredicateObligation<'tcx>,
5577 trait_predicate: ty::PolyTraitPredicate<'tcx>,
5578 pre_message: String,
5579 long_ty_path: &mut Option<PathBuf>,
5580) -> String {
5581 if let ObligationCauseCode::MainFunctionType = obligation.cause.code() {
5582 "consider using `()`, or a `Result`".to_owned()
5583 } else {
5584 let ty_desc = match trait_predicate.self_ty().skip_binder().kind() {
5585 ty::FnDef(_, _) => Some("fn item"),
5586 ty::Closure(_, _) => Some("closure"),
5587 _ => None,
5588 };
5589
5590 let desc = match ty_desc {
5591 Some(desc) => ::alloc::__export::must_use({
::alloc::fmt::format(format_args!(" {0}", desc))
})format!(" {desc}"),
5592 None => String::new(),
5593 };
5594 if let ty::PredicatePolarity::Positive = trait_predicate.polarity() {
5595 ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("{3}the {0}trait `{1}` is not implemented for{4} `{2}`",
if tcx.lookup_stability(trait_predicate.def_id()).map(|s|
s.level.is_stable()) == Some(false) {
"nightly-only, unstable "
} else { "" },
trait_predicate.print_modifiers_and_trait_path(),
tcx.short_string(trait_predicate.self_ty().skip_binder(),
long_ty_path), pre_message, desc))
})format!(
5596 "{pre_message}the {}trait `{}` is not implemented for{desc} `{}`",
5597 if tcx.lookup_stability(trait_predicate.def_id()).map(|s| s.level.is_stable())
5598 == Some(false)
5599 {
5600 "nightly-only, unstable "
5601 } else {
5602 ""
5603 },
5604 trait_predicate.print_modifiers_and_trait_path(),
5605 tcx.short_string(trait_predicate.self_ty().skip_binder(), long_ty_path),
5606 )
5607 } else {
5608 ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("{0}the trait bound `{1}` is not satisfied",
pre_message, trait_predicate))
})format!("{pre_message}the trait bound `{trait_predicate}` is not satisfied")
5612 }
5613 }
5614}
5615
5616struct ReplaceImplTraitFolder<'tcx> {
5618 tcx: TyCtxt<'tcx>,
5619 param: &'tcx ty::GenericParamDef,
5620 replace_ty: Ty<'tcx>,
5621}
5622
5623impl<'tcx> TypeFolder<TyCtxt<'tcx>> for ReplaceImplTraitFolder<'tcx> {
5624 fn fold_ty(&mut self, t: Ty<'tcx>) -> Ty<'tcx> {
5625 if let ty::Param(ty::ParamTy { index, .. }) = t.kind() {
5626 if self.param.index == *index {
5627 return self.replace_ty;
5628 }
5629 }
5630 t.super_fold_with(self)
5631 }
5632
5633 fn cx(&self) -> TyCtxt<'tcx> {
5634 self.tcx
5635 }
5636}
5637
5638pub fn suggest_desugaring_async_fn_to_impl_future_in_trait<'tcx>(
5639 tcx: TyCtxt<'tcx>,
5640 sig: hir::FnSig<'tcx>,
5641 body: hir::TraitFn<'tcx>,
5642 opaque_def_id: LocalDefId,
5643 add_bounds: &str,
5644) -> Option<Vec<(Span, String)>> {
5645 let hir::IsAsync::Async(async_span) = sig.header.asyncness else {
5646 return None;
5647 };
5648 let async_span = tcx.sess.source_map().span_extend_while_whitespace(async_span);
5649
5650 let future = tcx.hir_node_by_def_id(opaque_def_id).expect_opaque_ty();
5651 let [hir::GenericBound::Trait(trait_ref)] = future.bounds else {
5652 return None;
5654 };
5655 let Some(hir::PathSegment { args: Some(args), .. }) = trait_ref.trait_ref.path.segments.last()
5656 else {
5657 return None;
5659 };
5660 let Some(future_output_ty) = args.constraints.first().and_then(|constraint| constraint.ty())
5661 else {
5662 return None;
5664 };
5665
5666 let mut sugg = if future_output_ty.span.is_empty() {
5667 <[_]>::into_vec(::alloc::boxed::box_new([(async_span, String::new()),
(future_output_ty.span,
::alloc::__export::must_use({
::alloc::fmt::format(format_args!(" -> impl std::future::Future<Output = ()>{0}",
add_bounds))
}))]))vec![
5668 (async_span, String::new()),
5669 (
5670 future_output_ty.span,
5671 format!(" -> impl std::future::Future<Output = ()>{add_bounds}"),
5672 ),
5673 ]
5674 } else {
5675 <[_]>::into_vec(::alloc::boxed::box_new([(future_output_ty.span.shrink_to_lo(),
"impl std::future::Future<Output = ".to_owned()),
(future_output_ty.span.shrink_to_hi(),
::alloc::__export::must_use({
::alloc::fmt::format(format_args!(">{0}", add_bounds))
})), (async_span, String::new())]))vec![
5676 (future_output_ty.span.shrink_to_lo(), "impl std::future::Future<Output = ".to_owned()),
5677 (future_output_ty.span.shrink_to_hi(), format!(">{add_bounds}")),
5678 (async_span, String::new()),
5679 ]
5680 };
5681
5682 if let hir::TraitFn::Provided(body) = body {
5684 let body = tcx.hir_body(body);
5685 let body_span = body.value.span;
5686 let body_span_without_braces =
5687 body_span.with_lo(body_span.lo() + BytePos(1)).with_hi(body_span.hi() - BytePos(1));
5688 if body_span_without_braces.is_empty() {
5689 sugg.push((body_span_without_braces, " async {} ".to_owned()));
5690 } else {
5691 sugg.extend([
5692 (body_span_without_braces.shrink_to_lo(), "async {".to_owned()),
5693 (body_span_without_braces.shrink_to_hi(), "} ".to_owned()),
5694 ]);
5695 }
5696 }
5697
5698 Some(sugg)
5699}
5700
5701fn point_at_assoc_type_restriction<G: EmissionGuarantee>(
5704 tcx: TyCtxt<'_>,
5705 err: &mut Diag<'_, G>,
5706 self_ty_str: &str,
5707 trait_name: &str,
5708 predicate: ty::Predicate<'_>,
5709 generics: &hir::Generics<'_>,
5710 data: &ImplDerivedCause<'_>,
5711) {
5712 let ty::PredicateKind::Clause(clause) = predicate.kind().skip_binder() else {
5713 return;
5714 };
5715 let ty::ClauseKind::Projection(proj) = clause else {
5716 return;
5717 };
5718 let name = tcx.item_name(proj.projection_term.def_id);
5719 let mut predicates = generics.predicates.iter().peekable();
5720 let mut prev: Option<(&hir::WhereBoundPredicate<'_>, Span)> = None;
5721 while let Some(pred) = predicates.next() {
5722 let curr_span = pred.span;
5723 let hir::WherePredicateKind::BoundPredicate(pred) = pred.kind else {
5724 continue;
5725 };
5726 let mut bounds = pred.bounds.iter();
5727 while let Some(bound) = bounds.next() {
5728 let Some(trait_ref) = bound.trait_ref() else {
5729 continue;
5730 };
5731 if bound.span() != data.span {
5732 continue;
5733 }
5734 if let hir::TyKind::Path(path) = pred.bounded_ty.kind
5735 && let hir::QPath::TypeRelative(ty, segment) = path
5736 && segment.ident.name == name
5737 && let hir::TyKind::Path(inner_path) = ty.kind
5738 && let hir::QPath::Resolved(None, inner_path) = inner_path
5739 && let Res::SelfTyAlias { .. } = inner_path.res
5740 {
5741 let span = if pred.origin == hir::PredicateOrigin::WhereClause
5744 && generics
5745 .predicates
5746 .iter()
5747 .filter(|p| {
5748 #[allow(non_exhaustive_omitted_patterns)] match p.kind {
hir::WherePredicateKind::BoundPredicate(p) if
hir::PredicateOrigin::WhereClause == p.origin => true,
_ => false,
}matches!(
5749 p.kind,
5750 hir::WherePredicateKind::BoundPredicate(p)
5751 if hir::PredicateOrigin::WhereClause == p.origin
5752 )
5753 })
5754 .count()
5755 == 1
5756 {
5757 generics.where_clause_span
5760 } else if let Some(next_pred) = predicates.peek()
5761 && let hir::WherePredicateKind::BoundPredicate(next) = next_pred.kind
5762 && pred.origin == next.origin
5763 {
5764 curr_span.until(next_pred.span)
5766 } else if let Some((prev, prev_span)) = prev
5767 && pred.origin == prev.origin
5768 {
5769 prev_span.shrink_to_hi().to(curr_span)
5771 } else if pred.origin == hir::PredicateOrigin::WhereClause {
5772 curr_span.with_hi(generics.where_clause_span.hi())
5773 } else {
5774 curr_span
5775 };
5776
5777 err.span_suggestion_verbose(
5778 span,
5779 "associated type for the current `impl` cannot be restricted in `where` \
5780 clauses, remove this bound",
5781 "",
5782 Applicability::MaybeIncorrect,
5783 );
5784 }
5785 if let Some(new) =
5786 tcx.associated_items(data.impl_or_alias_def_id).find_by_ident_and_kind(
5787 tcx,
5788 Ident::with_dummy_span(name),
5789 ty::AssocTag::Type,
5790 data.impl_or_alias_def_id,
5791 )
5792 {
5793 let span = tcx.def_span(new.def_id);
5796 err.span_label(
5797 span,
5798 ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("associated type `<{0} as {1}>::{2}` is specified here",
self_ty_str, trait_name, name))
})format!(
5799 "associated type `<{self_ty_str} as {trait_name}>::{name}` is specified \
5800 here",
5801 ),
5802 );
5803 let mut visitor = SelfVisitor { name: Some(name), .. };
5806 visitor.visit_trait_ref(trait_ref);
5807 for path in visitor.paths {
5808 err.span_suggestion_verbose(
5809 path.span,
5810 "replace the associated type with the type specified in this `impl`",
5811 tcx.type_of(new.def_id).skip_binder(),
5812 Applicability::MachineApplicable,
5813 );
5814 }
5815 } else {
5816 let mut visitor = SelfVisitor { name: None, .. };
5817 visitor.visit_trait_ref(trait_ref);
5818 let span: MultiSpan =
5819 visitor.paths.iter().map(|p| p.span).collect::<Vec<Span>>().into();
5820 err.span_note(
5821 span,
5822 "associated types for the current `impl` cannot be restricted in `where` \
5823 clauses",
5824 );
5825 }
5826 }
5827 prev = Some((pred, curr_span));
5828 }
5829}
5830
5831fn get_deref_type_and_refs(mut ty: Ty<'_>) -> (Ty<'_>, Vec<hir::Mutability>) {
5832 let mut refs = ::alloc::vec::Vec::new()vec![];
5833
5834 while let ty::Ref(_, new_ty, mutbl) = ty.kind() {
5835 ty = *new_ty;
5836 refs.push(*mutbl);
5837 }
5838
5839 (ty, refs)
5840}
5841
5842struct FindTypeParam {
5845 param: rustc_span::Symbol,
5846 invalid_spans: Vec<Span> = Vec::new(),
5847 nested: bool = false,
5848}
5849
5850impl<'v> Visitor<'v> for FindTypeParam {
5851 fn visit_where_predicate(&mut self, _: &'v hir::WherePredicate<'v>) {
5852 }
5854
5855 fn visit_ty(&mut self, ty: &hir::Ty<'_, AmbigArg>) {
5856 match ty.kind {
5863 hir::TyKind::Ptr(_) | hir::TyKind::Ref(..) | hir::TyKind::TraitObject(..) => {}
5864 hir::TyKind::Path(hir::QPath::Resolved(None, path))
5865 if let [segment] = path.segments
5866 && segment.ident.name == self.param =>
5867 {
5868 if !self.nested {
5869 {
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/traits/suggestions.rs:5869",
"rustc_trait_selection::error_reporting::traits::suggestions",
::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs"),
::tracing_core::__macro_support::Option::Some(5869u32),
::tracing_core::__macro_support::Option::Some("rustc_trait_selection::error_reporting::traits::suggestions"),
::tracing_core::field::FieldSet::new(&["message", "ty"],
::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!("FindTypeParam::visit_ty")
as &dyn Value)),
(&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
::tracing::__macro_support::Option::Some(&debug(&ty) as
&dyn Value))])
});
} else { ; }
};debug!(?ty, "FindTypeParam::visit_ty");
5870 self.invalid_spans.push(ty.span);
5871 }
5872 }
5873 hir::TyKind::Path(_) => {
5874 let prev = self.nested;
5875 self.nested = true;
5876 hir::intravisit::walk_ty(self, ty);
5877 self.nested = prev;
5878 }
5879 _ => {
5880 hir::intravisit::walk_ty(self, ty);
5881 }
5882 }
5883 }
5884}
5885
5886struct ParamFinder {
5889 params: Vec<Symbol> = Vec::new(),
5890}
5891
5892impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for ParamFinder {
5893 fn visit_ty(&mut self, t: Ty<'tcx>) -> Self::Result {
5894 match t.kind() {
5895 ty::Param(p) => self.params.push(p.name),
5896 _ => {}
5897 }
5898 t.super_visit_with(self)
5899 }
5900}
5901
5902impl ParamFinder {
5903 fn can_suggest_bound(&self, generics: &hir::Generics<'_>) -> bool {
5906 if self.params.is_empty() {
5907 return true;
5910 }
5911 generics.params.iter().any(|p| match p.name {
5912 hir::ParamName::Plain(p_name) => {
5913 self.params.iter().any(|p| *p == p_name.name || *p == kw::SelfUpper)
5915 }
5916 _ => true,
5917 })
5918 }
5919}