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