Skip to main content

rustc_trait_selection/error_reporting/infer/nice_region_error/
placeholder_error.rs

1use std::fmt;
2
3use rustc_data_structures::intern::Interned;
4use rustc_errors::{Diag, IntoDiagArg};
5use rustc_hir::def::Namespace;
6use rustc_hir::def_id::{CRATE_DEF_ID, DefId};
7use rustc_middle::bug;
8use rustc_middle::ty::error::ExpectedFound;
9use rustc_middle::ty::print::{FmtPrinter, Print, PrintTraitRefExt as _, RegionHighlightMode};
10use rustc_middle::ty::{self, GenericArgsRef, RePlaceholder, Region, TyCtxt};
11use tracing::{debug, instrument};
12
13use crate::error_reporting::infer::nice_region_error::NiceRegionError;
14use crate::errors::{
15    ActualImplExpectedKind, ActualImplExpectedLifetimeKind, ActualImplExplNotes,
16    TraitPlaceholderMismatch, TyOrSig,
17};
18use crate::infer::{RegionResolutionError, SubregionOrigin, TypeTrace, ValuePairs};
19use crate::traits::{ObligationCause, ObligationCauseCode};
20
21#[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)]
22pub(crate) struct Highlighted<'tcx, T> {
23    pub tcx: TyCtxt<'tcx>,
24    pub highlight: RegionHighlightMode<'tcx>,
25    pub value: T,
26    pub ns: Namespace,
27}
28
29impl<'tcx, T> IntoDiagArg for Highlighted<'tcx, T>
30where
31    T: for<'a> Print<'tcx, FmtPrinter<'a, 'tcx>>,
32{
33    fn into_diag_arg(self, _: &mut Option<std::path::PathBuf>) -> rustc_errors::DiagArgValue {
34        rustc_errors::DiagArgValue::Str(self.to_string().into())
35    }
36}
37
38impl<'tcx, T> Highlighted<'tcx, T> {
39    fn map<U>(self, f: impl FnOnce(T) -> U) -> Highlighted<'tcx, U> {
40        Highlighted { tcx: self.tcx, highlight: self.highlight, value: f(self.value), ns: self.ns }
41    }
42}
43
44impl<'tcx, T> fmt::Display for Highlighted<'tcx, T>
45where
46    T: for<'a> Print<'tcx, FmtPrinter<'a, 'tcx>>,
47{
48    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
49        let mut p = ty::print::FmtPrinter::new(self.tcx, self.ns);
50        p.region_highlight_mode = self.highlight;
51
52        self.value.print(&mut p)?;
53        f.write_str(&p.into_buffer())
54    }
55}
56
57impl<'tcx> NiceRegionError<'_, 'tcx> {
58    /// When given a `ConcreteFailure` for a function with arguments containing a named region and
59    /// an anonymous region, emit a descriptive diagnostic error.
60    pub(super) fn try_report_placeholder_conflict(&self) -> Option<Diag<'tcx>> {
61        match &self.error {
62            ///////////////////////////////////////////////////////////////////////////
63            // NB. The ordering of cases in this match is very
64            // sensitive, because we are often matching against
65            // specific cases and then using an `_` to match all
66            // others.
67
68            ///////////////////////////////////////////////////////////////////////////
69            // Check for errors from comparing trait failures -- first
70            // with two placeholders, then with one.
71            Some(RegionResolutionError::SubSupConflict(
72                vid,
73                _,
74                SubregionOrigin::Subtype(box TypeTrace { cause, values }),
75                sub_placeholder @ Region(Interned(RePlaceholder(_), _)),
76                _,
77                sup_placeholder @ Region(Interned(RePlaceholder(_), _)),
78                _,
79            )) => self.try_report_trait_placeholder_mismatch(
80                Some(ty::Region::new_var(self.tcx(), *vid)),
81                cause,
82                Some(*sub_placeholder),
83                Some(*sup_placeholder),
84                values,
85            ),
86
87            Some(RegionResolutionError::SubSupConflict(
88                vid,
89                _,
90                SubregionOrigin::Subtype(box TypeTrace { cause, values }),
91                sub_placeholder @ Region(Interned(RePlaceholder(_), _)),
92                _,
93                _,
94                _,
95            )) => self.try_report_trait_placeholder_mismatch(
96                Some(ty::Region::new_var(self.tcx(), *vid)),
97                cause,
98                Some(*sub_placeholder),
99                None,
100                values,
101            ),
102
103            Some(RegionResolutionError::SubSupConflict(
104                vid,
105                _,
106                SubregionOrigin::Subtype(box TypeTrace { cause, values }),
107                _,
108                _,
109                sup_placeholder @ Region(Interned(RePlaceholder(_), _)),
110                _,
111            )) => self.try_report_trait_placeholder_mismatch(
112                Some(ty::Region::new_var(self.tcx(), *vid)),
113                cause,
114                None,
115                Some(*sup_placeholder),
116                values,
117            ),
118
119            Some(RegionResolutionError::SubSupConflict(
120                vid,
121                _,
122                _,
123                _,
124                SubregionOrigin::Subtype(box TypeTrace { cause, values }),
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::UpperBoundUniverseConflict(
136                vid,
137                _,
138                _,
139                SubregionOrigin::Subtype(box TypeTrace { cause, values }),
140                sup_placeholder @ Region(Interned(RePlaceholder(_), _)),
141            )) => self.try_report_trait_placeholder_mismatch(
142                Some(ty::Region::new_var(self.tcx(), *vid)),
143                cause,
144                None,
145                Some(*sup_placeholder),
146                values,
147            ),
148
149            Some(RegionResolutionError::ConcreteFailure(
150                SubregionOrigin::Subtype(box TypeTrace { cause, values }),
151                sub_region @ Region(Interned(RePlaceholder(_), _)),
152                sup_region @ Region(Interned(RePlaceholder(_), _)),
153            )) => self.try_report_trait_placeholder_mismatch(
154                None,
155                cause,
156                Some(*sub_region),
157                Some(*sup_region),
158                values,
159            ),
160
161            Some(RegionResolutionError::ConcreteFailure(
162                SubregionOrigin::Subtype(box TypeTrace { cause, values }),
163                sub_region @ Region(Interned(RePlaceholder(_), _)),
164                sup_region,
165            )) => self.try_report_trait_placeholder_mismatch(
166                (!sup_region.is_named(self.tcx())).then_some(*sup_region),
167                cause,
168                Some(*sub_region),
169                None,
170                values,
171            ),
172
173            Some(RegionResolutionError::ConcreteFailure(
174                SubregionOrigin::Subtype(box TypeTrace { cause, values }),
175                sub_region,
176                sup_region @ Region(Interned(RePlaceholder(_), _)),
177            )) => self.try_report_trait_placeholder_mismatch(
178                (!sub_region.is_named(self.tcx())).then_some(*sub_region),
179                cause,
180                None,
181                Some(*sup_region),
182                values,
183            ),
184
185            _ => None,
186        }
187    }
188
189    fn try_report_trait_placeholder_mismatch(
190        &self,
191        vid: Option<Region<'tcx>>,
192        cause: &ObligationCause<'tcx>,
193        sub_placeholder: Option<Region<'tcx>>,
194        sup_placeholder: Option<Region<'tcx>>,
195        value_pairs: &ValuePairs<'tcx>,
196    ) -> Option<Diag<'tcx>> {
197        let (expected_args, found_args, trait_def_id) = match value_pairs {
198            ValuePairs::TraitRefs(ExpectedFound { expected, found })
199                if expected.def_id == found.def_id =>
200            {
201                // It's possible that the placeholders come from a binder
202                // outside of this value pair. Use `no_bound_vars` as a
203                // simple heuristic for that.
204                (expected.args, found.args, expected.def_id)
205            }
206            _ => return None,
207        };
208
209        Some(self.report_trait_placeholder_mismatch(
210            vid,
211            cause,
212            sub_placeholder,
213            sup_placeholder,
214            trait_def_id,
215            expected_args,
216            found_args,
217        ))
218    }
219
220    // error[E0308]: implementation of `Foo` does not apply to enough lifetimes
221    //   --> /home/nmatsakis/tmp/foo.rs:12:5
222    //    |
223    // 12 |     all::<&'static u32>();
224    //    |     ^^^^^^^^^^^^^^^^^^^ lifetime mismatch
225    //    |
226    //    = note: Due to a where-clause on the function `all`,
227    //    = note: `T` must implement `...` for any two lifetimes `'1` and `'2`.
228    //    = note: However, the type `T` only implements `...` for some specific lifetime `'2`.
229    #[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(229u32),
                                    ::tracing_core::__macro_support::Option::Some("rustc_trait_selection::error_reporting::infer::nice_region_error::placeholder_error"),
                                    ::tracing_core::field::FieldSet::new(&["vid", "cause",
                                                    "sub_placeholder", "sup_placeholder", "trait_def_id",
                                                    "expected_args", "actual_args"],
                                        ::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(&vid)
                                                            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(&cause)
                                                            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(&sub_placeholder)
                                                            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(&sup_placeholder)
                                                            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_def_id)
                                                            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(&expected_args)
                                                            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(&actual_args)
                                                            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: 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:312",
                                    "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(312u32),
                                    ::tracing_core::__macro_support::Option::Some("rustc_trait_selection::error_reporting::infer::nice_region_error::placeholder_error"),
                                    ::tracing_core::field::FieldSet::new(&["actual_has_vid",
                                                    "expected_has_vid", "has_sub", "has_sup",
                                                    "actual_self_ty_has_vid", "expected_self_ty_has_vid"],
                                        ::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(&actual_has_vid)
                                                        as &dyn Value)),
                                            (&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
                                                ::tracing::__macro_support::Option::Some(&debug(&expected_has_vid)
                                                        as &dyn Value)),
                                            (&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
                                                ::tracing::__macro_support::Option::Some(&debug(&has_sub) as
                                                        &dyn Value)),
                                            (&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
                                                ::tracing::__macro_support::Option::Some(&debug(&has_sup) as
                                                        &dyn Value)),
                                            (&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
                                                ::tracing::__macro_support::Option::Some(&debug(&actual_self_ty_has_vid)
                                                        as &dyn Value)),
                                            (&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
                                                ::tracing::__macro_support::Option::Some(&debug(&expected_self_ty_has_vid)
                                                        as &dyn 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);
            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,
                })
        }
    }
}#[instrument(level = "debug", skip(self))]
230    fn report_trait_placeholder_mismatch(
231        &self,
232        vid: Option<Region<'tcx>>,
233        cause: &ObligationCause<'tcx>,
234        sub_placeholder: Option<Region<'tcx>>,
235        sup_placeholder: Option<Region<'tcx>>,
236        trait_def_id: DefId,
237        expected_args: GenericArgsRef<'tcx>,
238        actual_args: GenericArgsRef<'tcx>,
239    ) -> Diag<'tcx> {
240        let span = cause.span;
241
242        let (leading_ellipsis, satisfy_span, where_span, dup_span, def_id) =
243            if let ObligationCauseCode::WhereClause(def_id, span)
244            | ObligationCauseCode::WhereClauseInExpr(def_id, span, ..) = *cause.code()
245                && def_id != CRATE_DEF_ID.to_def_id()
246            {
247                (
248                    true,
249                    Some(span),
250                    Some(self.tcx().def_span(def_id)),
251                    None,
252                    self.tcx().def_path_str(def_id),
253                )
254            } else {
255                (false, None, None, Some(span), String::new())
256            };
257
258        let expected_trait_ref = self.cx.resolve_vars_if_possible(ty::TraitRef::new_from_args(
259            self.cx.tcx,
260            trait_def_id,
261            expected_args,
262        ));
263        let actual_trait_ref = self.cx.resolve_vars_if_possible(ty::TraitRef::new_from_args(
264            self.cx.tcx,
265            trait_def_id,
266            actual_args,
267        ));
268
269        // Search the expected and actual trait references to see (a)
270        // whether the sub/sup placeholders appear in them (sometimes
271        // you have a trait ref like `T: Foo<fn(&u8)>`, where the
272        // placeholder was created as part of an inner type) and (b)
273        // whether the inference variable appears. In each case,
274        // assign a counter value in each case if so.
275        let mut counter = 0;
276        let mut has_sub = None;
277        let mut has_sup = None;
278
279        let mut actual_has_vid = None;
280        let mut expected_has_vid = None;
281
282        self.tcx().for_each_free_region(&expected_trait_ref, |r| {
283            if Some(r) == sub_placeholder && has_sub.is_none() {
284                has_sub = Some(counter);
285                counter += 1;
286            } else if Some(r) == sup_placeholder && has_sup.is_none() {
287                has_sup = Some(counter);
288                counter += 1;
289            }
290
291            if Some(r) == vid && expected_has_vid.is_none() {
292                expected_has_vid = Some(counter);
293                counter += 1;
294            }
295        });
296
297        self.tcx().for_each_free_region(&actual_trait_ref, |r| {
298            if Some(r) == vid && actual_has_vid.is_none() {
299                actual_has_vid = Some(counter);
300                counter += 1;
301            }
302        });
303
304        let actual_self_ty_has_vid =
305            self.tcx().any_free_region_meets(&actual_trait_ref.self_ty(), |r| Some(r) == vid);
306
307        let expected_self_ty_has_vid =
308            self.tcx().any_free_region_meets(&expected_trait_ref.self_ty(), |r| Some(r) == vid);
309
310        let any_self_ty_has_vid = actual_self_ty_has_vid || expected_self_ty_has_vid;
311
312        debug!(
313            ?actual_has_vid,
314            ?expected_has_vid,
315            ?has_sub,
316            ?has_sup,
317            ?actual_self_ty_has_vid,
318            ?expected_self_ty_has_vid,
319        );
320
321        let actual_impl_expl_notes = self.explain_actual_impl_that_was_found(
322            sub_placeholder,
323            sup_placeholder,
324            has_sub,
325            has_sup,
326            expected_trait_ref,
327            actual_trait_ref,
328            vid,
329            expected_has_vid,
330            actual_has_vid,
331            any_self_ty_has_vid,
332            leading_ellipsis,
333        );
334
335        self.tcx().dcx().create_err(TraitPlaceholderMismatch {
336            span,
337            satisfy_span,
338            where_span,
339            dup_span,
340            def_id,
341            trait_def_id: self.tcx().def_path_str(trait_def_id),
342            actual_impl_expl_notes,
343        })
344    }
345
346    /// Add notes with details about the expected and actual trait refs, with attention to cases
347    /// when placeholder regions are involved: either the trait or the self type containing
348    /// them needs to be mentioned the closest to the placeholders.
349    /// This makes the error messages read better, however at the cost of some complexity
350    /// due to the number of combinations we have to deal with.
351    fn explain_actual_impl_that_was_found(
352        &self,
353        sub_placeholder: Option<Region<'tcx>>,
354        sup_placeholder: Option<Region<'tcx>>,
355        has_sub: Option<usize>,
356        has_sup: Option<usize>,
357        expected_trait_ref: ty::TraitRef<'tcx>,
358        actual_trait_ref: ty::TraitRef<'tcx>,
359        vid: Option<Region<'tcx>>,
360        expected_has_vid: Option<usize>,
361        actual_has_vid: Option<usize>,
362        any_self_ty_has_vid: bool,
363        leading_ellipsis: bool,
364    ) -> Vec<ActualImplExplNotes<'tcx>> {
365        // The weird thing here with the `maybe_highlighting_region` calls and the
366        // the match inside is meant to be like this:
367        //
368        // - The match checks whether the given things (placeholders, etc) appear
369        //   in the types are about to print
370        // - Meanwhile, the `maybe_highlighting_region` calls set up
371        //   highlights so that, if they do appear, we will replace
372        //   them `'0` and whatever. (This replacement takes place
373        //   inside the closure given to `maybe_highlighting_region`.)
374        //
375        // There is some duplication between the calls -- i.e., the
376        // `maybe_highlighting_region` checks if (e.g.) `has_sub` is
377        // None, an then we check again inside the closure, but this
378        // setup sort of minimized the number of calls and so form.
379
380        let highlight_trait_ref = |trait_ref| Highlighted {
381            tcx: self.tcx(),
382            highlight: RegionHighlightMode::default(),
383            value: trait_ref,
384            ns: Namespace::TypeNS,
385        };
386
387        let same_self_type = actual_trait_ref.self_ty() == expected_trait_ref.self_ty();
388
389        let mut expected_trait_ref = highlight_trait_ref(expected_trait_ref);
390        expected_trait_ref.highlight.maybe_highlighting_region(sub_placeholder, has_sub);
391        expected_trait_ref.highlight.maybe_highlighting_region(sup_placeholder, has_sup);
392
393        let passive_voice = match (has_sub, has_sup) {
394            (Some(_), _) | (_, Some(_)) => any_self_ty_has_vid,
395            (None, None) => {
396                expected_trait_ref.highlight.maybe_highlighting_region(vid, expected_has_vid);
397                match expected_has_vid {
398                    Some(_) => true,
399                    None => any_self_ty_has_vid,
400                }
401            }
402        };
403
404        let (kind, ty_or_sig, trait_path) = if same_self_type {
405            let mut self_ty = expected_trait_ref.map(|tr| tr.self_ty());
406            self_ty.highlight.maybe_highlighting_region(vid, actual_has_vid);
407
408            if self_ty.value.is_closure() && self.tcx().is_fn_trait(expected_trait_ref.value.def_id)
409            {
410                let closure_sig = self_ty.map(|closure| {
411                    if let ty::Closure(_, args) = closure.kind() {
412                        self.tcx()
413                            .signature_unclosure(args.as_closure().sig(), rustc_hir::Safety::Safe)
414                    } else {
415                        ::rustc_middle::util::bug::bug_fmt(format_args!("type is not longer closure"));bug!("type is not longer closure");
416                    }
417                });
418                (
419                    ActualImplExpectedKind::Signature,
420                    TyOrSig::ClosureSig(closure_sig),
421                    expected_trait_ref.map(|tr| tr.print_only_trait_path()),
422                )
423            } else {
424                (
425                    ActualImplExpectedKind::Other,
426                    TyOrSig::Ty(self_ty),
427                    expected_trait_ref.map(|tr| tr.print_only_trait_path()),
428                )
429            }
430        } else if passive_voice {
431            (
432                ActualImplExpectedKind::Passive,
433                TyOrSig::Ty(expected_trait_ref.map(|tr| tr.self_ty())),
434                expected_trait_ref.map(|tr| tr.print_only_trait_path()),
435            )
436        } else {
437            (
438                ActualImplExpectedKind::Other,
439                TyOrSig::Ty(expected_trait_ref.map(|tr| tr.self_ty())),
440                expected_trait_ref.map(|tr| tr.print_only_trait_path()),
441            )
442        };
443
444        let (lt_kind, lifetime_1, lifetime_2) = match (has_sub, has_sup) {
445            (Some(n1), Some(n2)) => {
446                (ActualImplExpectedLifetimeKind::Two, std::cmp::min(n1, n2), std::cmp::max(n1, n2))
447            }
448            (Some(n), _) | (_, Some(n)) => (ActualImplExpectedLifetimeKind::Any, n, 0),
449            (None, None) => {
450                if let Some(n) = expected_has_vid {
451                    (ActualImplExpectedLifetimeKind::Some, n, 0)
452                } else {
453                    (ActualImplExpectedLifetimeKind::Nothing, 0, 0)
454                }
455            }
456        };
457
458        let note_1 = ActualImplExplNotes::new_expected(
459            kind,
460            lt_kind,
461            leading_ellipsis,
462            ty_or_sig,
463            trait_path,
464            lifetime_1,
465            lifetime_2,
466        );
467
468        let mut actual_trait_ref = highlight_trait_ref(actual_trait_ref);
469        actual_trait_ref.highlight.maybe_highlighting_region(vid, actual_has_vid);
470
471        let passive_voice = match actual_has_vid {
472            Some(_) => any_self_ty_has_vid,
473            None => true,
474        };
475
476        let trait_path = actual_trait_ref.map(|tr| tr.print_only_trait_path());
477        let ty = actual_trait_ref.map(|tr| tr.self_ty()).to_string();
478        let has_lifetime = actual_has_vid.is_some();
479        let lifetime = actual_has_vid.unwrap_or_default();
480
481        let note_2 = if same_self_type {
482            ActualImplExplNotes::ButActuallyImplementsTrait { trait_path, has_lifetime, lifetime }
483        } else if passive_voice {
484            ActualImplExplNotes::ButActuallyImplementedForTy {
485                trait_path,
486                ty,
487                has_lifetime,
488                lifetime,
489            }
490        } else {
491            ActualImplExplNotes::ButActuallyTyImplements { trait_path, ty, has_lifetime, lifetime }
492        };
493
494        ::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]
495    }
496}