1use std::fmt;
2
3use rustc_data_structures::Limit;
4use rustc_data_structures::intern::Interned;
5use rustc_errors::{Applicability, Diag, IntoDiagArg};
6use rustc_hir as hir;
7use rustc_hir::def::Namespace;
8use rustc_hir::def_id::{CRATE_DEF_ID, DefId};
9use rustc_middle::bug;
10use rustc_middle::ty::error::ExpectedFound;
11use rustc_middle::ty::print::{FmtPrinter, Print, PrintTraitRefExt as _, RegionHighlightMode};
12use rustc_middle::ty::{
13 self, GenericArgsRef, IsSuggestable, RePlaceholder, Region, RegionExt, RegionUtilitiesExt,
14 TyCtxt,
15};
16use tracing::{debug, instrument};
17
18use crate::diagnostics::{
19 ActualImplExpectedKind, ActualImplExpectedLifetimeKind, ActualImplExplNotes,
20 TraitPlaceholderMismatch, TyOrSig,
21};
22use crate::error_reporting::infer::nice_region_error::NiceRegionError;
23use crate::infer::{RegionResolutionError, SubregionOrigin, TypeTrace, ValuePairs};
24use crate::traits::{ObligationCause, ObligationCauseCode};
25
26#[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) -> Highlighted<'tcx, T> {
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)]
27pub(crate) struct Highlighted<'tcx, T> {
28 pub tcx: TyCtxt<'tcx>,
29 pub highlight: RegionHighlightMode<'tcx>,
30 pub value: T,
31 pub ns: Namespace,
32}
33
34impl<'tcx, T> IntoDiagArg for Highlighted<'tcx, T>
35where
36 T: for<'a> Print<FmtPrinter<'a, 'tcx>> + Copy,
37{
38 fn into_diag_arg(self, _: &mut Option<std::path::PathBuf>) -> rustc_errors::DiagArgValue {
39 rustc_errors::DiagArgValue::Str(self.to_string().into())
40 }
41}
42
43impl<'tcx, T> Highlighted<'tcx, T> {
44 fn map<U>(self, f: impl FnOnce(T) -> U) -> Highlighted<'tcx, U> {
45 Highlighted { tcx: self.tcx, highlight: self.highlight, value: f(self.value), ns: self.ns }
46 }
47}
48
49impl<'tcx, T> fmt::Display for Highlighted<'tcx, T>
50where
51 T: for<'a> Print<FmtPrinter<'a, 'tcx>> + Copy,
52{
53 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
54 let mut p = ty::print::FmtPrinter::new(self.tcx, self.ns);
55 p.region_highlight_mode = self.highlight;
56
57 self.value.print(&mut p)?;
58 let b = p.into_buffer();
59 if b.len() <= 40 || !self.highlight.keep_regions || self.tcx.sess.opts.verbose {
60 f.write_str(&b)?;
63 } else {
64 let mut p = FmtPrinter::new_with_limit(self.tcx, self.ns, Limit(0));
67 p.region_highlight_mode = self.highlight;
68 self.value.print(&mut p).expect("could not print type");
69 let x = p.into_buffer();
70 f.write_str(&x)?;
71 }
72 Ok(())
73 }
74}
75
76impl<'tcx> NiceRegionError<'_, 'tcx> {
77 pub(super) fn try_report_placeholder_conflict(&self) -> Option<Diag<'tcx>> {
80 match &self.error {
81 Some(RegionResolutionError::SubSupConflict(
91 vid,
92 _,
93 SubregionOrigin::Subtype(TypeTrace { cause, values }),
94 sub_placeholder @ Region(Interned(RePlaceholder(_), _)),
95 _,
96 sup_placeholder @ Region(Interned(RePlaceholder(_), _)),
97 _,
98 )) => self.try_report_trait_placeholder_mismatch(
99 Some(ty::Region::new_var(self.tcx(), *vid)),
100 cause,
101 Some(*sub_placeholder),
102 Some(*sup_placeholder),
103 values,
104 ),
105
106 Some(RegionResolutionError::SubSupConflict(
107 vid,
108 _,
109 SubregionOrigin::Subtype(TypeTrace { cause, values }),
110 sub_placeholder @ Region(Interned(RePlaceholder(_), _)),
111 _,
112 _,
113 _,
114 )) => self.try_report_trait_placeholder_mismatch(
115 Some(ty::Region::new_var(self.tcx(), *vid)),
116 cause,
117 Some(*sub_placeholder),
118 None,
119 values,
120 ),
121
122 Some(RegionResolutionError::SubSupConflict(
123 vid,
124 _,
125 SubregionOrigin::Subtype(TypeTrace { cause, values }),
126 _,
127 _,
128 sup_placeholder @ Region(Interned(RePlaceholder(_), _)),
129 _,
130 )) => self.try_report_trait_placeholder_mismatch(
131 Some(ty::Region::new_var(self.tcx(), *vid)),
132 cause,
133 None,
134 Some(*sup_placeholder),
135 values,
136 ),
137
138 Some(RegionResolutionError::SubSupConflict(
139 vid,
140 _,
141 _,
142 _,
143 SubregionOrigin::Subtype(TypeTrace { cause, values }),
144 sup_placeholder @ Region(Interned(RePlaceholder(_), _)),
145 _,
146 )) => self.try_report_trait_placeholder_mismatch(
147 Some(ty::Region::new_var(self.tcx(), *vid)),
148 cause,
149 None,
150 Some(*sup_placeholder),
151 values,
152 ),
153
154 Some(RegionResolutionError::UpperBoundUniverseConflict(
155 vid,
156 _,
157 _,
158 SubregionOrigin::Subtype(TypeTrace { cause, values }),
159 sup_placeholder @ Region(Interned(RePlaceholder(_), _)),
160 )) => self.try_report_trait_placeholder_mismatch(
161 Some(ty::Region::new_var(self.tcx(), *vid)),
162 cause,
163 None,
164 Some(*sup_placeholder),
165 values,
166 ),
167
168 Some(RegionResolutionError::ConcreteFailure(
169 SubregionOrigin::Subtype(TypeTrace { cause, values }),
170 sub_region @ Region(Interned(RePlaceholder(_), _)),
171 sup_region @ Region(Interned(RePlaceholder(_), _)),
172 )) => self.try_report_trait_placeholder_mismatch(
173 None,
174 cause,
175 Some(*sub_region),
176 Some(*sup_region),
177 values,
178 ),
179
180 Some(RegionResolutionError::ConcreteFailure(
181 SubregionOrigin::Subtype(TypeTrace { cause, values }),
182 sub_region @ Region(Interned(RePlaceholder(_), _)),
183 sup_region,
184 )) => self.try_report_trait_placeholder_mismatch(
185 (!sup_region.is_named(self.tcx())).then_some(*sup_region),
186 cause,
187 Some(*sub_region),
188 None,
189 values,
190 ),
191
192 Some(RegionResolutionError::ConcreteFailure(
193 SubregionOrigin::Subtype(TypeTrace { cause, values }),
194 sub_region,
195 sup_region @ Region(Interned(RePlaceholder(_), _)),
196 )) => self.try_report_trait_placeholder_mismatch(
197 (!sub_region.is_named(self.tcx())).then_some(*sub_region),
198 cause,
199 None,
200 Some(*sup_region),
201 values,
202 ),
203
204 _ => None,
205 }
206 }
207
208 fn try_report_trait_placeholder_mismatch(
209 &self,
210 vid: Option<Region<'tcx>>,
211 cause: &ObligationCause<'tcx>,
212 sub_placeholder: Option<Region<'tcx>>,
213 sup_placeholder: Option<Region<'tcx>>,
214 value_pairs: &ValuePairs<'tcx>,
215 ) -> Option<Diag<'tcx>> {
216 let (expected_args, found_args, trait_def_id) = match value_pairs {
217 ValuePairs::TraitRefs(ExpectedFound { expected, found })
218 if expected.def_id == found.def_id =>
219 {
220 (expected.args, found.args, expected.def_id)
224 }
225 _ => return None,
226 };
227
228 Some(self.report_trait_placeholder_mismatch(
229 vid,
230 cause,
231 sub_placeholder,
232 sup_placeholder,
233 trait_def_id,
234 expected_args,
235 found_args,
236 ))
237 }
238
239 #[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("compiler/rustc_trait_selection/src/error_reporting/infer/nice_region_error/placeholder_error.rs"),
::tracing_core::__macro_support::Option::Some(248u32),
::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 (leading_ellipsis, satisfy_span, where_span, dup_span,
def_id) =
if let ObligationCauseCode::WhereClause(def_id, span) |
ObligationCauseCode::WhereClauseInExpr(def_id, span, ..) =
*cause.code() && def_id != CRATE_DEF_ID.to_def_id() {
(true, Some(span), Some(self.tcx().def_span(def_id)), None,
self.tcx().def_path_str(def_id))
} else { (false, None, None, Some(span), String::new()) };
let expected_trait_ref =
self.cx.resolve_vars_if_possible(ty::TraitRef::new_from_args(self.cx.tcx,
trait_def_id, expected_args));
let actual_trait_ref =
self.cx.resolve_vars_if_possible(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 compiler/rustc_trait_selection/src/error_reporting/infer/nice_region_error/placeholder_error.rs:331",
"rustc_trait_selection::error_reporting::infer::nice_region_error::placeholder_error",
::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("compiler/rustc_trait_selection/src/error_reporting/infer/nice_region_error/placeholder_error.rs"),
::tracing_core::__macro_support::Option::Some(331u32),
::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, leading_ellipsis);
let mut err =
self.tcx().dcx().create_err(TraitPlaceholderMismatch {
span,
satisfy_span,
where_span,
dup_span,
def_id,
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;
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.resolve_vars_if_possible(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))]
249 fn report_trait_placeholder_mismatch(
250 &self,
251 vid: Option<Region<'tcx>>,
252 cause: &ObligationCause<'tcx>,
253 sub_placeholder: Option<Region<'tcx>>,
254 sup_placeholder: Option<Region<'tcx>>,
255 trait_def_id: DefId,
256 expected_args: GenericArgsRef<'tcx>,
257 actual_args: GenericArgsRef<'tcx>,
258 ) -> Diag<'tcx> {
259 let span = cause.span;
260
261 let (leading_ellipsis, satisfy_span, where_span, dup_span, def_id) =
262 if let ObligationCauseCode::WhereClause(def_id, span)
263 | ObligationCauseCode::WhereClauseInExpr(def_id, span, ..) = *cause.code()
264 && def_id != CRATE_DEF_ID.to_def_id()
265 {
266 (
267 true,
268 Some(span),
269 Some(self.tcx().def_span(def_id)),
270 None,
271 self.tcx().def_path_str(def_id),
272 )
273 } else {
274 (false, None, None, Some(span), String::new())
275 };
276
277 let expected_trait_ref = self.cx.resolve_vars_if_possible(ty::TraitRef::new_from_args(
278 self.cx.tcx,
279 trait_def_id,
280 expected_args,
281 ));
282 let actual_trait_ref = self.cx.resolve_vars_if_possible(ty::TraitRef::new_from_args(
283 self.cx.tcx,
284 trait_def_id,
285 actual_args,
286 ));
287
288 let mut counter = 0;
295 let mut has_sub = None;
296 let mut has_sup = None;
297
298 let mut actual_has_vid = None;
299 let mut expected_has_vid = None;
300
301 self.tcx().for_each_free_region(&expected_trait_ref, |r| {
302 if Some(r) == sub_placeholder && has_sub.is_none() {
303 has_sub = Some(counter);
304 counter += 1;
305 } else if Some(r) == sup_placeholder && has_sup.is_none() {
306 has_sup = Some(counter);
307 counter += 1;
308 }
309
310 if Some(r) == vid && expected_has_vid.is_none() {
311 expected_has_vid = Some(counter);
312 counter += 1;
313 }
314 });
315
316 self.tcx().for_each_free_region(&actual_trait_ref, |r| {
317 if Some(r) == vid && actual_has_vid.is_none() {
318 actual_has_vid = Some(counter);
319 counter += 1;
320 }
321 });
322
323 let actual_self_ty_has_vid =
324 self.tcx().any_free_region_meets(&actual_trait_ref.self_ty(), |r| Some(r) == vid);
325
326 let expected_self_ty_has_vid =
327 self.tcx().any_free_region_meets(&expected_trait_ref.self_ty(), |r| Some(r) == vid);
328
329 let any_self_ty_has_vid = actual_self_ty_has_vid || expected_self_ty_has_vid;
330
331 debug!(
332 ?actual_has_vid,
333 ?expected_has_vid,
334 ?has_sub,
335 ?has_sup,
336 ?actual_self_ty_has_vid,
337 ?expected_self_ty_has_vid,
338 );
339
340 let actual_impl_expl_notes = self.explain_actual_impl_that_was_found(
341 sub_placeholder,
342 sup_placeholder,
343 has_sub,
344 has_sup,
345 expected_trait_ref,
346 actual_trait_ref,
347 vid,
348 expected_has_vid,
349 actual_has_vid,
350 any_self_ty_has_vid,
351 leading_ellipsis,
352 );
353
354 let mut err = self.tcx().dcx().create_err(TraitPlaceholderMismatch {
355 span,
356 satisfy_span,
357 where_span,
358 dup_span,
359 def_id,
360 trait_def_id: self.tcx().def_path_str(trait_def_id),
361 actual_impl_expl_notes,
362 });
363
364 let mut current_code = cause.code();
365 let mut coroutine_def_id = None;
366
367 loop {
368 match current_code {
369 ObligationCauseCode::MatchImpl(inner_cause, _) => {
370 current_code = inner_cause.code();
371 }
372 ObligationCauseCode::BuiltinDerived(derived) => {
373 let self_ty = derived.parent_trait_pred.skip_binder().self_ty();
374
375 if let ty::Coroutine(def_id, _) | ty::CoroutineWitness(def_id, _) =
376 self_ty.kind()
377 {
378 coroutine_def_id = Some(*def_id);
379 break;
380 }
381
382 current_code = &derived.parent_code;
383 }
384 _ => break,
385 }
386 }
387
388 if let Some(def_id) = coroutine_def_id {
389 if self.tcx().trait_is_auto(trait_def_id) {
390 let c_span = self.tcx().def_span(def_id);
391 let descr = self.tcx().def_descr(def_id);
392 let trait_name = self.tcx().def_path_str(trait_def_id);
393
394 err.span_label(
395 c_span,
396 format!("this {descr} captures a value whose type is not `{trait_name}`"),
397 );
398 }
399 }
400
401 if self.tcx().is_fn_trait(trait_def_id) {
406 let actual_self_ty = self.cx.resolve_vars_if_possible(
407 ty::TraitRef::new_from_args(self.cx.tcx, trait_def_id, actual_args).self_ty(),
408 );
409 if let ty::Closure(closure_def_id, _) = *actual_self_ty.kind()
410 && let Some(local_def_id) = closure_def_id.as_local()
411 && let hir::Node::Expr(hir::Expr { kind: hir::ExprKind::Closure(closure), .. }) =
412 self.tcx().hir_node_by_def_id(local_def_id)
413 {
414 let body = self.tcx().hir_body(closure.body);
415 let expected_input_tys = expected_args.type_at(1);
417 if let ty::Tuple(input_tys) = *expected_input_tys.kind() {
418 let suggestions: Vec<_> = body
419 .params
420 .iter()
421 .zip(input_tys.iter())
422 .filter_map(|(param, ty)| {
423 if param.ty_span == param.pat.span
425 && ty.is_suggestable(self.tcx(), false)
426 {
427 Some((param.pat.span.shrink_to_hi(), format!(": {ty}")))
428 } else {
429 None
430 }
431 })
432 .collect();
433 if !suggestions.is_empty() {
434 let msg = if suggestions.len() == 1 {
435 "consider adding an explicit type annotation to the closure's argument"
436 } else {
437 "consider adding explicit type annotations to the closure's arguments"
438 };
439 err.multipart_suggestion(msg, suggestions, Applicability::MaybeIncorrect);
440 }
441 }
442 }
443 }
444
445 err
446 }
447
448 fn explain_actual_impl_that_was_found(
454 &self,
455 sub_placeholder: Option<Region<'tcx>>,
456 sup_placeholder: Option<Region<'tcx>>,
457 has_sub: Option<usize>,
458 has_sup: Option<usize>,
459 expected_trait_ref: ty::TraitRef<'tcx>,
460 actual_trait_ref: ty::TraitRef<'tcx>,
461 vid: Option<Region<'tcx>>,
462 expected_has_vid: Option<usize>,
463 actual_has_vid: Option<usize>,
464 any_self_ty_has_vid: bool,
465 leading_ellipsis: bool,
466 ) -> Vec<ActualImplExplNotes<'tcx>> {
467 let highlight_trait_ref = |trait_ref| Highlighted {
483 tcx: self.tcx(),
484 highlight: RegionHighlightMode::default(),
485 value: trait_ref,
486 ns: Namespace::TypeNS,
487 };
488
489 let same_self_type = actual_trait_ref.self_ty() == expected_trait_ref.self_ty();
490
491 let mut expected_trait_ref = highlight_trait_ref(expected_trait_ref);
492 expected_trait_ref.highlight.maybe_highlighting_region(sub_placeholder, has_sub);
493 expected_trait_ref.highlight.maybe_highlighting_region(sup_placeholder, has_sup);
494
495 let passive_voice = match (has_sub, has_sup) {
496 (Some(_), _) | (_, Some(_)) => any_self_ty_has_vid,
497 (None, None) => {
498 expected_trait_ref.highlight.maybe_highlighting_region(vid, expected_has_vid);
499 match expected_has_vid {
500 Some(_) => true,
501 None => any_self_ty_has_vid,
502 }
503 }
504 };
505
506 let (kind, ty_or_sig, trait_path) = if same_self_type {
507 let mut self_ty = expected_trait_ref.map(|tr| tr.self_ty());
508 self_ty.highlight.maybe_highlighting_region(vid, actual_has_vid);
509
510 if self_ty.value.is_closure() && self.tcx().is_fn_trait(expected_trait_ref.value.def_id)
511 {
512 let closure_sig = self_ty.map(|closure| {
513 if let ty::Closure(_, args) = closure.kind() {
514 self.tcx()
515 .signature_unclosure(args.as_closure().sig(), rustc_hir::Safety::Safe)
516 } else {
517 ::rustc_middle::util::bug::bug_fmt(format_args!("type is not longer closure"));bug!("type is not longer closure");
518 }
519 });
520 (
521 ActualImplExpectedKind::Signature,
522 TyOrSig::ClosureSig(closure_sig),
523 expected_trait_ref.map(|tr| tr.print_only_trait_path()),
524 )
525 } else {
526 (
527 ActualImplExpectedKind::Other,
528 TyOrSig::Ty(self_ty),
529 expected_trait_ref.map(|tr| tr.print_only_trait_path()),
530 )
531 }
532 } else if passive_voice {
533 (
534 ActualImplExpectedKind::Passive,
535 TyOrSig::Ty(expected_trait_ref.map(|tr| tr.self_ty())),
536 expected_trait_ref.map(|tr| tr.print_only_trait_path()),
537 )
538 } else {
539 (
540 ActualImplExpectedKind::Other,
541 TyOrSig::Ty(expected_trait_ref.map(|tr| tr.self_ty())),
542 expected_trait_ref.map(|tr| tr.print_only_trait_path()),
543 )
544 };
545
546 let (lt_kind, lifetime_1, lifetime_2) = match (has_sub, has_sup) {
547 (Some(n1), Some(n2)) => {
548 (ActualImplExpectedLifetimeKind::Two, std::cmp::min(n1, n2), std::cmp::max(n1, n2))
549 }
550 (Some(n), _) | (_, Some(n)) => (ActualImplExpectedLifetimeKind::Any, n, 0),
551 (None, None) => {
552 if let Some(n) = expected_has_vid {
553 (ActualImplExpectedLifetimeKind::Some, n, 0)
554 } else {
555 (ActualImplExpectedLifetimeKind::Nothing, 0, 0)
556 }
557 }
558 };
559
560 let note_1 = ActualImplExplNotes::new_expected(
561 kind,
562 lt_kind,
563 leading_ellipsis,
564 ty_or_sig,
565 trait_path,
566 lifetime_1,
567 lifetime_2,
568 );
569
570 let mut actual_trait_ref = highlight_trait_ref(actual_trait_ref);
571 actual_trait_ref.highlight.maybe_highlighting_region(vid, actual_has_vid);
572
573 let passive_voice = match actual_has_vid {
574 Some(_) => any_self_ty_has_vid,
575 None => true,
576 };
577
578 let trait_path = actual_trait_ref.map(|tr| tr.print_only_trait_path());
579 let ty = actual_trait_ref.map(|tr| tr.self_ty()).to_string();
580 let has_lifetime = actual_has_vid.is_some();
581 let lifetime = actual_has_vid.unwrap_or_default();
582
583 let note_2 = if same_self_type {
584 ActualImplExplNotes::ButActuallyImplementsTrait { trait_path, has_lifetime, lifetime }
585 } else if passive_voice {
586 ActualImplExplNotes::ButActuallyImplementedForTy {
587 trait_path,
588 ty,
589 has_lifetime,
590 lifetime,
591 }
592 } else {
593 ActualImplExplNotes::ButActuallyTyImplements { trait_path, ty, has_lifetime, lifetime }
594 };
595
596 ::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]
597 }
598}