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