1use std::fmt;
2
3use rustc_data_structures::intern::Interned;
4use rustc_errors::{Applicability, Diag, IntoDiagArg};
5use rustc_hir as hir;
6use rustc_hir::def::{DefKind, Namespace};
7use rustc_hir::def_id::{CRATE_DEF_ID, DefId};
8use rustc_middle::ty::error::ExpectedFound;
9use rustc_middle::ty::print::{FmtPrinter, Print, PrintTraitRefExt as _, RegionHighlightMode};
10use rustc_middle::ty::{self, GenericArgsRef, IsSuggestable, RePlaceholder, Region, TyCtxt};
11use rustc_span::{Span, bug};
12use rustc_structures::Limit;
13use tracing::{debug, instrument};
14
15use crate::diagnostics::{
16 ActualImplExpectedKind, ActualImplExpectedLifetimeKind, ActualImplExplNotes,
17 TraitPlaceholderMismatch, TyOrSig,
18};
19use crate::error_reporting::infer::nice_region_error::NiceRegionError;
20use crate::infer::{RegionResolutionError, SubregionOrigin, TypeTrace, ValuePairs};
21use crate::traits::{ObligationCause, ObligationCauseCode};
22
23#[derive(#[automatically_derived]
impl<'tcx, T: ::core::marker::Copy> ::core::marker::Copy for
Highlighted<'tcx, T> {
}Copy, #[automatically_derived]
impl<'tcx, T: ::core::clone::Clone> ::core::clone::Clone for
Highlighted<'tcx, T> {
#[inline]
fn clone(&self) -> Self {
Highlighted {
tcx: ::core::clone::Clone::clone(&self.tcx),
highlight: ::core::clone::Clone::clone(&self.highlight),
value: ::core::clone::Clone::clone(&self.value),
ns: ::core::clone::Clone::clone(&self.ns),
}
}
}Clone)]
24pub(crate) struct Highlighted<'tcx, T> {
25 pub tcx: TyCtxt<'tcx>,
26 pub highlight: RegionHighlightMode<'tcx>,
27 pub value: T,
28 pub ns: Namespace,
29}
30
31impl<'tcx, T> IntoDiagArg for Highlighted<'tcx, T>
32where
33 T: for<'a> Print<FmtPrinter<'a, 'tcx>> + Copy,
34{
35 fn into_diag_arg(self, _: &mut Option<std::path::PathBuf>) -> rustc_errors::DiagArgValue {
36 rustc_errors::DiagArgValue::Str(self.to_string().into())
37 }
38}
39
40impl<'tcx, T> Highlighted<'tcx, T> {
41 fn map<U>(self, f: impl FnOnce(T) -> U) -> Highlighted<'tcx, U> {
42 Highlighted { tcx: self.tcx, highlight: self.highlight, value: f(self.value), ns: self.ns }
43 }
44}
45
46impl<'tcx, T> fmt::Display for Highlighted<'tcx, T>
47where
48 T: for<'a> Print<FmtPrinter<'a, 'tcx>> + Copy,
49{
50 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
51 let mut p = ty::print::FmtPrinter::new(self.tcx, self.ns);
52 p.region_highlight_mode = self.highlight;
53
54 self.value.print(&mut p)?;
55 let b = p.into_buffer();
56 if b.len() <= 40 || !self.highlight.keep_regions || self.tcx.sess.opts.verbose {
57 f.write_str(&b)?;
60 } else {
61 let mut p = FmtPrinter::new_with_limit(self.tcx, self.ns, Limit(0));
64 p.region_highlight_mode = self.highlight;
65 self.value.print(&mut p).expect("could not print type");
66 let x = p.into_buffer();
67 f.write_str(&x)?;
68 }
69 Ok(())
70 }
71}
72
73impl<'tcx> NiceRegionError<'_, 'tcx> {
74 pub(super) fn try_report_placeholder_conflict(&self) -> Option<Diag<'tcx>> {
77 match &self.error {
78 Some(RegionResolutionError::SubSupConflict(
88 vid,
89 _,
90 SubregionOrigin::Subtype(TypeTrace { cause, values }),
91 sub_placeholder @ Region(Interned(RePlaceholder(_), _)),
92 _,
93 sup_placeholder @ Region(Interned(RePlaceholder(_), _)),
94 _,
95 )) => self.try_report_trait_placeholder_mismatch(
96 Some(ty::Region::new_var(self.tcx(), *vid)),
97 cause,
98 Some(*sub_placeholder),
99 Some(*sup_placeholder),
100 values,
101 ),
102
103 Some(RegionResolutionError::SubSupConflict(
104 vid,
105 _,
106 SubregionOrigin::Subtype(TypeTrace { cause, values }),
107 sub_placeholder @ Region(Interned(RePlaceholder(_), _)),
108 _,
109 _,
110 _,
111 )) => self.try_report_trait_placeholder_mismatch(
112 Some(ty::Region::new_var(self.tcx(), *vid)),
113 cause,
114 Some(*sub_placeholder),
115 None,
116 values,
117 ),
118
119 Some(RegionResolutionError::SubSupConflict(
120 vid,
121 _,
122 SubregionOrigin::Subtype(TypeTrace { cause, values }),
123 _,
124 _,
125 sup_placeholder @ Region(Interned(RePlaceholder(_), _)),
126 _,
127 )) => self.try_report_trait_placeholder_mismatch(
128 Some(ty::Region::new_var(self.tcx(), *vid)),
129 cause,
130 None,
131 Some(*sup_placeholder),
132 values,
133 ),
134
135 Some(RegionResolutionError::SubSupConflict(
136 vid,
137 _,
138 _,
139 _,
140 SubregionOrigin::Subtype(TypeTrace { cause, values }),
141 sup_placeholder @ Region(Interned(RePlaceholder(_), _)),
142 _,
143 )) => self.try_report_trait_placeholder_mismatch(
144 Some(ty::Region::new_var(self.tcx(), *vid)),
145 cause,
146 None,
147 Some(*sup_placeholder),
148 values,
149 ),
150
151 Some(RegionResolutionError::UpperBoundUniverseConflict(
152 vid,
153 _,
154 _,
155 SubregionOrigin::Subtype(TypeTrace { cause, values }),
156 sup_placeholder @ Region(Interned(RePlaceholder(_), _)),
157 )) => self.try_report_trait_placeholder_mismatch(
158 Some(ty::Region::new_var(self.tcx(), *vid)),
159 cause,
160 None,
161 Some(*sup_placeholder),
162 values,
163 ),
164
165 Some(RegionResolutionError::ConcreteFailure(
166 SubregionOrigin::Subtype(TypeTrace { cause, values }),
167 sub_region @ Region(Interned(RePlaceholder(_), _)),
168 sup_region @ Region(Interned(RePlaceholder(_), _)),
169 )) => self.try_report_trait_placeholder_mismatch(
170 None,
171 cause,
172 Some(*sub_region),
173 Some(*sup_region),
174 values,
175 ),
176
177 Some(RegionResolutionError::ConcreteFailure(
178 SubregionOrigin::Subtype(TypeTrace { cause, values }),
179 sub_region @ Region(Interned(RePlaceholder(_), _)),
180 sup_region,
181 )) => self.try_report_trait_placeholder_mismatch(
182 (!sup_region.is_named(self.tcx())).then_some(*sup_region),
183 cause,
184 Some(*sub_region),
185 None,
186 values,
187 ),
188
189 Some(RegionResolutionError::ConcreteFailure(
190 SubregionOrigin::Subtype(TypeTrace { cause, values }),
191 sub_region,
192 sup_region @ Region(Interned(RePlaceholder(_), _)),
193 )) => self.try_report_trait_placeholder_mismatch(
194 (!sub_region.is_named(self.tcx())).then_some(*sub_region),
195 cause,
196 None,
197 Some(*sup_region),
198 values,
199 ),
200
201 _ => None,
202 }
203 }
204
205 fn try_report_trait_placeholder_mismatch(
206 &self,
207 vid: Option<Region<'tcx>>,
208 cause: &ObligationCause<'tcx>,
209 sub_placeholder: Option<Region<'tcx>>,
210 sup_placeholder: Option<Region<'tcx>>,
211 value_pairs: &ValuePairs<'tcx>,
212 ) -> Option<Diag<'tcx>> {
213 let (expected_args, found_args, trait_def_id) = match value_pairs {
214 ValuePairs::TraitRefs(ExpectedFound { expected, found })
215 if expected.def_id == found.def_id =>
216 {
217 (expected.args, found.args, expected.def_id)
221 }
222 _ => return None,
223 };
224
225 Some(self.report_trait_placeholder_mismatch(
226 vid,
227 cause,
228 sub_placeholder,
229 sup_placeholder,
230 trait_def_id,
231 expected_args,
232 found_args,
233 ))
234 }
235
236 {}
#[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("report_trait_placeholder_mismatch",
"rustc_trait_selection::error_reporting::infer::nice_region_error::placeholder_error",
::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("/rustc-dev/a30aa9064df6a504b6a323c6884a2f4cfbfff666/compiler/rustc_trait_selection/src/error_reporting/infer/nice_region_error/placeholder_error.rs"),
::tracing_core::__macro_support::Option::Some(245u32),
::tracing_core::__macro_support::Option::Some("rustc_trait_selection::error_reporting::infer::nice_region_error::placeholder_error"),
::tracing_core::field::FieldSet::new(&[{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("vid")
}> =
::tracing::__macro_support::FieldName::new("vid");
NAME.as_str()
},
{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("cause")
}> =
::tracing::__macro_support::FieldName::new("cause");
NAME.as_str()
},
{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("sub_placeholder")
}> =
::tracing::__macro_support::FieldName::new("sub_placeholder");
NAME.as_str()
},
{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("sup_placeholder")
}> =
::tracing::__macro_support::FieldName::new("sup_placeholder");
NAME.as_str()
},
{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("trait_def_id")
}> =
::tracing::__macro_support::FieldName::new("trait_def_id");
NAME.as_str()
},
{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("expected_args")
}> =
::tracing::__macro_support::FieldName::new("expected_args");
NAME.as_str()
},
{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("actual_args")
}> =
::tracing::__macro_support::FieldName::new("actual_args");
NAME.as_str()
}], ::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};
meta.fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&vid)
as &dyn ::tracing::field::Value)),
(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&cause)
as &dyn ::tracing::field::Value)),
(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&sub_placeholder)
as &dyn ::tracing::field::Value)),
(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&sup_placeholder)
as &dyn ::tracing::field::Value)),
(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&trait_def_id)
as &dyn ::tracing::field::Value)),
(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&expected_args)
as &dyn ::tracing::field::Value)),
(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&actual_args)
as &dyn ::tracing::field::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: Diag<'tcx> = loop {};
return __tracing_attr_fake_return;
}
{
let span = cause.span;
let mut code = cause.code();
loop {
match code {
ObligationCauseCode::MatchImpl(inner_cause, _) => {
code = inner_cause.code();
}
ObligationCauseCode::ImplDerived(derived) => {
code = &derived.derived.parent_code;
}
ObligationCauseCode::BuiltinDerived(derived) => {
code = &derived.parent_code;
}
ObligationCauseCode::WellFormedDerived(derived) => {
code = &derived.parent_code;
}
ObligationCauseCode::ImplDerivedHost(derived) => {
code = &derived.derived.parent_code;
}
ObligationCauseCode::BuiltinDerivedHost(derived) => {
code = &derived.parent_code;
}
_ => break,
}
}
let (mut satisfy_span, mut item_span, outer_span, dup_span,
item_name) =
if let ObligationCauseCode::WhereClause(def_id, span) |
ObligationCauseCode::WhereClauseInExpr(def_id, span, ..) =
*code && def_id != CRATE_DEF_ID.to_def_id() {
let parent = self.tcx().parent(def_id);
(Some(span),
Some(self.tcx().opt_item_ident(def_id).map_or_else(||
self.tcx().def_span(def_id), |n| n.span)),
if let DefKind::Trait | DefKind::Impl { .. } =
self.tcx().def_kind(parent) {
Some(self.tcx().def_span(parent).shrink_to_lo())
} else { None }, None, self.tcx().def_path_str(def_id))
} else { (None, None, None, Some(span), String::new()) };
if let Some(span) = satisfy_span && span.is_dummy() {
satisfy_span = None;
}
if let Some(span) = item_span && span.is_dummy() {
item_span = None;
}
let expected_trait_ref =
self.cx.deeply_resolve_ignoring_regions(ty::TraitRef::new_from_args(self.cx.tcx,
trait_def_id, expected_args));
let actual_trait_ref =
self.cx.deeply_resolve_ignoring_regions(ty::TraitRef::new_from_args(self.cx.tcx,
trait_def_id, actual_args));
let mut counter = 0;
let mut has_sub = None;
let mut has_sup = None;
let mut actual_has_vid = None;
let mut expected_has_vid = None;
self.tcx().for_each_free_region(&expected_trait_ref,
|r|
{
if Some(r) == sub_placeholder && has_sub.is_none() {
has_sub = Some(counter);
counter += 1;
} else if Some(r) == sup_placeholder && has_sup.is_none() {
has_sup = Some(counter);
counter += 1;
}
if Some(r) == vid && expected_has_vid.is_none() {
expected_has_vid = Some(counter);
counter += 1;
}
});
self.tcx().for_each_free_region(&actual_trait_ref,
|r|
{
if Some(r) == vid && actual_has_vid.is_none() {
actual_has_vid = Some(counter);
counter += 1;
}
});
let actual_self_ty_has_vid =
self.tcx().any_free_region_meets(&actual_trait_ref.self_ty(),
|r| Some(r) == vid);
let expected_self_ty_has_vid =
self.tcx().any_free_region_meets(&expected_trait_ref.self_ty(),
|r| Some(r) == vid);
let any_self_ty_has_vid =
actual_self_ty_has_vid || expected_self_ty_has_vid;
{
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("event /rustc-dev/a30aa9064df6a504b6a323c6884a2f4cfbfff666/compiler/rustc_trait_selection/src/error_reporting/infer/nice_region_error/placeholder_error.rs:367",
"rustc_trait_selection::error_reporting::infer::nice_region_error::placeholder_error",
::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("/rustc-dev/a30aa9064df6a504b6a323c6884a2f4cfbfff666/compiler/rustc_trait_selection/src/error_reporting/infer/nice_region_error/placeholder_error.rs"),
::tracing_core::__macro_support::Option::Some(367u32),
::tracing_core::__macro_support::Option::Some("rustc_trait_selection::error_reporting::infer::nice_region_error::placeholder_error"),
::tracing_core::field::FieldSet::new(&[{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("actual_has_vid")
}> =
::tracing::__macro_support::FieldName::new("actual_has_vid");
NAME.as_str()
},
{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("expected_has_vid")
}> =
::tracing::__macro_support::FieldName::new("expected_has_vid");
NAME.as_str()
},
{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("has_sub")
}> =
::tracing::__macro_support::FieldName::new("has_sub");
NAME.as_str()
},
{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("has_sup")
}> =
::tracing::__macro_support::FieldName::new("has_sup");
NAME.as_str()
},
{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("actual_self_ty_has_vid")
}> =
::tracing::__macro_support::FieldName::new("actual_self_ty_has_vid");
NAME.as_str()
},
{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("expected_self_ty_has_vid")
}> =
::tracing::__macro_support::FieldName::new("expected_self_ty_has_vid");
NAME.as_str()
}], ::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};
__CALLSITE.metadata().fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&actual_has_vid)
as &dyn ::tracing::field::Value)),
(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&expected_has_vid)
as &dyn ::tracing::field::Value)),
(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&has_sub)
as &dyn ::tracing::field::Value)),
(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&has_sup)
as &dyn ::tracing::field::Value)),
(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&actual_self_ty_has_vid)
as &dyn ::tracing::field::Value)),
(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&expected_self_ty_has_vid)
as &dyn ::tracing::field::Value))])
});
} else { ; }
};
let actual_impl_expl_notes =
self.explain_actual_impl_that_was_found(sub_placeholder,
sup_placeholder, has_sub, has_sup, expected_trait_ref,
actual_trait_ref, vid, expected_has_vid, actual_has_vid,
any_self_ty_has_vid, satisfy_span, item_span, outer_span,
item_name);
let mut err =
self.tcx().dcx().create_err(TraitPlaceholderMismatch {
span,
dup_span,
trait_def_id: self.tcx().def_path_str(trait_def_id),
actual_impl_expl_notes,
});
let mut current_code = cause.code();
let mut coroutine_def_id = None;
if cause.body_def_id != CRATE_DEF_ID {
if let ObligationCauseCode::WhereClause(..) |
ObligationCauseCode::WhereClauseInExpr(..) = *code
{} else {
self.cx.note_obligation_cause_code(cause.body_def_id,
&mut err, actual_trait_ref,
self.tcx().param_env(cause.body_def_id), cause.code(),
&mut ::alloc::vec::Vec::new(), &mut Default::default());
}
}
loop {
match current_code {
ObligationCauseCode::MatchImpl(inner_cause, _) => {
current_code = inner_cause.code();
}
ObligationCauseCode::BuiltinDerived(derived) => {
let self_ty =
derived.parent_trait_pred.skip_binder().self_ty();
if let ty::Coroutine(def_id, _) |
ty::CoroutineWitness(def_id, _) = self_ty.kind() {
coroutine_def_id = Some(*def_id);
break;
}
current_code = &derived.parent_code;
}
_ => break,
}
}
if let Some(def_id) = coroutine_def_id {
if self.tcx().trait_is_auto(trait_def_id) {
let c_span = self.tcx().def_span(def_id);
let descr = self.tcx().def_descr(def_id);
let trait_name = self.tcx().def_path_str(trait_def_id);
err.span_label(c_span,
::alloc::__export::must_use({
::alloc::fmt::format(format_args!("this {0} captures a value whose type is not `{1}`",
descr, trait_name))
}));
}
}
if self.tcx().is_fn_trait(trait_def_id) {
let actual_self_ty =
self.cx.deeply_resolve_ignoring_regions(ty::TraitRef::new_from_args(self.cx.tcx,
trait_def_id, actual_args).self_ty());
if let ty::Closure(closure_def_id, _) = *actual_self_ty.kind()
&& let Some(local_def_id) = closure_def_id.as_local() &&
let hir::Node::Expr(hir::Expr {
kind: hir::ExprKind::Closure(closure), .. }) =
self.tcx().hir_node_by_def_id(local_def_id) {
let body = self.tcx().hir_body(closure.body);
let expected_input_tys = expected_args.type_at(1);
if let ty::Tuple(input_tys) = *expected_input_tys.kind() {
let suggestions: Vec<_> =
body.params.iter().zip(input_tys.iter()).filter_map(|(param,
ty)|
{
if param.ty_span == param.pat.span &&
ty.is_suggestable(self.tcx(), false) {
Some((param.pat.span.shrink_to_hi(),
::alloc::__export::must_use({
::alloc::fmt::format(format_args!(": {0}", ty))
})))
} else { None }
}).collect();
if !suggestions.is_empty() {
let msg =
if suggestions.len() == 1 {
"consider adding an explicit type annotation to the closure's argument"
} else {
"consider adding explicit type annotations to the closure's arguments"
};
err.multipart_suggestion(msg, suggestions,
Applicability::MaybeIncorrect);
}
}
}
}
err
}
}
}#[instrument(level = "debug", skip(self))]
246 fn report_trait_placeholder_mismatch(
247 &self,
248 vid: Option<Region<'tcx>>,
249 cause: &ObligationCause<'tcx>,
250 sub_placeholder: Option<Region<'tcx>>,
251 sup_placeholder: Option<Region<'tcx>>,
252 trait_def_id: DefId,
253 expected_args: GenericArgsRef<'tcx>,
254 actual_args: GenericArgsRef<'tcx>,
255 ) -> Diag<'tcx> {
256 let span = cause.span;
257
258 let mut code = cause.code();
259 loop {
260 match code {
261 ObligationCauseCode::MatchImpl(inner_cause, _) => {
262 code = inner_cause.code();
263 }
264 ObligationCauseCode::ImplDerived(derived) => {
265 code = &derived.derived.parent_code;
266 }
267 ObligationCauseCode::BuiltinDerived(derived) => {
268 code = &derived.parent_code;
269 }
270 ObligationCauseCode::WellFormedDerived(derived) => {
271 code = &derived.parent_code;
272 }
273 ObligationCauseCode::ImplDerivedHost(derived) => {
274 code = &derived.derived.parent_code;
275 }
276 ObligationCauseCode::BuiltinDerivedHost(derived) => {
277 code = &derived.parent_code;
278 }
279 _ => break,
280 }
281 }
282 let (mut satisfy_span, mut item_span, outer_span, dup_span, item_name) =
283 if let ObligationCauseCode::WhereClause(def_id, span)
284 | ObligationCauseCode::WhereClauseInExpr(def_id, span, ..) = *code
285 && def_id != CRATE_DEF_ID.to_def_id()
286 {
287 let parent = self.tcx().parent(def_id);
288 (
289 Some(span),
290 Some(
291 self.tcx()
292 .opt_item_ident(def_id)
293 .map_or_else(|| self.tcx().def_span(def_id), |n| n.span),
294 ),
295 if let DefKind::Trait | DefKind::Impl { .. } = self.tcx().def_kind(parent) {
296 Some(self.tcx().def_span(parent).shrink_to_lo())
297 } else {
298 None
299 },
300 None,
301 self.tcx().def_path_str(def_id),
302 )
303 } else {
304 (None, None, None, Some(span), String::new())
305 };
306 if let Some(span) = satisfy_span
307 && span.is_dummy()
308 {
309 satisfy_span = None;
310 }
311 if let Some(span) = item_span
312 && span.is_dummy()
313 {
314 item_span = None;
315 }
316
317 let expected_trait_ref = self.cx.deeply_resolve_ignoring_regions(
318 ty::TraitRef::new_from_args(self.cx.tcx, trait_def_id, expected_args),
319 );
320 let actual_trait_ref = self.cx.deeply_resolve_ignoring_regions(
321 ty::TraitRef::new_from_args(self.cx.tcx, trait_def_id, actual_args),
322 );
323
324 let mut counter = 0;
331 let mut has_sub = None;
332 let mut has_sup = None;
333
334 let mut actual_has_vid = None;
335 let mut expected_has_vid = None;
336
337 self.tcx().for_each_free_region(&expected_trait_ref, |r| {
338 if Some(r) == sub_placeholder && has_sub.is_none() {
339 has_sub = Some(counter);
340 counter += 1;
341 } else if Some(r) == sup_placeholder && has_sup.is_none() {
342 has_sup = Some(counter);
343 counter += 1;
344 }
345
346 if Some(r) == vid && expected_has_vid.is_none() {
347 expected_has_vid = Some(counter);
348 counter += 1;
349 }
350 });
351
352 self.tcx().for_each_free_region(&actual_trait_ref, |r| {
353 if Some(r) == vid && actual_has_vid.is_none() {
354 actual_has_vid = Some(counter);
355 counter += 1;
356 }
357 });
358
359 let actual_self_ty_has_vid =
360 self.tcx().any_free_region_meets(&actual_trait_ref.self_ty(), |r| Some(r) == vid);
361
362 let expected_self_ty_has_vid =
363 self.tcx().any_free_region_meets(&expected_trait_ref.self_ty(), |r| Some(r) == vid);
364
365 let any_self_ty_has_vid = actual_self_ty_has_vid || expected_self_ty_has_vid;
366
367 debug!(
368 ?actual_has_vid,
369 ?expected_has_vid,
370 ?has_sub,
371 ?has_sup,
372 ?actual_self_ty_has_vid,
373 ?expected_self_ty_has_vid,
374 );
375
376 let actual_impl_expl_notes = self.explain_actual_impl_that_was_found(
377 sub_placeholder,
378 sup_placeholder,
379 has_sub,
380 has_sup,
381 expected_trait_ref,
382 actual_trait_ref,
383 vid,
384 expected_has_vid,
385 actual_has_vid,
386 any_self_ty_has_vid,
387 satisfy_span,
388 item_span,
389 outer_span,
390 item_name,
391 );
392
393 let mut err = self.tcx().dcx().create_err(TraitPlaceholderMismatch {
394 span,
395 dup_span,
396 trait_def_id: self.tcx().def_path_str(trait_def_id),
397 actual_impl_expl_notes,
398 });
399
400 let mut current_code = cause.code();
401 let mut coroutine_def_id = None;
402 if cause.body_def_id != CRATE_DEF_ID {
403 if let ObligationCauseCode::WhereClause(..)
404 | ObligationCauseCode::WhereClauseInExpr(..) = *code
405 {
406 } else {
408 self.cx.note_obligation_cause_code(
409 cause.body_def_id,
410 &mut err,
411 actual_trait_ref,
412 self.tcx().param_env(cause.body_def_id),
413 cause.code(),
414 &mut vec![],
415 &mut Default::default(),
416 );
417 }
418 }
419
420 loop {
421 match current_code {
422 ObligationCauseCode::MatchImpl(inner_cause, _) => {
423 current_code = inner_cause.code();
424 }
425 ObligationCauseCode::BuiltinDerived(derived) => {
426 let self_ty = derived.parent_trait_pred.skip_binder().self_ty();
427
428 if let ty::Coroutine(def_id, _) | ty::CoroutineWitness(def_id, _) =
429 self_ty.kind()
430 {
431 coroutine_def_id = Some(*def_id);
432 break;
433 }
434
435 current_code = &derived.parent_code;
436 }
437 _ => break,
438 }
439 }
440
441 if let Some(def_id) = coroutine_def_id {
442 if self.tcx().trait_is_auto(trait_def_id) {
443 let c_span = self.tcx().def_span(def_id);
444 let descr = self.tcx().def_descr(def_id);
445 let trait_name = self.tcx().def_path_str(trait_def_id);
446
447 err.span_label(
448 c_span,
449 format!("this {descr} captures a value whose type is not `{trait_name}`"),
450 );
451 }
452 }
453
454 if self.tcx().is_fn_trait(trait_def_id) {
459 let actual_self_ty = self.cx.deeply_resolve_ignoring_regions(
460 ty::TraitRef::new_from_args(self.cx.tcx, trait_def_id, actual_args).self_ty(),
461 );
462 if let ty::Closure(closure_def_id, _) = *actual_self_ty.kind()
463 && let Some(local_def_id) = closure_def_id.as_local()
464 && let hir::Node::Expr(hir::Expr { kind: hir::ExprKind::Closure(closure), .. }) =
465 self.tcx().hir_node_by_def_id(local_def_id)
466 {
467 let body = self.tcx().hir_body(closure.body);
468 let expected_input_tys = expected_args.type_at(1);
470 if let ty::Tuple(input_tys) = *expected_input_tys.kind() {
471 let suggestions: Vec<_> = body
472 .params
473 .iter()
474 .zip(input_tys.iter())
475 .filter_map(|(param, ty)| {
476 if param.ty_span == param.pat.span
478 && ty.is_suggestable(self.tcx(), false)
479 {
480 Some((param.pat.span.shrink_to_hi(), format!(": {ty}")))
481 } else {
482 None
483 }
484 })
485 .collect();
486 if !suggestions.is_empty() {
487 let msg = if suggestions.len() == 1 {
488 "consider adding an explicit type annotation to the closure's argument"
489 } else {
490 "consider adding explicit type annotations to the closure's arguments"
491 };
492 err.multipart_suggestion(msg, suggestions, Applicability::MaybeIncorrect);
493 }
494 }
495 }
496 }
497
498 err
499 }
500
501 fn explain_actual_impl_that_was_found(
507 &self,
508 sub_placeholder: Option<Region<'tcx>>,
509 sup_placeholder: Option<Region<'tcx>>,
510 has_sub: Option<usize>,
511 has_sup: Option<usize>,
512 expected_trait_ref: ty::TraitRef<'tcx>,
513 actual_trait_ref: ty::TraitRef<'tcx>,
514 vid: Option<Region<'tcx>>,
515 expected_has_vid: Option<usize>,
516 actual_has_vid: Option<usize>,
517 any_self_ty_has_vid: bool,
518 satisfy_span: Option<Span>,
519 item_span: Option<Span>,
520 outer_span: Option<Span>,
521 item_name: String,
522 ) -> Vec<ActualImplExplNotes<'tcx>> {
523 let highlight_trait_ref = |trait_ref| Highlighted {
539 tcx: self.tcx(),
540 highlight: RegionHighlightMode::default(),
541 value: trait_ref,
542 ns: Namespace::TypeNS,
543 };
544
545 let same_self_type = actual_trait_ref.self_ty() == expected_trait_ref.self_ty();
546
547 let mut expected_trait_ref = highlight_trait_ref(expected_trait_ref);
548 expected_trait_ref.highlight.maybe_highlighting_region(sub_placeholder, has_sub);
549 expected_trait_ref.highlight.maybe_highlighting_region(sup_placeholder, has_sup);
550
551 let passive_voice = match (has_sub, has_sup) {
552 (Some(_), _) | (_, Some(_)) => any_self_ty_has_vid,
553 (None, None) => {
554 expected_trait_ref.highlight.maybe_highlighting_region(vid, expected_has_vid);
555 match expected_has_vid {
556 Some(_) => true,
557 None => any_self_ty_has_vid,
558 }
559 }
560 };
561
562 let (kind, ty_or_sig, trait_path) = if same_self_type {
563 let mut self_ty = expected_trait_ref.map(|tr| tr.self_ty());
564 self_ty.highlight.maybe_highlighting_region(vid, actual_has_vid);
565
566 if self_ty.value.is_closure() && self.tcx().is_fn_trait(expected_trait_ref.value.def_id)
567 {
568 let closure_sig = self_ty.map(|closure| {
569 if let ty::Closure(_, args) = closure.kind() {
570 self.tcx()
571 .signature_unclosure(args.as_closure().sig(), rustc_hir::Safety::Safe)
572 } else {
573 ::rustc_span::macros::bug_impl(None,
format_args!("type is not longer closure"), Location::caller());bug!("type is not longer closure");
574 }
575 });
576 (
577 ActualImplExpectedKind::Signature,
578 TyOrSig::ClosureSig(closure_sig),
579 expected_trait_ref.map(|tr| tr.print_only_trait_path()),
580 )
581 } else {
582 (
583 ActualImplExpectedKind::Other,
584 TyOrSig::Ty(self_ty),
585 expected_trait_ref.map(|tr| tr.print_only_trait_path()),
586 )
587 }
588 } else if passive_voice {
589 (
590 ActualImplExpectedKind::Passive,
591 TyOrSig::Ty(expected_trait_ref.map(|tr| tr.self_ty())),
592 expected_trait_ref.map(|tr| tr.print_only_trait_path()),
593 )
594 } else {
595 (
596 ActualImplExpectedKind::Other,
597 TyOrSig::Ty(expected_trait_ref.map(|tr| tr.self_ty())),
598 expected_trait_ref.map(|tr| tr.print_only_trait_path()),
599 )
600 };
601
602 let (lt_kind, lifetime_1, lifetime_2) = match (has_sub, has_sup) {
603 (Some(n1), Some(n2)) => {
604 (ActualImplExpectedLifetimeKind::Two, std::cmp::min(n1, n2), std::cmp::max(n1, n2))
605 }
606 (Some(n), _) | (_, Some(n)) => (ActualImplExpectedLifetimeKind::Any, n, 0),
607 (None, None) => {
608 if let Some(n) = expected_has_vid {
609 (ActualImplExpectedLifetimeKind::Some, n, 0)
610 } else {
611 (ActualImplExpectedLifetimeKind::Nothing, 0, 0)
612 }
613 }
614 };
615
616 let note_1 = ActualImplExplNotes::new_expected(
617 kind,
618 lt_kind,
619 ty_or_sig,
620 trait_path,
621 lifetime_1,
622 lifetime_2,
623 satisfy_span,
624 item_span,
625 outer_span,
626 item_name,
627 );
628
629 let mut actual_trait_ref = highlight_trait_ref(actual_trait_ref);
630 actual_trait_ref.highlight.maybe_highlighting_region(vid, actual_has_vid);
631
632 let passive_voice = match actual_has_vid {
633 Some(_) => any_self_ty_has_vid,
634 None => true,
635 };
636
637 let trait_path = actual_trait_ref.map(|tr| tr.print_only_trait_path());
638 let ty = actual_trait_ref.map(|tr| tr.self_ty()).to_string();
639 let has_lifetime = actual_has_vid.is_some();
640 let lifetime = actual_has_vid.unwrap_or_default();
641
642 let note_2 = if same_self_type {
643 let impl_candidates = self.cx.find_similar_impl_candidates(
644 actual_trait_ref.value.def_id,
645 actual_trait_ref.value.self_ty(),
646 );
647 let span = if let [candidate] = impl_candidates {
648 Some(self.tcx().def_span(candidate.impl_def_id))
649 } else {
650 None
651 };
652 ActualImplExplNotes::ButActuallyImplementsTrait {
653 trait_path,
654 has_lifetime,
655 lifetime,
656 span,
657 }
658 } else if passive_voice {
659 ActualImplExplNotes::ButActuallyImplementedForTy {
660 trait_path,
661 ty,
662 has_lifetime,
663 lifetime,
664 }
665 } else {
666 ActualImplExplNotes::ButActuallyTyImplements { trait_path, ty, has_lifetime, lifetime }
667 };
668
669 ::alloc::boxed::box_assume_init_into_vec_unsafe(::alloc::intrinsics::write_box_via_move(::alloc::boxed::Box::new_uninit(),
[note_1, note_2]))vec![note_1, note_2]
670 }
671}