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::{Applicability, Diag, IntoDiagArg};
5use rustc_hir as hir;
6use rustc_hir::def::{DefKind, Namespace};
7use rustc_hir::def_id::{CRATE_DEF_ID, DefId};
8use rustc_middle::ty::error::ExpectedFound;
9use rustc_middle::ty::print::{FmtPrinter, Print, PrintTraitRefExt as _, RegionHighlightMode};
10use rustc_middle::ty::{self, GenericArgsRef, IsSuggestable, RePlaceholder, Region, TyCtxt};
11use rustc_span::{Span, bug};
12use rustc_structures::Limit;
13use tracing::{debug, instrument};
14
15use crate::diagnostics::{
16    ActualImplExpectedKind, ActualImplExpectedLifetimeKind, ActualImplExplNotes,
17    TraitPlaceholderMismatch, TyOrSig,
18};
19use crate::error_reporting::infer::nice_region_error::NiceRegionError;
20use crate::infer::{RegionResolutionError, SubregionOrigin, TypeTrace, ValuePairs};
21use crate::traits::{ObligationCause, ObligationCauseCode};
22
23#[derive(#[automatically_derived]
impl<'tcx, T: ::core::marker::Copy> ::core::marker::Copy for
    Highlighted<'tcx, T> {
}Copy, #[automatically_derived]
impl<'tcx, T: ::core::clone::Clone> ::core::clone::Clone for
    Highlighted<'tcx, T> {
    #[inline]
    fn clone(&self) -> Self {
        Highlighted {
            tcx: ::core::clone::Clone::clone(&self.tcx),
            highlight: ::core::clone::Clone::clone(&self.highlight),
            value: ::core::clone::Clone::clone(&self.value),
            ns: ::core::clone::Clone::clone(&self.ns),
        }
    }
}Clone)]
24pub(crate) struct Highlighted<'tcx, T> {
25    pub tcx: TyCtxt<'tcx>,
26    pub highlight: RegionHighlightMode<'tcx>,
27    pub value: T,
28    pub ns: Namespace,
29}
30
31impl<'tcx, T> IntoDiagArg for Highlighted<'tcx, T>
32where
33    T: for<'a> Print<FmtPrinter<'a, 'tcx>> + Copy,
34{
35    fn into_diag_arg(self, _: &mut Option<std::path::PathBuf>) -> rustc_errors::DiagArgValue {
36        rustc_errors::DiagArgValue::Str(self.to_string().into())
37    }
38}
39
40impl<'tcx, T> Highlighted<'tcx, T> {
41    fn map<U>(self, f: impl FnOnce(T) -> U) -> Highlighted<'tcx, U> {
42        Highlighted { tcx: self.tcx, highlight: self.highlight, value: f(self.value), ns: self.ns }
43    }
44}
45
46impl<'tcx, T> fmt::Display for Highlighted<'tcx, T>
47where
48    T: for<'a> Print<FmtPrinter<'a, 'tcx>> + Copy,
49{
50    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
51        let mut p = ty::print::FmtPrinter::new(self.tcx, self.ns);
52        p.region_highlight_mode = self.highlight;
53
54        self.value.print(&mut p)?;
55        let b = p.into_buffer();
56        if b.len() <= 40 || !self.highlight.keep_regions || self.tcx.sess.opts.verbose {
57            // This is a short enough type that can be safely be printed to the user, or we aren't
58            // showing the type with a particular interest in its lifetimes.
59            f.write_str(&b)?;
60        } else {
61            // We are highlighting lifetimes in the output, we will print out the smallest possible
62            // portion of the type while keeping the lifetimes visible.
63            let mut p = FmtPrinter::new_with_limit(self.tcx, self.ns, Limit(0));
64            p.region_highlight_mode = self.highlight;
65            self.value.print(&mut p).expect("could not print type");
66            let x = p.into_buffer();
67            f.write_str(&x)?;
68        }
69        Ok(())
70    }
71}
72
73impl<'tcx> NiceRegionError<'_, 'tcx> {
74    /// When given a `ConcreteFailure` for a function with arguments containing a named region and
75    /// an anonymous region, emit a descriptive diagnostic error.
76    pub(super) fn try_report_placeholder_conflict(&self) -> Option<Diag<'tcx>> {
77        match &self.error {
78            ///////////////////////////////////////////////////////////////////////////
79            // NB. The ordering of cases in this match is very
80            // sensitive, because we are often matching against
81            // specific cases and then using an `_` to match all
82            // others.
83
84            ///////////////////////////////////////////////////////////////////////////
85            // Check for errors from comparing trait failures -- first
86            // with two placeholders, then with one.
87            Some(RegionResolutionError::SubSupConflict(
88                vid,
89                _,
90                SubregionOrigin::Subtype(TypeTrace { cause, values }),
91                sub_placeholder @ Region(Interned(RePlaceholder(_), _)),
92                _,
93                sup_placeholder @ Region(Interned(RePlaceholder(_), _)),
94                _,
95            )) => self.try_report_trait_placeholder_mismatch(
96                Some(ty::Region::new_var(self.tcx(), *vid)),
97                cause,
98                Some(*sub_placeholder),
99                Some(*sup_placeholder),
100                values,
101            ),
102
103            Some(RegionResolutionError::SubSupConflict(
104                vid,
105                _,
106                SubregionOrigin::Subtype(TypeTrace { cause, values }),
107                sub_placeholder @ Region(Interned(RePlaceholder(_), _)),
108                _,
109                _,
110                _,
111            )) => self.try_report_trait_placeholder_mismatch(
112                Some(ty::Region::new_var(self.tcx(), *vid)),
113                cause,
114                Some(*sub_placeholder),
115                None,
116                values,
117            ),
118
119            Some(RegionResolutionError::SubSupConflict(
120                vid,
121                _,
122                SubregionOrigin::Subtype(TypeTrace { cause, values }),
123                _,
124                _,
125                sup_placeholder @ Region(Interned(RePlaceholder(_), _)),
126                _,
127            )) => self.try_report_trait_placeholder_mismatch(
128                Some(ty::Region::new_var(self.tcx(), *vid)),
129                cause,
130                None,
131                Some(*sup_placeholder),
132                values,
133            ),
134
135            Some(RegionResolutionError::SubSupConflict(
136                vid,
137                _,
138                _,
139                _,
140                SubregionOrigin::Subtype(TypeTrace { cause, values }),
141                sup_placeholder @ Region(Interned(RePlaceholder(_), _)),
142                _,
143            )) => self.try_report_trait_placeholder_mismatch(
144                Some(ty::Region::new_var(self.tcx(), *vid)),
145                cause,
146                None,
147                Some(*sup_placeholder),
148                values,
149            ),
150
151            Some(RegionResolutionError::UpperBoundUniverseConflict(
152                vid,
153                _,
154                _,
155                SubregionOrigin::Subtype(TypeTrace { cause, values }),
156                sup_placeholder @ Region(Interned(RePlaceholder(_), _)),
157            )) => self.try_report_trait_placeholder_mismatch(
158                Some(ty::Region::new_var(self.tcx(), *vid)),
159                cause,
160                None,
161                Some(*sup_placeholder),
162                values,
163            ),
164
165            Some(RegionResolutionError::ConcreteFailure(
166                SubregionOrigin::Subtype(TypeTrace { cause, values }),
167                sub_region @ Region(Interned(RePlaceholder(_), _)),
168                sup_region @ Region(Interned(RePlaceholder(_), _)),
169            )) => self.try_report_trait_placeholder_mismatch(
170                None,
171                cause,
172                Some(*sub_region),
173                Some(*sup_region),
174                values,
175            ),
176
177            Some(RegionResolutionError::ConcreteFailure(
178                SubregionOrigin::Subtype(TypeTrace { cause, values }),
179                sub_region @ Region(Interned(RePlaceholder(_), _)),
180                sup_region,
181            )) => self.try_report_trait_placeholder_mismatch(
182                (!sup_region.is_named(self.tcx())).then_some(*sup_region),
183                cause,
184                Some(*sub_region),
185                None,
186                values,
187            ),
188
189            Some(RegionResolutionError::ConcreteFailure(
190                SubregionOrigin::Subtype(TypeTrace { cause, values }),
191                sub_region,
192                sup_region @ Region(Interned(RePlaceholder(_), _)),
193            )) => self.try_report_trait_placeholder_mismatch(
194                (!sub_region.is_named(self.tcx())).then_some(*sub_region),
195                cause,
196                None,
197                Some(*sup_region),
198                values,
199            ),
200
201            _ => None,
202        }
203    }
204
205    fn try_report_trait_placeholder_mismatch(
206        &self,
207        vid: Option<Region<'tcx>>,
208        cause: &ObligationCause<'tcx>,
209        sub_placeholder: Option<Region<'tcx>>,
210        sup_placeholder: Option<Region<'tcx>>,
211        value_pairs: &ValuePairs<'tcx>,
212    ) -> Option<Diag<'tcx>> {
213        let (expected_args, found_args, trait_def_id) = match value_pairs {
214            ValuePairs::TraitRefs(ExpectedFound { expected, found })
215                if expected.def_id == found.def_id =>
216            {
217                // It's possible that the placeholders come from a binder
218                // outside of this value pair. Use `no_bound_vars` as a
219                // simple heuristic for that.
220                (expected.args, found.args, expected.def_id)
221            }
222            _ => return None,
223        };
224
225        Some(self.report_trait_placeholder_mismatch(
226            vid,
227            cause,
228            sub_placeholder,
229            sup_placeholder,
230            trait_def_id,
231            expected_args,
232            found_args,
233        ))
234    }
235
236    // error[E0308]: implementation of `Foo` does not apply to enough lifetimes
237    //   --> /home/nmatsakis/tmp/foo.rs:12:5
238    //    |
239    // 12 |     all::<&'static u32>();
240    //    |     ^^^^^^^^^^^^^^^^^^^ lifetime mismatch
241    //    |
242    //    = note: Due to a where-clause on the function `all`,
243    //    = note: `T` must implement `...` for any two lifetimes `'1` and `'2`.
244    //    = note: However, the type `T` only implements `...` for some specific lifetime `'2`.
245    {}
#[allow(clippy :: suspicious_else_formatting)]
{
    let __tracing_attr_span;
    let __tracing_attr_guard;
    if ::tracing::Level::DEBUG <= ::tracing::level_filters::STATIC_MAX_LEVEL
                &&
                ::tracing::Level::DEBUG <=
                    ::tracing::level_filters::LevelFilter::current() ||
            { false } {
        __tracing_attr_span =
            {
                use ::tracing::__macro_support::Callsite as _;
                static __CALLSITE: ::tracing::callsite::DefaultCallsite =
                    {
                        static META: ::tracing::Metadata<'static> =
                            {
                                ::tracing_core::metadata::Metadata::new("report_trait_placeholder_mismatch",
                                    "rustc_trait_selection::error_reporting::infer::nice_region_error::placeholder_error",
                                    ::tracing::Level::DEBUG,
                                    ::tracing_core::__macro_support::Option::Some("/rustc-dev/a30aa9064df6a504b6a323c6884a2f4cfbfff666/compiler/rustc_trait_selection/src/error_reporting/infer/nice_region_error/placeholder_error.rs"),
                                    ::tracing_core::__macro_support::Option::Some(245u32),
                                    ::tracing_core::__macro_support::Option::Some("rustc_trait_selection::error_reporting::infer::nice_region_error::placeholder_error"),
                                    ::tracing_core::field::FieldSet::new(&[{
                                                        const NAME:
                                                            ::tracing::__macro_support::FieldName<{
                                                                ::tracing::__macro_support::FieldName::len("vid")
                                                            }> =
                                                            ::tracing::__macro_support::FieldName::new("vid");
                                                        NAME.as_str()
                                                    },
                                                    {
                                                        const NAME:
                                                            ::tracing::__macro_support::FieldName<{
                                                                ::tracing::__macro_support::FieldName::len("cause")
                                                            }> =
                                                            ::tracing::__macro_support::FieldName::new("cause");
                                                        NAME.as_str()
                                                    },
                                                    {
                                                        const NAME:
                                                            ::tracing::__macro_support::FieldName<{
                                                                ::tracing::__macro_support::FieldName::len("sub_placeholder")
                                                            }> =
                                                            ::tracing::__macro_support::FieldName::new("sub_placeholder");
                                                        NAME.as_str()
                                                    },
                                                    {
                                                        const NAME:
                                                            ::tracing::__macro_support::FieldName<{
                                                                ::tracing::__macro_support::FieldName::len("sup_placeholder")
                                                            }> =
                                                            ::tracing::__macro_support::FieldName::new("sup_placeholder");
                                                        NAME.as_str()
                                                    },
                                                    {
                                                        const NAME:
                                                            ::tracing::__macro_support::FieldName<{
                                                                ::tracing::__macro_support::FieldName::len("trait_def_id")
                                                            }> =
                                                            ::tracing::__macro_support::FieldName::new("trait_def_id");
                                                        NAME.as_str()
                                                    },
                                                    {
                                                        const NAME:
                                                            ::tracing::__macro_support::FieldName<{
                                                                ::tracing::__macro_support::FieldName::len("expected_args")
                                                            }> =
                                                            ::tracing::__macro_support::FieldName::new("expected_args");
                                                        NAME.as_str()
                                                    },
                                                    {
                                                        const NAME:
                                                            ::tracing::__macro_support::FieldName<{
                                                                ::tracing::__macro_support::FieldName::len("actual_args")
                                                            }> =
                                                            ::tracing::__macro_support::FieldName::new("actual_args");
                                                        NAME.as_str()
                                                    }], ::tracing_core::callsite::Identifier(&__CALLSITE)),
                                    ::tracing::metadata::Kind::SPAN)
                            };
                        ::tracing::callsite::DefaultCallsite::new(&META)
                    };
                let mut interest = ::tracing::subscriber::Interest::never();
                if ::tracing::Level::DEBUG <=
                                    ::tracing::level_filters::STATIC_MAX_LEVEL &&
                                ::tracing::Level::DEBUG <=
                                    ::tracing::level_filters::LevelFilter::current() &&
                            { interest = __CALLSITE.interest(); !interest.is_never() }
                        &&
                        ::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
                            interest) {
                    let meta = __CALLSITE.metadata();
                    ::tracing::Span::new(meta,
                        &{
                                #[allow(unused_imports)]
                                use ::tracing::field::{debug, display, Value};
                                meta.fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&vid)
                                                            as &dyn ::tracing::field::Value)),
                                                (::tracing::__macro_support::Option::Some(&::tracing::field::debug(&cause)
                                                            as &dyn ::tracing::field::Value)),
                                                (::tracing::__macro_support::Option::Some(&::tracing::field::debug(&sub_placeholder)
                                                            as &dyn ::tracing::field::Value)),
                                                (::tracing::__macro_support::Option::Some(&::tracing::field::debug(&sup_placeholder)
                                                            as &dyn ::tracing::field::Value)),
                                                (::tracing::__macro_support::Option::Some(&::tracing::field::debug(&trait_def_id)
                                                            as &dyn ::tracing::field::Value)),
                                                (::tracing::__macro_support::Option::Some(&::tracing::field::debug(&expected_args)
                                                            as &dyn ::tracing::field::Value)),
                                                (::tracing::__macro_support::Option::Some(&::tracing::field::debug(&actual_args)
                                                            as &dyn ::tracing::field::Value))])
                            })
                } else {
                    let span =
                        ::tracing::__macro_support::__disabled_span(__CALLSITE.metadata());
                    {};
                    span
                }
            };
        __tracing_attr_guard = __tracing_attr_span.enter();
    }

    #[warn(clippy :: suspicious_else_formatting)]
    {

        #[allow(unknown_lints, unreachable_code, clippy ::
        diverging_sub_expression, clippy :: empty_loop, clippy ::
        let_unit_value, clippy :: let_with_type_underscore, clippy ::
        needless_return, clippy :: unreachable)]
        if false {
            let __tracing_attr_fake_return: Diag<'tcx> = loop {};
            return __tracing_attr_fake_return;
        }
        {
            let span = cause.span;
            let mut code = cause.code();
            loop {
                match code {
                    ObligationCauseCode::MatchImpl(inner_cause, _) => {
                        code = inner_cause.code();
                    }
                    ObligationCauseCode::ImplDerived(derived) => {
                        code = &derived.derived.parent_code;
                    }
                    ObligationCauseCode::BuiltinDerived(derived) => {
                        code = &derived.parent_code;
                    }
                    ObligationCauseCode::WellFormedDerived(derived) => {
                        code = &derived.parent_code;
                    }
                    ObligationCauseCode::ImplDerivedHost(derived) => {
                        code = &derived.derived.parent_code;
                    }
                    ObligationCauseCode::BuiltinDerivedHost(derived) => {
                        code = &derived.parent_code;
                    }
                    _ => break,
                }
            }
            let (mut satisfy_span, mut item_span, outer_span, dup_span,
                    item_name) =
                if let ObligationCauseCode::WhereClause(def_id, span) |
                            ObligationCauseCode::WhereClauseInExpr(def_id, span, ..) =
                            *code && def_id != CRATE_DEF_ID.to_def_id() {
                    let parent = self.tcx().parent(def_id);
                    (Some(span),
                        Some(self.tcx().opt_item_ident(def_id).map_or_else(||
                                    self.tcx().def_span(def_id), |n| n.span)),
                        if let DefKind::Trait | DefKind::Impl { .. } =
                                self.tcx().def_kind(parent) {
                            Some(self.tcx().def_span(parent).shrink_to_lo())
                        } else { None }, None, self.tcx().def_path_str(def_id))
                } else { (None, None, None, Some(span), String::new()) };
            if let Some(span) = satisfy_span && span.is_dummy() {
                satisfy_span = None;
            }
            if let Some(span) = item_span && span.is_dummy() {
                item_span = None;
            }
            let expected_trait_ref =
                self.cx.deeply_resolve_ignoring_regions(ty::TraitRef::new_from_args(self.cx.tcx,
                        trait_def_id, expected_args));
            let actual_trait_ref =
                self.cx.deeply_resolve_ignoring_regions(ty::TraitRef::new_from_args(self.cx.tcx,
                        trait_def_id, actual_args));
            let mut counter = 0;
            let mut has_sub = None;
            let mut has_sup = None;
            let mut actual_has_vid = None;
            let mut expected_has_vid = None;
            self.tcx().for_each_free_region(&expected_trait_ref,
                |r|
                    {
                        if Some(r) == sub_placeholder && has_sub.is_none() {
                            has_sub = Some(counter);
                            counter += 1;
                        } else if Some(r) == sup_placeholder && has_sup.is_none() {
                            has_sup = Some(counter);
                            counter += 1;
                        }
                        if Some(r) == vid && expected_has_vid.is_none() {
                            expected_has_vid = Some(counter);
                            counter += 1;
                        }
                    });
            self.tcx().for_each_free_region(&actual_trait_ref,
                |r|
                    {
                        if Some(r) == vid && actual_has_vid.is_none() {
                            actual_has_vid = Some(counter);
                            counter += 1;
                        }
                    });
            let actual_self_ty_has_vid =
                self.tcx().any_free_region_meets(&actual_trait_ref.self_ty(),
                    |r| Some(r) == vid);
            let expected_self_ty_has_vid =
                self.tcx().any_free_region_meets(&expected_trait_ref.self_ty(),
                    |r| Some(r) == vid);
            let any_self_ty_has_vid =
                actual_self_ty_has_vid || expected_self_ty_has_vid;
            {
                use ::tracing::__macro_support::Callsite as _;
                static __CALLSITE: ::tracing::callsite::DefaultCallsite =
                    {
                        static META: ::tracing::Metadata<'static> =
                            {
                                ::tracing_core::metadata::Metadata::new("event /rustc-dev/a30aa9064df6a504b6a323c6884a2f4cfbfff666/compiler/rustc_trait_selection/src/error_reporting/infer/nice_region_error/placeholder_error.rs:367",
                                    "rustc_trait_selection::error_reporting::infer::nice_region_error::placeholder_error",
                                    ::tracing::Level::DEBUG,
                                    ::tracing_core::__macro_support::Option::Some("/rustc-dev/a30aa9064df6a504b6a323c6884a2f4cfbfff666/compiler/rustc_trait_selection/src/error_reporting/infer/nice_region_error/placeholder_error.rs"),
                                    ::tracing_core::__macro_support::Option::Some(367u32),
                                    ::tracing_core::__macro_support::Option::Some("rustc_trait_selection::error_reporting::infer::nice_region_error::placeholder_error"),
                                    ::tracing_core::field::FieldSet::new(&[{
                                                        const NAME:
                                                            ::tracing::__macro_support::FieldName<{
                                                                ::tracing::__macro_support::FieldName::len("actual_has_vid")
                                                            }> =
                                                            ::tracing::__macro_support::FieldName::new("actual_has_vid");
                                                        NAME.as_str()
                                                    },
                                                    {
                                                        const NAME:
                                                            ::tracing::__macro_support::FieldName<{
                                                                ::tracing::__macro_support::FieldName::len("expected_has_vid")
                                                            }> =
                                                            ::tracing::__macro_support::FieldName::new("expected_has_vid");
                                                        NAME.as_str()
                                                    },
                                                    {
                                                        const NAME:
                                                            ::tracing::__macro_support::FieldName<{
                                                                ::tracing::__macro_support::FieldName::len("has_sub")
                                                            }> =
                                                            ::tracing::__macro_support::FieldName::new("has_sub");
                                                        NAME.as_str()
                                                    },
                                                    {
                                                        const NAME:
                                                            ::tracing::__macro_support::FieldName<{
                                                                ::tracing::__macro_support::FieldName::len("has_sup")
                                                            }> =
                                                            ::tracing::__macro_support::FieldName::new("has_sup");
                                                        NAME.as_str()
                                                    },
                                                    {
                                                        const NAME:
                                                            ::tracing::__macro_support::FieldName<{
                                                                ::tracing::__macro_support::FieldName::len("actual_self_ty_has_vid")
                                                            }> =
                                                            ::tracing::__macro_support::FieldName::new("actual_self_ty_has_vid");
                                                        NAME.as_str()
                                                    },
                                                    {
                                                        const NAME:
                                                            ::tracing::__macro_support::FieldName<{
                                                                ::tracing::__macro_support::FieldName::len("expected_self_ty_has_vid")
                                                            }> =
                                                            ::tracing::__macro_support::FieldName::new("expected_self_ty_has_vid");
                                                        NAME.as_str()
                                                    }], ::tracing_core::callsite::Identifier(&__CALLSITE)),
                                    ::tracing::metadata::Kind::EVENT)
                            };
                        ::tracing::callsite::DefaultCallsite::new(&META)
                    };
                let enabled =
                    ::tracing::Level::DEBUG <=
                                ::tracing::level_filters::STATIC_MAX_LEVEL &&
                            ::tracing::Level::DEBUG <=
                                ::tracing::level_filters::LevelFilter::current() &&
                        {
                            let interest = __CALLSITE.interest();
                            !interest.is_never() &&
                                ::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
                                    interest)
                        };
                if enabled {
                    (|value_set: ::tracing::field::ValueSet|
                                {
                                    let meta = __CALLSITE.metadata();
                                    ::tracing::Event::dispatch(meta, &value_set);
                                    ;
                                })({
                            #[allow(unused_imports)]
                            use ::tracing::field::{debug, display, Value};
                            __CALLSITE.metadata().fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&actual_has_vid)
                                                        as &dyn ::tracing::field::Value)),
                                            (::tracing::__macro_support::Option::Some(&::tracing::field::debug(&expected_has_vid)
                                                        as &dyn ::tracing::field::Value)),
                                            (::tracing::__macro_support::Option::Some(&::tracing::field::debug(&has_sub)
                                                        as &dyn ::tracing::field::Value)),
                                            (::tracing::__macro_support::Option::Some(&::tracing::field::debug(&has_sup)
                                                        as &dyn ::tracing::field::Value)),
                                            (::tracing::__macro_support::Option::Some(&::tracing::field::debug(&actual_self_ty_has_vid)
                                                        as &dyn ::tracing::field::Value)),
                                            (::tracing::__macro_support::Option::Some(&::tracing::field::debug(&expected_self_ty_has_vid)
                                                        as &dyn ::tracing::field::Value))])
                        });
                } else { ; }
            };
            let actual_impl_expl_notes =
                self.explain_actual_impl_that_was_found(sub_placeholder,
                    sup_placeholder, has_sub, has_sup, expected_trait_ref,
                    actual_trait_ref, vid, expected_has_vid, actual_has_vid,
                    any_self_ty_has_vid, satisfy_span, item_span, outer_span,
                    item_name);
            let mut err =
                self.tcx().dcx().create_err(TraitPlaceholderMismatch {
                        span,
                        dup_span,
                        trait_def_id: self.tcx().def_path_str(trait_def_id),
                        actual_impl_expl_notes,
                    });
            let mut current_code = cause.code();
            let mut coroutine_def_id = None;
            if cause.body_def_id != CRATE_DEF_ID {
                if let ObligationCauseCode::WhereClause(..) |
                        ObligationCauseCode::WhereClauseInExpr(..) = *code
                    {} else {
                    self.cx.note_obligation_cause_code(cause.body_def_id,
                        &mut err, actual_trait_ref,
                        self.tcx().param_env(cause.body_def_id), cause.code(),
                        &mut ::alloc::vec::Vec::new(), &mut Default::default());
                }
            }
            loop {
                match current_code {
                    ObligationCauseCode::MatchImpl(inner_cause, _) => {
                        current_code = inner_cause.code();
                    }
                    ObligationCauseCode::BuiltinDerived(derived) => {
                        let self_ty =
                            derived.parent_trait_pred.skip_binder().self_ty();
                        if let ty::Coroutine(def_id, _) |
                                ty::CoroutineWitness(def_id, _) = self_ty.kind() {
                            coroutine_def_id = Some(*def_id);
                            break;
                        }
                        current_code = &derived.parent_code;
                    }
                    _ => break,
                }
            }
            if let Some(def_id) = coroutine_def_id {
                if self.tcx().trait_is_auto(trait_def_id) {
                    let c_span = self.tcx().def_span(def_id);
                    let descr = self.tcx().def_descr(def_id);
                    let trait_name = self.tcx().def_path_str(trait_def_id);
                    err.span_label(c_span,
                        ::alloc::__export::must_use({
                                ::alloc::fmt::format(format_args!("this {0} captures a value whose type is not `{1}`",
                                        descr, trait_name))
                            }));
                }
            }
            if self.tcx().is_fn_trait(trait_def_id) {
                let actual_self_ty =
                    self.cx.deeply_resolve_ignoring_regions(ty::TraitRef::new_from_args(self.cx.tcx,
                                trait_def_id, actual_args).self_ty());
                if let ty::Closure(closure_def_id, _) = *actual_self_ty.kind()
                            && let Some(local_def_id) = closure_def_id.as_local() &&
                        let hir::Node::Expr(hir::Expr {
                            kind: hir::ExprKind::Closure(closure), .. }) =
                            self.tcx().hir_node_by_def_id(local_def_id) {
                    let body = self.tcx().hir_body(closure.body);
                    let expected_input_tys = expected_args.type_at(1);
                    if let ty::Tuple(input_tys) = *expected_input_tys.kind() {
                        let suggestions: Vec<_> =
                            body.params.iter().zip(input_tys.iter()).filter_map(|(param,
                                            ty)|
                                        {
                                            if param.ty_span == param.pat.span &&
                                                    ty.is_suggestable(self.tcx(), false) {
                                                Some((param.pat.span.shrink_to_hi(),
                                                        ::alloc::__export::must_use({
                                                                ::alloc::fmt::format(format_args!(": {0}", ty))
                                                            })))
                                            } else { None }
                                        }).collect();
                        if !suggestions.is_empty() {
                            let msg =
                                if suggestions.len() == 1 {
                                    "consider adding an explicit type annotation to the closure's argument"
                                } else {
                                    "consider adding explicit type annotations to the closure's arguments"
                                };
                            err.multipart_suggestion(msg, suggestions,
                                Applicability::MaybeIncorrect);
                        }
                    }
                }
            }
            err
        }
    }
}#[instrument(level = "debug", skip(self))]
246    fn report_trait_placeholder_mismatch(
247        &self,
248        vid: Option<Region<'tcx>>,
249        cause: &ObligationCause<'tcx>,
250        sub_placeholder: Option<Region<'tcx>>,
251        sup_placeholder: Option<Region<'tcx>>,
252        trait_def_id: DefId,
253        expected_args: GenericArgsRef<'tcx>,
254        actual_args: GenericArgsRef<'tcx>,
255    ) -> Diag<'tcx> {
256        let span = cause.span;
257
258        let mut code = cause.code();
259        loop {
260            match code {
261                ObligationCauseCode::MatchImpl(inner_cause, _) => {
262                    code = inner_cause.code();
263                }
264                ObligationCauseCode::ImplDerived(derived) => {
265                    code = &derived.derived.parent_code;
266                }
267                ObligationCauseCode::BuiltinDerived(derived) => {
268                    code = &derived.parent_code;
269                }
270                ObligationCauseCode::WellFormedDerived(derived) => {
271                    code = &derived.parent_code;
272                }
273                ObligationCauseCode::ImplDerivedHost(derived) => {
274                    code = &derived.derived.parent_code;
275                }
276                ObligationCauseCode::BuiltinDerivedHost(derived) => {
277                    code = &derived.parent_code;
278                }
279                _ => break,
280            }
281        }
282        let (mut satisfy_span, mut item_span, outer_span, dup_span, item_name) =
283            if let ObligationCauseCode::WhereClause(def_id, span)
284            | ObligationCauseCode::WhereClauseInExpr(def_id, span, ..) = *code
285                && def_id != CRATE_DEF_ID.to_def_id()
286            {
287                let parent = self.tcx().parent(def_id);
288                (
289                    Some(span),
290                    Some(
291                        self.tcx()
292                            .opt_item_ident(def_id)
293                            .map_or_else(|| self.tcx().def_span(def_id), |n| n.span),
294                    ),
295                    if let DefKind::Trait | DefKind::Impl { .. } = self.tcx().def_kind(parent) {
296                        Some(self.tcx().def_span(parent).shrink_to_lo())
297                    } else {
298                        None
299                    },
300                    None,
301                    self.tcx().def_path_str(def_id),
302                )
303            } else {
304                (None, None, None, Some(span), String::new())
305            };
306        if let Some(span) = satisfy_span
307            && span.is_dummy()
308        {
309            satisfy_span = None;
310        }
311        if let Some(span) = item_span
312            && span.is_dummy()
313        {
314            item_span = None;
315        }
316
317        let expected_trait_ref = self.cx.deeply_resolve_ignoring_regions(
318            ty::TraitRef::new_from_args(self.cx.tcx, trait_def_id, expected_args),
319        );
320        let actual_trait_ref = self.cx.deeply_resolve_ignoring_regions(
321            ty::TraitRef::new_from_args(self.cx.tcx, trait_def_id, actual_args),
322        );
323
324        // Search the expected and actual trait references to see (a)
325        // whether the sub/sup placeholders appear in them (sometimes
326        // you have a trait ref like `T: Foo<fn(&u8)>`, where the
327        // placeholder was created as part of an inner type) and (b)
328        // whether the inference variable appears. In each case,
329        // assign a counter value in each case if so.
330        let mut counter = 0;
331        let mut has_sub = None;
332        let mut has_sup = None;
333
334        let mut actual_has_vid = None;
335        let mut expected_has_vid = None;
336
337        self.tcx().for_each_free_region(&expected_trait_ref, |r| {
338            if Some(r) == sub_placeholder && has_sub.is_none() {
339                has_sub = Some(counter);
340                counter += 1;
341            } else if Some(r) == sup_placeholder && has_sup.is_none() {
342                has_sup = Some(counter);
343                counter += 1;
344            }
345
346            if Some(r) == vid && expected_has_vid.is_none() {
347                expected_has_vid = Some(counter);
348                counter += 1;
349            }
350        });
351
352        self.tcx().for_each_free_region(&actual_trait_ref, |r| {
353            if Some(r) == vid && actual_has_vid.is_none() {
354                actual_has_vid = Some(counter);
355                counter += 1;
356            }
357        });
358
359        let actual_self_ty_has_vid =
360            self.tcx().any_free_region_meets(&actual_trait_ref.self_ty(), |r| Some(r) == vid);
361
362        let expected_self_ty_has_vid =
363            self.tcx().any_free_region_meets(&expected_trait_ref.self_ty(), |r| Some(r) == vid);
364
365        let any_self_ty_has_vid = actual_self_ty_has_vid || expected_self_ty_has_vid;
366
367        debug!(
368            ?actual_has_vid,
369            ?expected_has_vid,
370            ?has_sub,
371            ?has_sup,
372            ?actual_self_ty_has_vid,
373            ?expected_self_ty_has_vid,
374        );
375
376        let actual_impl_expl_notes = self.explain_actual_impl_that_was_found(
377            sub_placeholder,
378            sup_placeholder,
379            has_sub,
380            has_sup,
381            expected_trait_ref,
382            actual_trait_ref,
383            vid,
384            expected_has_vid,
385            actual_has_vid,
386            any_self_ty_has_vid,
387            satisfy_span,
388            item_span,
389            outer_span,
390            item_name,
391        );
392
393        let mut err = self.tcx().dcx().create_err(TraitPlaceholderMismatch {
394            span,
395            dup_span,
396            trait_def_id: self.tcx().def_path_str(trait_def_id),
397            actual_impl_expl_notes,
398        });
399
400        let mut current_code = cause.code();
401        let mut coroutine_def_id = None;
402        if cause.body_def_id != CRATE_DEF_ID {
403            if let ObligationCauseCode::WhereClause(..)
404            | ObligationCauseCode::WhereClauseInExpr(..) = *code
405            {
406                // Do not point at the same bound twice.
407            } else {
408                self.cx.note_obligation_cause_code(
409                    cause.body_def_id,
410                    &mut err,
411                    actual_trait_ref,
412                    self.tcx().param_env(cause.body_def_id),
413                    cause.code(),
414                    &mut vec![],
415                    &mut Default::default(),
416                );
417            }
418        }
419
420        loop {
421            match current_code {
422                ObligationCauseCode::MatchImpl(inner_cause, _) => {
423                    current_code = inner_cause.code();
424                }
425                ObligationCauseCode::BuiltinDerived(derived) => {
426                    let self_ty = derived.parent_trait_pred.skip_binder().self_ty();
427
428                    if let ty::Coroutine(def_id, _) | ty::CoroutineWitness(def_id, _) =
429                        self_ty.kind()
430                    {
431                        coroutine_def_id = Some(*def_id);
432                        break;
433                    }
434
435                    current_code = &derived.parent_code;
436                }
437                _ => break,
438            }
439        }
440
441        if let Some(def_id) = coroutine_def_id {
442            if self.tcx().trait_is_auto(trait_def_id) {
443                let c_span = self.tcx().def_span(def_id);
444                let descr = self.tcx().def_descr(def_id);
445                let trait_name = self.tcx().def_path_str(trait_def_id);
446
447                err.span_label(
448                    c_span,
449                    format!("this {descr} captures a value whose type is not `{trait_name}`"),
450                );
451            }
452        }
453
454        // When the mismatched trait is an Fn-trait and the self type is a closure with
455        // unannotated parameters, suggest adding explicit type annotations. This turns
456        // the confusing lifetime-generality error into an actionable hint, e.g.:
457        //   |buf|  →  |buf: &mut [u8]|
458        if self.tcx().is_fn_trait(trait_def_id) {
459            let actual_self_ty = self.cx.deeply_resolve_ignoring_regions(
460                ty::TraitRef::new_from_args(self.cx.tcx, trait_def_id, actual_args).self_ty(),
461            );
462            if let ty::Closure(closure_def_id, _) = *actual_self_ty.kind()
463                && let Some(local_def_id) = closure_def_id.as_local()
464                && let hir::Node::Expr(hir::Expr { kind: hir::ExprKind::Closure(closure), .. }) =
465                    self.tcx().hir_node_by_def_id(local_def_id)
466            {
467                let body = self.tcx().hir_body(closure.body);
468                // For Fn traits, args[1] is the tupled input types (e.g. `(&mut [u8],)`).
469                let expected_input_tys = expected_args.type_at(1);
470                if let ty::Tuple(input_tys) = *expected_input_tys.kind() {
471                    let suggestions: Vec<_> = body
472                        .params
473                        .iter()
474                        .zip(input_tys.iter())
475                        .filter_map(|(param, ty)| {
476                            // ty_span == pat.span means no explicit type annotation was written.
477                            if param.ty_span == param.pat.span
478                                && ty.is_suggestable(self.tcx(), false)
479                            {
480                                Some((param.pat.span.shrink_to_hi(), format!(": {ty}")))
481                            } else {
482                                None
483                            }
484                        })
485                        .collect();
486                    if !suggestions.is_empty() {
487                        let msg = if suggestions.len() == 1 {
488                            "consider adding an explicit type annotation to the closure's argument"
489                        } else {
490                            "consider adding explicit type annotations to the closure's arguments"
491                        };
492                        err.multipart_suggestion(msg, suggestions, Applicability::MaybeIncorrect);
493                    }
494                }
495            }
496        }
497
498        err
499    }
500
501    /// Add notes with details about the expected and actual trait refs, with attention to cases
502    /// when placeholder regions are involved: either the trait or the self type containing
503    /// them needs to be mentioned the closest to the placeholders.
504    /// This makes the error messages read better, however at the cost of some complexity
505    /// due to the number of combinations we have to deal with.
506    fn explain_actual_impl_that_was_found(
507        &self,
508        sub_placeholder: Option<Region<'tcx>>,
509        sup_placeholder: Option<Region<'tcx>>,
510        has_sub: Option<usize>,
511        has_sup: Option<usize>,
512        expected_trait_ref: ty::TraitRef<'tcx>,
513        actual_trait_ref: ty::TraitRef<'tcx>,
514        vid: Option<Region<'tcx>>,
515        expected_has_vid: Option<usize>,
516        actual_has_vid: Option<usize>,
517        any_self_ty_has_vid: bool,
518        satisfy_span: Option<Span>,
519        item_span: Option<Span>,
520        outer_span: Option<Span>,
521        item_name: String,
522    ) -> Vec<ActualImplExplNotes<'tcx>> {
523        // The weird thing here with the `maybe_highlighting_region` calls and the
524        // the match inside is meant to be like this:
525        //
526        // - The match checks whether the given things (placeholders, etc) appear
527        //   in the types are about to print
528        // - Meanwhile, the `maybe_highlighting_region` calls set up
529        //   highlights so that, if they do appear, we will replace
530        //   them `'0` and whatever. (This replacement takes place
531        //   inside the closure given to `maybe_highlighting_region`.)
532        //
533        // There is some duplication between the calls -- i.e., the
534        // `maybe_highlighting_region` checks if (e.g.) `has_sub` is
535        // None, an then we check again inside the closure, but this
536        // setup sort of minimized the number of calls and so form.
537
538        let highlight_trait_ref = |trait_ref| Highlighted {
539            tcx: self.tcx(),
540            highlight: RegionHighlightMode::default(),
541            value: trait_ref,
542            ns: Namespace::TypeNS,
543        };
544
545        let same_self_type = actual_trait_ref.self_ty() == expected_trait_ref.self_ty();
546
547        let mut expected_trait_ref = highlight_trait_ref(expected_trait_ref);
548        expected_trait_ref.highlight.maybe_highlighting_region(sub_placeholder, has_sub);
549        expected_trait_ref.highlight.maybe_highlighting_region(sup_placeholder, has_sup);
550
551        let passive_voice = match (has_sub, has_sup) {
552            (Some(_), _) | (_, Some(_)) => any_self_ty_has_vid,
553            (None, None) => {
554                expected_trait_ref.highlight.maybe_highlighting_region(vid, expected_has_vid);
555                match expected_has_vid {
556                    Some(_) => true,
557                    None => any_self_ty_has_vid,
558                }
559            }
560        };
561
562        let (kind, ty_or_sig, trait_path) = if same_self_type {
563            let mut self_ty = expected_trait_ref.map(|tr| tr.self_ty());
564            self_ty.highlight.maybe_highlighting_region(vid, actual_has_vid);
565
566            if self_ty.value.is_closure() && self.tcx().is_fn_trait(expected_trait_ref.value.def_id)
567            {
568                let closure_sig = self_ty.map(|closure| {
569                    if let ty::Closure(_, args) = closure.kind() {
570                        self.tcx()
571                            .signature_unclosure(args.as_closure().sig(), rustc_hir::Safety::Safe)
572                    } else {
573                        ::rustc_span::macros::bug_impl(None,
    format_args!("type is not longer closure"), Location::caller());bug!("type is not longer closure");
574                    }
575                });
576                (
577                    ActualImplExpectedKind::Signature,
578                    TyOrSig::ClosureSig(closure_sig),
579                    expected_trait_ref.map(|tr| tr.print_only_trait_path()),
580                )
581            } else {
582                (
583                    ActualImplExpectedKind::Other,
584                    TyOrSig::Ty(self_ty),
585                    expected_trait_ref.map(|tr| tr.print_only_trait_path()),
586                )
587            }
588        } else if passive_voice {
589            (
590                ActualImplExpectedKind::Passive,
591                TyOrSig::Ty(expected_trait_ref.map(|tr| tr.self_ty())),
592                expected_trait_ref.map(|tr| tr.print_only_trait_path()),
593            )
594        } else {
595            (
596                ActualImplExpectedKind::Other,
597                TyOrSig::Ty(expected_trait_ref.map(|tr| tr.self_ty())),
598                expected_trait_ref.map(|tr| tr.print_only_trait_path()),
599            )
600        };
601
602        let (lt_kind, lifetime_1, lifetime_2) = match (has_sub, has_sup) {
603            (Some(n1), Some(n2)) => {
604                (ActualImplExpectedLifetimeKind::Two, std::cmp::min(n1, n2), std::cmp::max(n1, n2))
605            }
606            (Some(n), _) | (_, Some(n)) => (ActualImplExpectedLifetimeKind::Any, n, 0),
607            (None, None) => {
608                if let Some(n) = expected_has_vid {
609                    (ActualImplExpectedLifetimeKind::Some, n, 0)
610                } else {
611                    (ActualImplExpectedLifetimeKind::Nothing, 0, 0)
612                }
613            }
614        };
615
616        let note_1 = ActualImplExplNotes::new_expected(
617            kind,
618            lt_kind,
619            ty_or_sig,
620            trait_path,
621            lifetime_1,
622            lifetime_2,
623            satisfy_span,
624            item_span,
625            outer_span,
626            item_name,
627        );
628
629        let mut actual_trait_ref = highlight_trait_ref(actual_trait_ref);
630        actual_trait_ref.highlight.maybe_highlighting_region(vid, actual_has_vid);
631
632        let passive_voice = match actual_has_vid {
633            Some(_) => any_self_ty_has_vid,
634            None => true,
635        };
636
637        let trait_path = actual_trait_ref.map(|tr| tr.print_only_trait_path());
638        let ty = actual_trait_ref.map(|tr| tr.self_ty()).to_string();
639        let has_lifetime = actual_has_vid.is_some();
640        let lifetime = actual_has_vid.unwrap_or_default();
641
642        let note_2 = if same_self_type {
643            let impl_candidates = self.cx.find_similar_impl_candidates(
644                actual_trait_ref.value.def_id,
645                actual_trait_ref.value.self_ty(),
646            );
647            let span = if let [candidate] = impl_candidates {
648                Some(self.tcx().def_span(candidate.impl_def_id))
649            } else {
650                None
651            };
652            ActualImplExplNotes::ButActuallyImplementsTrait {
653                trait_path,
654                has_lifetime,
655                lifetime,
656                span,
657            }
658        } else if passive_voice {
659            ActualImplExplNotes::ButActuallyImplementedForTy {
660                trait_path,
661                ty,
662                has_lifetime,
663                lifetime,
664            }
665        } else {
666            ActualImplExplNotes::ButActuallyTyImplements { trait_path, ty, has_lifetime, lifetime }
667        };
668
669        ::alloc::boxed::box_assume_init_into_vec_unsafe(::alloc::intrinsics::write_box_via_move(::alloc::boxed::Box::new_uninit(),
        [note_1, note_2]))vec![note_1, note_2]
670    }
671}