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