compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs RUST 3,810 lines View on github.com → Search inside
File is large — showing lines 1–2,000 of 3,810.
1// ignore-tidy-filelength2use core::ops::ControlFlow;3use std::borrow::Cow;4use std::collections::hash_set;5use std::path::PathBuf;67use rustc_ast::ast::LitKind;8use rustc_ast::{LitIntType, TraitObjectSyntax};9use rustc_data_structures::fx::{FxHashMap, FxHashSet};10use rustc_data_structures::unord::UnordSet;11use rustc_errors::codes::*;12use rustc_errors::{13    Applicability, Diag, ErrorGuaranteed, Level, MultiSpan, StashKey, StringPart, Suggestions, msg,14    pluralize, struct_span_code_err,15};16use rustc_hir::attrs::diagnostic::CustomDiagnostic;17use rustc_hir::def_id::{DefId, LOCAL_CRATE, LocalDefId};18use rustc_hir::intravisit::Visitor;19use rustc_hir::{self as hir, LangItem, Node, find_attr};20use rustc_infer::infer::{InferOk, TypeTrace};21use rustc_infer::traits::ImplSource;22use rustc_infer::traits::solve::Goal;23use rustc_middle::traits::SignatureMismatchData;24use rustc_middle::traits::select::OverflowError;25use rustc_middle::ty::abstract_const::NotConstEvaluatable;26use rustc_middle::ty::error::{ExpectedFound, TypeError};27use rustc_middle::ty::print::{28    PrintPolyTraitPredicateExt, PrintPolyTraitRefExt as _, PrintTraitPredicateExt as _,29    PrintTraitRefExt as _, with_forced_trimmed_paths,30};31use rustc_middle::ty::{32    self, GenericArgKind, TraitRef, Ty, TyCtxt, TypeFoldable, TypeFolder, TypeSuperFoldable,33    TypeVisitableExt, Unnormalized, Upcast,34};35use rustc_middle::{bug, span_bug};36use rustc_span::def_id::CrateNum;37use rustc_span::{BytePos, DUMMY_SP, STDLIB_STABLE_CRATES, Span, Symbol, sym};38use tracing::{debug, instrument};3940use super::suggestions::get_explanation_based_on_obligation;41use super::{ArgKind, CandidateSimilarity, GetSafeTransmuteErrorAndReason, ImplCandidate};42use crate::diagnostics::{43    ClosureFnMutLabel, ClosureFnOnceLabel, ClosureKindMismatch, CoroClosureNotFn,44};45use crate::error_reporting::TypeErrCtxt;46use crate::error_reporting::infer::TyCategory;47use crate::error_reporting::traits::report_dyn_incompatibility;48use crate::infer::{self, InferCtxt, InferCtxtExt as _};49use crate::traits::query::evaluate_obligation::InferCtxtExt as _;50use crate::traits::{51    MismatchedProjectionTypes, NormalizeExt, Obligation, ObligationCause, ObligationCauseCode,52    ObligationCtxt, PredicateObligation, SelectionContext, SelectionError, elaborate,53    specialization_graph,54};5556impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {57    /// The `root_obligation` parameter should be the `root_obligation` field58    /// from a `FulfillmentError`. If no `FulfillmentError` is available,59    /// then it should be the same as `obligation`.60    pub fn report_selection_error(61        &self,62        mut obligation: PredicateObligation<'tcx>,63        root_obligation: &PredicateObligation<'tcx>,64        error: &SelectionError<'tcx>,65    ) -> ErrorGuaranteed {66        let tcx = self.tcx;67        let mut span = obligation.cause.span;68        let mut long_ty_file = None;6970        let mut err = match *error {71            SelectionError::Unimplemented => {72                // If this obligation was generated as a result of well-formedness checking, see if we73                // can get a better error message by performing HIR-based well-formedness checking.74                if let ObligationCauseCode::WellFormed(Some(wf_loc)) =75                    root_obligation.cause.code().peel_derives()76                    && !obligation.predicate.has_non_region_infer()77                {78                    if let Some(cause) = self.tcx.diagnostic_hir_wf_check((79                        tcx.erase_and_anonymize_regions(obligation.predicate),80                        *wf_loc,81                    )) {82                        obligation.cause = cause.clone();83                        span = obligation.cause.span;84                    }85                }8687                if let ObligationCauseCode::CompareImplItem {88                    impl_item_def_id,89                    trait_item_def_id,90                    kind: _,91                } = *obligation.cause.code()92                {93                    debug!("ObligationCauseCode::CompareImplItemObligation");94                    return self95                        .report_extra_impl_obligation(96                            span,97                            impl_item_def_id,98                            trait_item_def_id,99                            &format!("`{}`", obligation.predicate),100                        )101                        .emit();102                }103104                // Report a const-param specific error105                if let ObligationCauseCode::ConstParam(ty) = *obligation.cause.code().peel_derives()106                {107                    return self.report_const_param_not_wf(ty, &obligation).emit();108                }109110                let bound_predicate = obligation.predicate.kind();111                match bound_predicate.skip_binder() {112                    ty::PredicateKind::Clause(ty::ClauseKind::Trait(trait_predicate)) => {113                        let leaf_trait_predicate =114                            self.resolve_vars_if_possible(bound_predicate.rebind(trait_predicate));115116                        // Let's use the root obligation as the main message, when we care about the117                        // most general case ("X doesn't implement Pattern<'_>") over the case that118                        // happened to fail ("char doesn't implement Fn(&mut char)").119                        //120                        // We rely on a few heuristics to identify cases where this root121                        // obligation is more important than the leaf obligation:122                        let (main_trait_predicate, main_obligation) =123                            if let ty::PredicateKind::Clause(124                            ty::ClauseKind::Trait(root_pred)125                        ) = root_obligation.predicate.kind().skip_binder()126                            && !leaf_trait_predicate.self_ty().skip_binder().has_escaping_bound_vars()127                            && !root_pred.self_ty().has_escaping_bound_vars()128                            // The type of the leaf predicate is (roughly) the same as the type129                            // from the root predicate, as a proxy for "we care about the root"130                            // FIXME: this doesn't account for trivial derefs, but works as a first131                            // approximation.132                            && (133                                // `T: Trait` && `&&T: OtherTrait`, we want `OtherTrait`134                                self.can_eq(135                                    obligation.param_env,136                                    leaf_trait_predicate.self_ty().skip_binder(),137                                    root_pred.self_ty().peel_refs(),138                                )139                                // `&str: Iterator` && `&str: IntoIterator`, we want `IntoIterator`140                                || self.can_eq(141                                    obligation.param_env,142                                    leaf_trait_predicate.self_ty().skip_binder(),143                                    root_pred.self_ty(),144                                )145                            )146                            // The leaf trait and the root trait are different, so as to avoid147                            // talking about `&mut T: Trait` and instead remain talking about148                            // `T: Trait` instead149                            && leaf_trait_predicate.def_id() != root_pred.def_id()150                            // The root trait is not `Unsize`, as to avoid talking about it in151                            // `tests/ui/coercion/coerce-issue-49593-box-never.rs`.152                            && !self.tcx.is_lang_item(root_pred.def_id(), LangItem::Unsize)153                            {154                                (155                                    self.resolve_vars_if_possible(156                                        root_obligation.predicate.kind().rebind(root_pred),157                                    ),158                                    root_obligation,159                                )160                            } else {161                                (leaf_trait_predicate, &obligation)162                            };163164                        if let Some(guar) = self165                            .emit_specialized_closure_kind_error(&obligation, leaf_trait_predicate)166                        {167                            return guar;168                        }169170                        if let Err(guar) = leaf_trait_predicate.error_reported() {171                            return guar;172                        }173                        // Silence redundant errors on binding access that are already174                        // reported on the binding definition (#56607).175                        if let Err(guar) = self.fn_arg_obligation(&obligation) {176                            return guar;177                        }178                        let (post_message, pre_message, type_def) = self179                            .get_parent_trait_ref(obligation.cause.code())180                            .map(|(t, s)| {181                                let t = self.tcx.short_string(t, &mut long_ty_file);182                                (183                                    format!(" in `{t}`"),184                                    format!("within `{t}`, "),185                                    s.map(|s| (format!("within this `{t}`"), s)),186                                )187                            })188                            .unwrap_or_default();189190                        let CustomDiagnostic { message, label, notes, parent_label } = self191                            .on_unimplemented_note(192                                main_trait_predicate,193                                main_obligation,194                                &mut long_ty_file,195                            );196197                        let have_alt_message = message.is_some() || label.is_some();198199                        let message = message.unwrap_or_else(|| {200                            self.get_standard_error_message(201                                main_trait_predicate,202                                None,203                                post_message,204                                &mut long_ty_file,205                            )206                        });207                        let is_try_conversion =208                            self.is_try_conversion(span, main_trait_predicate.def_id());209                        let is_question_mark = matches!(210                            root_obligation.cause.code().peel_derives(),211                            ObligationCauseCode::QuestionMark,212                        ) && !(self213                            .tcx214                            .is_diagnostic_item(sym::FromResidual, main_trait_predicate.def_id())215                            || self.tcx.is_lang_item(main_trait_predicate.def_id(), LangItem::Try));216                        let is_unsize =217                            self.tcx.is_lang_item(leaf_trait_predicate.def_id(), LangItem::Unsize);218                        let question_mark_message = "the question mark operation (`?`) implicitly \219                                                     performs a conversion on the error value \220                                                     using the `From` trait";221                        let (message, notes) = if is_try_conversion {222                            let ty = self.tcx.short_string(223                                main_trait_predicate.skip_binder().self_ty(),224                                &mut long_ty_file,225                            );226                            // We have a `-> Result<_, E1>` and `gives_E2()?`.227                            (228                                format!("`?` couldn't convert the error to `{ty}`"),229                                vec![question_mark_message.to_owned()],230                            )231                        } else if is_question_mark {232                            let main_trait_predicate =233                                self.tcx.short_string(main_trait_predicate, &mut long_ty_file);234                            // Similar to the case above, but in this case the conversion is for a235                            // trait object: `-> Result<_, Box<dyn Error>` and `gives_E()?` when236                            // `E: Error` isn't met.237                            (238                                format!(239                                    "`?` couldn't convert the error: `{main_trait_predicate}` is \240                                     not satisfied",241                                ),242                                vec![question_mark_message.to_owned()],243                            )244                        } else {245                            (message, notes)246                        };247248                        let (err_msg, safe_transmute_explanation) = if self249                            .tcx250                            .is_lang_item(main_trait_predicate.def_id(), LangItem::TransmuteTrait)251                        {252                            // Recompute the safe transmute reason and use that for the error reporting253                            let (report_obligation, report_pred) = self254                                .select_transmute_obligation_for_reporting(255                                    &obligation,256                                    main_trait_predicate,257                                    root_obligation,258                                );259260                            match self.get_safe_transmute_error_and_reason(261                                report_obligation,262                                report_pred,263                                span,264                            ) {265                                GetSafeTransmuteErrorAndReason::Silent => {266                                    return self267                                        .dcx()268                                        .span_delayed_bug(span, "silent safe transmute error");269                                }270                                GetSafeTransmuteErrorAndReason::Default => (message, None),271                                GetSafeTransmuteErrorAndReason::Error {272                                    err_msg,273                                    safe_transmute_explanation,274                                } => (err_msg, safe_transmute_explanation),275                            }276                        } else {277                            (message, None)278                        };279280                        let mut err = struct_span_code_err!(self.dcx(), span, E0277, "{}", err_msg);281282                        let trait_def_id = main_trait_predicate.def_id();283                        let leaf_trait_def_id = leaf_trait_predicate.def_id();284                        if (self.tcx.is_diagnostic_item(sym::From, trait_def_id)285                            || self.tcx.is_diagnostic_item(sym::TryFrom, trait_def_id))286                            && (self.tcx.is_diagnostic_item(sym::From, leaf_trait_def_id)287                                || self.tcx.is_diagnostic_item(sym::TryFrom, leaf_trait_def_id))288                        {289                            let trait_ref = leaf_trait_predicate.skip_binder().trait_ref;290291                            if let Some(found_ty) =292                                trait_ref.args.get(1).and_then(|arg| arg.as_type())293                            {294                                let ty = main_trait_predicate.skip_binder().self_ty();295296                                if let Some(cast_ty) =297                                    self.find_explicit_cast_type(obligation.param_env, found_ty, ty)298                                {299                                    let found_ty_str =300                                        self.tcx.short_string(found_ty, &mut long_ty_file);301                                    let cast_ty_str =302                                        self.tcx.short_string(cast_ty, &mut long_ty_file);303304                                    err.help(format!(305                                        "consider casting the `{found_ty_str}` value to `{cast_ty_str}`",306                                    ));307                                }308                            }309                        }310311                        *err.long_ty_path() = long_ty_file;312313                        let mut suggested = false;314                        let mut noted_missing_impl = false;315                        if is_try_conversion || is_question_mark {316                            (suggested, noted_missing_impl) = self.try_conversion_context(317                                &obligation,318                                main_trait_predicate,319                                &mut err,320                            );321                        }322323                        suggested |= self.detect_negative_literal(324                            &obligation,325                            main_trait_predicate,326                            &mut err,327                        );328329                        if let Some(ret_span) = self.return_type_span(&obligation) {330                            if is_try_conversion {331                                let ty = self.tcx.short_string(332                                    main_trait_predicate.skip_binder().self_ty(),333                                    err.long_ty_path(),334                                );335                                err.span_label(336                                    ret_span,337                                    format!("expected `{ty}` because of this"),338                                );339                            } else if is_question_mark {340                                let main_trait_predicate =341                                    self.tcx.short_string(main_trait_predicate, err.long_ty_path());342                                err.span_label(343                                    ret_span,344                                    format!("required `{main_trait_predicate}` because of this"),345                                );346                            }347                        }348349                        if tcx.is_lang_item(leaf_trait_predicate.def_id(), LangItem::Tuple) {350                            self.add_tuple_trait_message(351                                obligation.cause.code().peel_derives(),352                                &mut err,353                            );354                        }355356                        let explanation = get_explanation_based_on_obligation(357                            self.tcx,358                            &obligation,359                            leaf_trait_predicate,360                            pre_message,361                            err.long_ty_path(),362                        );363364                        self.check_for_binding_assigned_block_without_tail_expression(365                            &obligation,366                            &mut err,367                            leaf_trait_predicate,368                        );369                        self.suggest_add_result_as_return_type(370                            &obligation,371                            &mut err,372                            leaf_trait_predicate,373                        );374375                        if self.suggest_add_reference_to_arg(376                            &obligation,377                            &mut err,378                            leaf_trait_predicate,379                            have_alt_message,380                        ) {381                            self.note_obligation_cause(&mut err, &obligation);382                            return err.emit();383                        }384385                        let ty_span = match leaf_trait_predicate.self_ty().skip_binder().kind() {386                            ty::Adt(def, _)387                                if def.did().is_local()388                                    && !self389                                        .can_suggest_derive(&obligation, leaf_trait_predicate) =>390                            {391                                self.tcx.def_span(def.did())392                            }393                            _ => DUMMY_SP,394                        };395                        if let Some(s) = label {396                            // If it has a custom `#[rustc_on_unimplemented]`397                            // error message, let's display it as the label!398                            err.span_label(span, s);399                            if !matches!(leaf_trait_predicate.skip_binder().self_ty().kind(), ty::Param(_))400                                // When the self type is a type param We don't need to "the trait401                                // `std::marker::Sized` is not implemented for `T`" as we will point402                                // at the type param with a label to suggest constraining it.403                                && !self.tcx.is_diagnostic_item(sym::FromResidual, leaf_trait_predicate.def_id())404                            // Don't say "the trait `FromResidual<Option<Infallible>>` is405                            // not implemented for `Result<T, E>`".406                            {407                                // We do this just so that the JSON output's `help` position is the408                                // right one and not `file.rs:1:1`. The render is the same.409                                if ty_span == DUMMY_SP {410                                    err.help(explanation);411                                } else {412                                    err.span_help(ty_span, explanation);413                                }414                            }415                        } else if let Some(custom_explanation) = safe_transmute_explanation {416                            err.span_label(span, custom_explanation);417                        } else if (explanation.len() > self.tcx.sess.diagnostic_width()418                            || ty_span != DUMMY_SP)419                            && !noted_missing_impl420                        {421                            // Really long types don't look good as span labels, instead move it422                            // to a `help`.423                            err.span_label(span, "unsatisfied trait bound");424425                            // We do this just so that the JSON output's `help` position is the426                            // right one and not `file.rs:1:1`. The render is the same.427                            if ty_span == DUMMY_SP {428                                err.help(explanation);429                            } else {430                                err.span_help(ty_span, explanation);431                            }432                        } else {433                            err.span_label(span, explanation);434                        }435436                        if let ObligationCauseCode::Coercion { source, target } =437                            *obligation.cause.code().peel_derives()438                        {439                            if self.tcx.is_lang_item(leaf_trait_predicate.def_id(), LangItem::Sized)440                            {441                                self.suggest_borrowing_for_object_cast(442                                    &mut err,443                                    root_obligation,444                                    source,445                                    target,446                                );447                            }448                        }449450                        if let Some((msg, span)) = type_def {451                            err.span_label(span, msg);452                        }453                        // `#[rustc_on_unimplemented]` notes for derivable traits (e.g. `Debug`'s454                        // "add `#[derive(Debug)]` to `X` or manually `impl Debug for X`") duplicate455                        // the `consider annotating X with #[derive(..)]` suggestion that456                        // `suggest_derive` emits below, so skip them when that suggestion will be457                        // shown. We keep the note otherwise (e.g. when a field isn't `Debug`, so458                        // the derive can't be suggested) to avoid leaving the diagnostic without459                        // actionable guidance.460                        let derive_suggestion_will_be_shown = main_trait_predicate461                            == leaf_trait_predicate462                            && self.can_suggest_derive(&obligation, leaf_trait_predicate);463                        if !derive_suggestion_will_be_shown {464                            for note in notes {465                                // If it has a custom `#[rustc_on_unimplemented]` note, let's display466                                // it.467                                err.note(note);468                            }469                        }470                        if let Some(s) = parent_label {471                            let body = obligation.cause.body_id;472                            err.span_label(tcx.def_span(body), s);473                        }474475                        self.suggest_floating_point_literal(476                            &obligation,477                            &mut err,478                            leaf_trait_predicate,479                        );480                        self.suggest_dereferencing_index(481                            &obligation,482                            &mut err,483                            leaf_trait_predicate,484                        );485                        suggested |=486                            self.suggest_dereferences(&obligation, &mut err, leaf_trait_predicate);487                        suggested |=488                            self.suggest_fn_call(&obligation, &mut err, leaf_trait_predicate);489                        suggested |= self.suggest_cast_to_fn_pointer(490                            &obligation,491                            &mut err,492                            leaf_trait_predicate,493                            main_trait_predicate,494                            span,495                        );496                        suggested |= self.suggest_remove_reference(497                            &obligation,498                            &mut err,499                            leaf_trait_predicate,500                        );501                        suggested |= self.suggest_semicolon_removal(502                            &obligation,503                            &mut err,504                            span,505                            leaf_trait_predicate,506                        );507                        self.note_different_trait_with_same_name(508                            &mut err,509                            &obligation,510                            leaf_trait_predicate,511                        );512                        self.note_adt_version_mismatch(&mut err, leaf_trait_predicate);513                        self.suggest_remove_await(&obligation, &mut err);514                        self.suggest_derive(&obligation, &mut err, leaf_trait_predicate);515516                        if tcx.is_lang_item(leaf_trait_predicate.def_id(), LangItem::Try) {517                            self.suggest_await_before_try(518                                &mut err,519                                &obligation,520                                leaf_trait_predicate,521                                span,522                            );523                        }524525                        if self.suggest_add_clone_to_arg(526                            &obligation,527                            &mut err,528                            leaf_trait_predicate,529                        ) {530                            return err.emit();531                        }532533                        if self.suggest_impl_trait(&mut err, &obligation, leaf_trait_predicate) {534                            return err.emit();535                        }536537                        if is_unsize {538                            // If the obligation failed due to a missing implementation of the539                            // `Unsize` trait, give a pointer to why that might be the case540                            err.note(541                                "all implementations of `Unsize` are provided \542                                automatically by the compiler, see \543                                <https://doc.rust-lang.org/stable/std/marker/trait.Unsize.html> \544                                for more information",545                            );546                        }547548                        let is_fn_trait = tcx.is_fn_trait(leaf_trait_predicate.def_id());549                        let is_target_feature_fn = if let ty::FnDef(def_id, _) =550                            *leaf_trait_predicate.skip_binder().self_ty().kind()551                        {552                            !self.tcx.codegen_fn_attrs(def_id).target_features.is_empty()553                        } else {554                            false555                        };556                        if is_fn_trait && is_target_feature_fn {557                            err.note(558                                "`#[target_feature]` functions do not implement the `Fn` traits",559                            );560                            err.note(561                                "try casting the function to a `fn` pointer or wrapping it in a closure",562                            );563                        }564565                        self.note_field_shadowed_by_private_candidate_in_cause(566                            &mut err,567                            &obligation.cause,568                            obligation.param_env,569                        );570                        self.try_to_add_help_message(571                            &root_obligation,572                            &obligation,573                            leaf_trait_predicate,574                            &mut err,575                            span,576                            is_fn_trait,577                            suggested,578                        );579580                        // Changing mutability doesn't make a difference to whether we have581                        // an `Unsize` impl (Fixes ICE in #71036)582                        if !is_unsize {583                            self.suggest_change_mut(&obligation, &mut err, leaf_trait_predicate);584                        }585586                        // If this error is due to `!: Trait` not implemented but `(): Trait` is587                        // implemented, and fallback has occurred, then it could be due to a588                        // variable that used to fallback to `()` now falling back to `!`. Issue a589                        // note informing about the change in behaviour.590                        if leaf_trait_predicate.skip_binder().self_ty().is_never()591                            && self.diverging_fallback_has_occurred592                        {593                            let predicate = leaf_trait_predicate.map_bound(|trait_pred| {594                                trait_pred.with_replaced_self_ty(self.tcx, tcx.types.unit)595                            });596                            let unit_obligation = obligation.with(tcx, predicate);597                            if self.predicate_may_hold(&unit_obligation) {598                                err.note(599                                    "this error might have been caused by changes to \600                                    Rust's type-inference algorithm (see issue #148922 \601                                    <https://github.com/rust-lang/rust/issues/148922> \602                                    for more information)",603                                );604                                err.help(605                                    "you might have intended to use the type `()` here instead",606                                );607                            }608                        }609610                        self.explain_hrtb_projection(611                            &mut err,612                            leaf_trait_predicate,613                            obligation.param_env,614                            &obligation.cause,615                        );616                        self.suggest_desugaring_async_fn_in_trait(&mut err, main_trait_predicate);617618                        // Return early if the trait is Debug or Display and the invocation619                        // originates within a standard library macro, because the output620                        // is otherwise overwhelming and unhelpful (see #85844 for an621                        // example).622623                        let in_std_macro =624                            match obligation.cause.span.ctxt().outer_expn_data().macro_def_id {625                                Some(macro_def_id) => {626                                    let crate_name = tcx.crate_name(macro_def_id.krate);627                                    STDLIB_STABLE_CRATES.contains(&crate_name)628                                }629                                None => false,630                            };631632                        if in_std_macro633                            && matches!(634                                self.tcx.get_diagnostic_name(leaf_trait_predicate.def_id()),635                                Some(sym::Debug | sym::Display)636                            )637                        {638                            return err.emit();639                        }640641                        err642                    }643644                    ty::PredicateKind::Clause(ty::ClauseKind::HostEffect(predicate)) => self645                        .report_host_effect_error(646                            bound_predicate.rebind(predicate),647                            &obligation,648                            span,649                        ),650651                    ty::PredicateKind::Subtype(predicate) => {652                        // Errors for Subtype predicates show up as653                        // `FulfillmentErrorCode::SubtypeError`,654                        // not selection error.655                        span_bug!(span, "subtype requirement gave wrong error: `{:?}`", predicate)656                    }657658                    ty::PredicateKind::Coerce(predicate) => {659                        // Errors for Coerce predicates show up as660                        // `FulfillmentErrorCode::SubtypeError`,661                        // not selection error.662                        span_bug!(span, "coerce requirement gave wrong error: `{:?}`", predicate)663                    }664665                    ty::PredicateKind::Clause(ty::ClauseKind::RegionOutlives(..))666                    | ty::PredicateKind::Clause(ty::ClauseKind::TypeOutlives(..)) => {667                        span_bug!(668                            span,669                            "outlives clauses should not error outside borrowck. obligation: `{:?}`",670                            obligation671                        )672                    }673674                    ty::PredicateKind::Clause(ty::ClauseKind::Projection(..)) => {675                        span_bug!(676                            span,677                            "projection clauses should be implied from elsewhere. obligation: `{:?}`",678                            obligation679                        )680                    }681682                    ty::PredicateKind::DynCompatible(trait_def_id) => {683                        let violations = self.tcx.dyn_compatibility_violations(trait_def_id);684                        let mut err = report_dyn_incompatibility(685                            self.tcx,686                            span,687                            None,688                            trait_def_id,689                            violations,690                        );691                        if let hir::Node::Item(item) =692                            self.tcx.hir_node_by_def_id(obligation.cause.body_id)693                            && let hir::ItemKind::Impl(impl_) = item.kind694                            && let None = impl_.of_trait695                            && let hir::TyKind::TraitObject(_, tagged_ptr) = impl_.self_ty.kind696                            && let TraitObjectSyntax::None = tagged_ptr.tag()697                            && impl_.self_ty.span.edition().at_least_rust_2021()698                        {699                            // Silence the dyn-compatibility error in favor of the missing dyn on700                            // self type error. #131051.701                            err.downgrade_to_delayed_bug();702                        }703                        err704                    }705706                    ty::PredicateKind::Clause(ty::ClauseKind::WellFormed(ty)) => {707                        let ty = self.resolve_vars_if_possible(ty);708                        if self.next_trait_solver() {709                            if let Err(guar) = ty.error_reported() {710                                return guar;711                            }712713                            // FIXME: we'll need a better message which takes into account714                            // which bounds actually failed to hold.715                            self.dcx().struct_span_err(716                                span,717                                format!("the type `{ty}` is not well-formed"),718                            )719                        } else {720                            // WF predicates cannot themselves make721                            // errors. They can only block due to722                            // ambiguity; otherwise, they always723                            // degenerate into other obligations724                            // (which may fail).725                            span_bug!(span, "WF predicate not satisfied for {:?}", ty);726                        }727                    }728729                    // Errors for `ConstEvaluatable`, `ConstEquate` predicates show up as730                    // `SelectionError::ConstEvalFailure`, not `Unimplemented`.731                    // Ambiguous predicates should never error.732                    // We never return `Err` when proving `UnstableFeature` goal.733                    ty::PredicateKind::Clause(ty::ClauseKind::ConstEvaluatable(..))734                    | ty::PredicateKind::ConstEquate { .. }735                    | ty::PredicateKind::Ambiguous736                    | ty::PredicateKind::Clause(ty::ClauseKind::UnstableFeature { .. })737                    | ty::PredicateKind::NormalizesTo { .. }738                    | ty::PredicateKind::AliasRelate(..)739                    | ty::PredicateKind::Clause(ty::ClauseKind::ConstArgHasType { .. }) => {740                        span_bug!(741                            span,742                            "Unexpected `Predicate` for `SelectionError`: `{:?}`",743                            obligation744                        )745                    }746                }747            }748749            SelectionError::SignatureMismatch(SignatureMismatchData {750                found_trait_ref,751                expected_trait_ref,752                terr: terr @ TypeError::CyclicTy(_),753            }) => self.report_cyclic_signature_error(754                &obligation,755                found_trait_ref,756                expected_trait_ref,757                terr,758            ),759            SelectionError::SignatureMismatch(SignatureMismatchData {760                found_trait_ref,761                expected_trait_ref,762                terr: _,763            }) => {764                match self.report_signature_mismatch_error(765                    &obligation,766                    span,767                    found_trait_ref,768                    expected_trait_ref,769                ) {770                    Ok(err) => err,771                    Err(guar) => return guar,772                }773            }774775            SelectionError::TraitDynIncompatible(did) => {776                let violations = self.tcx.dyn_compatibility_violations(did);777                report_dyn_incompatibility(self.tcx, span, None, did, violations)778            }779780            SelectionError::NotConstEvaluatable(NotConstEvaluatable::MentionsInfer) => {781                bug!(782                    "MentionsInfer should have been handled in `traits/fulfill.rs` or `traits/select/mod.rs`"783                )784            }785            SelectionError::NotConstEvaluatable(NotConstEvaluatable::MentionsParam) => {786                match self.report_not_const_evaluatable_error(&obligation, span) {787                    Ok(err) => err,788                    Err(guar) => return guar,789                }790            }791792            // Already reported in the query.793            SelectionError::NotConstEvaluatable(NotConstEvaluatable::Error(guar))794            | SelectionError::Overflow(OverflowError::Error(guar)) => {795                self.set_tainted_by_errors(guar);796                return guar;797            }798799            SelectionError::Overflow(_) => {800                bug!("overflow should be handled before the `report_selection_error` path");801            }802803            SelectionError::ConstArgHasWrongType { ct, ct_ty, expected_ty } => {804                let expected_ty_str = self.tcx.short_string(expected_ty, &mut long_ty_file);805                let ct_str = self.tcx.short_string(ct, &mut long_ty_file);806                let mut diag = self.dcx().struct_span_err(807                    span,808                    format!("the constant `{ct_str}` is not of type `{expected_ty_str}`"),809                );810                diag.long_ty_path = long_ty_file;811812                self.note_type_err(813                    &mut diag,814                    &obligation.cause,815                    None,816                    None,817                    TypeError::Sorts(ty::error::ExpectedFound::new(expected_ty, ct_ty)),818                    false,819                    None,820                );821                diag822            }823        };824825        self.note_obligation_cause(&mut err, &obligation);826        err.emit()827    }828}829830impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {831    pub(super) fn apply_do_not_recommend(832        &self,833        obligation: &mut PredicateObligation<'tcx>,834        root_obligation: &PredicateObligation<'tcx>,835    ) -> bool {836        let mut base_cause = obligation.cause.code().clone();837        let mut applied_do_not_recommend = false;838        loop {839            if let ObligationCauseCode::ImplDerived(ref c) = base_cause {840                if self.tcx.do_not_recommend_impl(c.impl_or_alias_def_id) {841                    let code = (*c.derived.parent_code).clone();842                    // Keep more precise spans that still point within the parent obligation,843                    // but do not let hidden impl details move the span outside of it.844                    if code == *root_obligation.cause.code()845                        && root_obligation.cause.span.eq_ctxt(obligation.cause.span)846                        && !root_obligation.cause.span.contains(obligation.cause.span)847                    {848                        obligation.cause.span = root_obligation.cause.span;849                    }850                    obligation.cause.map_code(|_| code);851                    obligation.predicate = c.derived.parent_trait_pred.upcast(self.tcx);852                    applied_do_not_recommend = true;853                }854            }855            if let Some(parent_cause) = base_cause.parent() {856                base_cause = parent_cause.clone();857            } else {858                break;859            }860        }861862        applied_do_not_recommend863    }864865    fn report_host_effect_error(866        &self,867        predicate: ty::Binder<'tcx, ty::HostEffectPredicate<'tcx>>,868        main_obligation: &PredicateObligation<'tcx>,869        span: Span,870    ) -> Diag<'a> {871        // FIXME(const_trait_impl): We should recompute the predicate with `[const]`872        // if it's `const`, and if it holds, explain that this bound only873        // *conditionally* holds.874        let trait_ref = predicate.map_bound(|predicate| ty::TraitPredicate {875            trait_ref: predicate.trait_ref,876            polarity: ty::PredicatePolarity::Positive,877        });878        let mut file = None;879880        let err_msg = self.get_standard_error_message(881            trait_ref,882            Some(predicate.constness()),883            String::new(),884            &mut file,885        );886        let mut diag = struct_span_code_err!(self.dcx(), span, E0277, "{}", err_msg);887        *diag.long_ty_path() = file;888        let obligation = Obligation::new(889            self.tcx,890            ObligationCause::dummy(),891            main_obligation.param_env,892            trait_ref,893        );894        if !self.predicate_may_hold(&obligation) {895            diag.downgrade_to_delayed_bug();896        }897898        if let Ok(Some(ImplSource::UserDefined(impl_data))) =899            self.enter_forall(trait_ref, |trait_ref_for_select| {900                SelectionContext::new(self).select(&obligation.with(self.tcx, trait_ref_for_select))901            })902        {903            let impl_did = impl_data.impl_def_id;904            let trait_did = trait_ref.def_id();905            let impl_span = self.tcx.def_span(impl_did);906            let trait_name = self.tcx.item_name(trait_did);907908            if self.tcx.is_const_trait(trait_did) && !self.tcx.is_const_trait_impl(impl_did) {909                if !impl_did.is_local() {910                    diag.span_note(911                        impl_span,912                        format!("trait `{trait_name}` is implemented but not `const`"),913                    );914                }915916                if let Some(command) =917                    find_attr!(self.tcx, impl_did, OnConst {directive, ..} => directive.as_deref())918                        .flatten()919                {920                    let (_, format_args) = self.on_unimplemented_components(921                        trait_ref,922                        main_obligation,923                        diag.long_ty_path(),924                    );925                    let CustomDiagnostic { message, label, notes, parent_label: _ } =926                        command.eval(None, &format_args);927928                    if let Some(message) = message {929                        diag.primary_message(message);930                    }931                    if let Some(label) = label {932                        diag.span_label(span, label);933                    }934                    for note in notes {935                        diag.note(note);936                    }937                } else if let Some(impl_did) = impl_did.as_local()938                    && let item = self.tcx.hir_expect_item(impl_did)939                    && let hir::ItemKind::Impl(item) = item.kind940                    && let Some(of_trait) = item.of_trait941                {942                    // trait is const, impl is local and not const943                    diag.span_suggestion_verbose(944                        of_trait.trait_ref.path.span.shrink_to_lo(),945                        format!("make the `impl` of trait `{trait_name}` `const`"),946                        "const ".to_string(),947                        Applicability::MaybeIncorrect,948                    );949                }950            }951        } else if let ty::Param(param) = trait_ref.self_ty().skip_binder().kind()952            && let Some(generics) =953                self.tcx.hir_node_by_def_id(main_obligation.cause.body_id).generics()954        {955            let constraint = ty::print::with_no_trimmed_paths!(format!(956                "[const] {}",957                trait_ref.map_bound(|tr| tr.trait_ref).print_trait_sugared(),958            ));959            ty::suggest_constraining_type_param(960                self.tcx,961                generics,962                &mut diag,963                param.name.as_str(),964                &constraint,965                Some(trait_ref.def_id()),966                None,967            );968        }969        diag970    }971972    fn emit_specialized_closure_kind_error(973        &self,974        obligation: &PredicateObligation<'tcx>,975        mut trait_pred: ty::PolyTraitPredicate<'tcx>,976    ) -> Option<ErrorGuaranteed> {977        // If we end up on an `AsyncFnKindHelper` goal, try to unwrap the parent978        // `AsyncFn*` goal.979        if self.tcx.is_lang_item(trait_pred.def_id(), LangItem::AsyncFnKindHelper) {980            let mut code = obligation.cause.code();981            // Unwrap a `FunctionArg` cause, which has been refined from a derived obligation.982            if let ObligationCauseCode::FunctionArg { parent_code, .. } = code {983                code = &**parent_code;984            }985            // If we have a derived obligation, then the parent will be a `AsyncFn*` goal.986            if let Some((_, Some(parent))) = code.parent_with_predicate() {987                trait_pred = parent;988            }989        }990991        let self_ty = trait_pred.self_ty().skip_binder();992993        let (expected_kind, trait_prefix) =994            if let Some(expected_kind) = self.tcx.fn_trait_kind_from_def_id(trait_pred.def_id()) {995                (expected_kind, "")996            } else if let Some(expected_kind) =997                self.tcx.async_fn_trait_kind_from_def_id(trait_pred.def_id())998            {999                (expected_kind, "Async")1000            } else {1001                return None;1002            };10031004        let (closure_def_id, found_args, has_self_borrows) = match *self_ty.kind() {1005            ty::Closure(def_id, args) => {1006                (def_id, args.as_closure().sig().map_bound(|sig| sig.inputs()[0]), false)1007            }1008            ty::CoroutineClosure(def_id, args) => (1009                def_id,1010                args.as_coroutine_closure()1011                    .coroutine_closure_sig()1012                    .map_bound(|sig| sig.tupled_inputs_ty),1013                !args.as_coroutine_closure().tupled_upvars_ty().is_ty_var()1014                    && args.as_coroutine_closure().has_self_borrows(),1015            ),1016            _ => return None,1017        };10181019        let expected_args = trait_pred.map_bound(|trait_pred| trait_pred.trait_ref.args.type_at(1));10201021        // Verify that the arguments are compatible. If the signature is1022        // mismatched, then we have a totally different error to report.1023        if self.enter_forall(found_args, |found_args| {1024            self.enter_forall(expected_args, |expected_args| {1025                !self.can_eq(obligation.param_env, expected_args, found_args)1026            })1027        }) {1028            return None;1029        }10301031        if let Some(found_kind) = self.closure_kind(self_ty)1032            && !found_kind.extends(expected_kind)1033        {1034            let mut err = self.report_closure_error(1035                &obligation,1036                closure_def_id,1037                found_kind,1038                expected_kind,1039                trait_prefix,1040            );1041            self.note_obligation_cause(&mut err, &obligation);1042            return Some(err.emit());1043        }10441045        // If the closure has captures, then perhaps the reason that the trait1046        // is unimplemented is because async closures don't implement `Fn`/`FnMut`1047        // if they have captures.1048        if has_self_borrows && expected_kind != ty::ClosureKind::FnOnce {1049            let coro_kind = match self1050                .tcx1051                .coroutine_kind(self.tcx.coroutine_for_closure(closure_def_id))1052                .unwrap()1053            {1054                rustc_hir::CoroutineKind::Desugared(desugaring, _) => desugaring.to_string(),1055                coro => coro.to_string(),1056            };1057            let mut err = self.dcx().create_err(CoroClosureNotFn {1058                span: self.tcx.def_span(closure_def_id),1059                kind: expected_kind.as_str(),1060                coro_kind,1061            });1062            self.note_obligation_cause(&mut err, &obligation);1063            return Some(err.emit());1064        }10651066        None1067    }10681069    fn fn_arg_obligation(1070        &self,1071        obligation: &PredicateObligation<'tcx>,1072    ) -> Result<(), ErrorGuaranteed> {1073        if let ObligationCauseCode::FunctionArg { arg_hir_id, .. } = obligation.cause.code()1074            && let Node::Expr(arg) = self.tcx.hir_node(*arg_hir_id)1075            && let arg = arg.peel_borrows()1076            && let hir::ExprKind::Path(hir::QPath::Resolved(1077                None,1078                hir::Path { res: hir::def::Res::Local(hir_id), .. },1079            )) = arg.kind1080            && let Node::Pat(pat) = self.tcx.hir_node(*hir_id)1081            && let Some((preds, guar)) = self.reported_trait_errors.borrow().get(&pat.span)1082            && preds.contains(&obligation.as_goal())1083        {1084            return Err(*guar);1085        }1086        Ok(())1087    }10881089    fn detect_negative_literal(1090        &self,1091        obligation: &PredicateObligation<'tcx>,1092        trait_pred: ty::PolyTraitPredicate<'tcx>,1093        err: &mut Diag<'_>,1094    ) -> bool {1095        if let ObligationCauseCode::UnOp { hir_id, .. } = obligation.cause.code()1096            && let hir::Node::Expr(expr) = self.tcx.hir_node(*hir_id)1097            && let hir::ExprKind::Unary(hir::UnOp::Neg, inner) = expr.kind1098            && let hir::ExprKind::Lit(lit) = inner.kind1099            && let LitKind::Int(_, LitIntType::Unsuffixed) = lit.node1100        {1101            err.span_suggestion_verbose(1102                lit.span.shrink_to_hi(),1103                "consider specifying an integer type that can be negative",1104                match trait_pred.skip_binder().self_ty().kind() {1105                    ty::Uint(ty::UintTy::Usize) => "isize",1106                    ty::Uint(ty::UintTy::U8) => "i8",1107                    ty::Uint(ty::UintTy::U16) => "i16",1108                    ty::Uint(ty::UintTy::U32) => "i32",1109                    ty::Uint(ty::UintTy::U64) => "i64",1110                    ty::Uint(ty::UintTy::U128) => "i128",1111                    _ => "i64",1112                }1113                .to_string(),1114                Applicability::MaybeIncorrect,1115            );1116            return true;1117        }1118        false1119    }11201121    /// When the `E` of the resulting `Result<T, E>` in an expression `foo().bar().baz()?`,1122    /// identify those method chain sub-expressions that could or could not have been annotated1123    /// with `?`.1124    fn try_conversion_context(1125        &self,1126        obligation: &PredicateObligation<'tcx>,1127        trait_pred: ty::PolyTraitPredicate<'tcx>,1128        err: &mut Diag<'_>,1129    ) -> (bool, bool) {1130        let span = obligation.cause.span;1131        /// Look for the (direct) sub-expr of `?`, and return it if it's a `.` method call.1132        struct FindMethodSubexprOfTry {1133            search_span: Span,1134        }1135        impl<'v> Visitor<'v> for FindMethodSubexprOfTry {1136            type Result = ControlFlow<&'v hir::Expr<'v>>;1137            fn visit_expr(&mut self, ex: &'v hir::Expr<'v>) -> Self::Result {1138                if let hir::ExprKind::Match(expr, _arms, hir::MatchSource::TryDesugar(_)) = ex.kind1139                    && ex.span.with_lo(ex.span.hi() - BytePos(1)).source_equal(self.search_span)1140                    && let hir::ExprKind::Call(_, [expr, ..]) = expr.kind1141                {1142                    ControlFlow::Break(expr)1143                } else {1144                    hir::intravisit::walk_expr(self, ex)1145                }1146            }1147        }1148        let hir_id = self.tcx.local_def_id_to_hir_id(obligation.cause.body_id);1149        let Some(body_id) = self.tcx.hir_node(hir_id).body_id() else { return (false, false) };1150        let ControlFlow::Break(expr) =1151            (FindMethodSubexprOfTry { search_span: span }).visit_body(self.tcx.hir_body(body_id))1152        else {1153            return (false, false);1154        };1155        let Some(typeck) = &self.typeck_results else {1156            return (false, false);1157        };1158        let ObligationCauseCode::QuestionMark = obligation.cause.code().peel_derives() else {1159            return (false, false);1160        };1161        let self_ty = trait_pred.skip_binder().self_ty();1162        let found_ty = trait_pred.skip_binder().trait_ref.args.get(1).and_then(|a| a.as_type());1163        let noted_missing_impl =1164            self.note_missing_impl_for_question_mark(err, self_ty, found_ty, trait_pred);11651166        let mut prev_ty = self.resolve_vars_if_possible(1167            typeck.expr_ty_adjusted_opt(expr).unwrap_or(Ty::new_misc_error(self.tcx)),1168        );11691170        // We always look at the `E` type, because that's the only one affected by `?`. If the1171        // incorrect `Result<T, E>` is because of the `T`, we'll get an E0308 on the whole1172        // expression, after the `?` has "unwrapped" the `T`.1173        let get_e_type = |prev_ty: Ty<'tcx>| -> Option<Ty<'tcx>> {1174            let ty::Adt(def, args) = prev_ty.kind() else {1175                return None;1176            };1177            let Some(arg) = args.get(1) else {1178                return None;1179            };1180            if !self.tcx.is_diagnostic_item(sym::Result, def.did()) {1181                return None;1182            }1183            arg.as_type()1184        };11851186        let mut suggested = false;1187        let mut chain = vec![];11881189        // The following logic is similar to `point_at_chain`, but that's focused on associated types1190        let mut expr = expr;1191        while let hir::ExprKind::MethodCall(path_segment, rcvr_expr, args, span) = expr.kind {1192            // Point at every method call in the chain with the `Result` type.1193            // let foo = bar.iter().map(mapper)?;1194            //               ------ -----------1195            expr = rcvr_expr;1196            chain.push((span, prev_ty));11971198            let next_ty = self.resolve_vars_if_possible(1199                typeck.expr_ty_adjusted_opt(expr).unwrap_or(Ty::new_misc_error(self.tcx)),1200            );12011202            let is_diagnostic_item = |symbol: Symbol, ty: Ty<'tcx>| {1203                let ty::Adt(def, _) = ty.kind() else {1204                    return false;1205                };1206                self.tcx.is_diagnostic_item(symbol, def.did())1207            };1208            // For each method in the chain, see if this is `Result::map_err` or1209            // `Option::ok_or_else` and if it is, see if the closure passed to it has an incorrect1210            // trailing `;`.1211            if let Some(ty) = get_e_type(prev_ty)1212                && let Some(found_ty) = found_ty1213                // Ideally we would instead use `FnCtxt::lookup_method_for_diagnostic` for 100%1214                // accurate check, but we are in the wrong stage to do that and looking for1215                // `Result::map_err` by checking the Self type and the path segment is enough.1216                // sym::ok_or_else1217                && (1218                    ( // Result::map_err1219                        path_segment.ident.name == sym::map_err1220                            && is_diagnostic_item(sym::Result, next_ty)1221                    ) || ( // Option::ok_or_else1222                        path_segment.ident.name == sym::ok_or_else1223                            && is_diagnostic_item(sym::Option, next_ty)1224                    )1225                )1226                // Found `Result<_, ()>?`1227                && let ty::Tuple(tys) = found_ty.kind()1228                && tys.is_empty()1229                // The current method call returns `Result<_, ()>`1230                && self.can_eq(obligation.param_env, ty, found_ty)1231                // There's a single argument in the method call and it is a closure1232                && let [arg] = args1233                && let hir::ExprKind::Closure(closure) = arg.kind1234                // The closure has a block for its body with no tail expression1235                && let body = self.tcx.hir_body(closure.body)1236                && let hir::ExprKind::Block(block, _) = body.value.kind1237                && let None = block.expr1238                // The last statement is of a type that can be converted to the return error type1239                && let [.., stmt] = block.stmts1240                && let hir::StmtKind::Semi(expr) = stmt.kind1241                && let expr_ty = self.resolve_vars_if_possible(1242                    typeck.expr_ty_adjusted_opt(expr)1243                        .unwrap_or(Ty::new_misc_error(self.tcx)),1244                )1245                && self1246                    .infcx1247                    .type_implements_trait(1248                        self.tcx.get_diagnostic_item(sym::From).unwrap(),1249                        [self_ty, expr_ty],1250                        obligation.param_env,1251                    )1252                    .must_apply_modulo_regions()1253            {1254                suggested = true;1255                err.span_suggestion_short(1256                    stmt.span.with_lo(expr.span.hi()),1257                    "remove this semicolon",1258                    String::new(),1259                    Applicability::MachineApplicable,1260                );1261            }12621263            prev_ty = next_ty;12641265            if let hir::ExprKind::Path(hir::QPath::Resolved(None, path)) = expr.kind1266                && let hir::Path { res: hir::def::Res::Local(hir_id), .. } = path1267                && let hir::Node::Pat(binding) = self.tcx.hir_node(*hir_id)1268            {1269                let parent = self.tcx.parent_hir_node(binding.hir_id);1270                // We've reached the root of the method call chain...1271                if let hir::Node::LetStmt(local) = parent1272                    && let Some(binding_expr) = local.init1273                {1274                    // ...and it is a binding. Get the binding creation and continue the chain.1275                    expr = binding_expr;1276                }1277                if let hir::Node::Param(_param) = parent {1278                    // ...and it is an fn argument.1279                    break;1280                }1281            }1282        }1283        // `expr` is now the "root" expression of the method call chain, which can be any1284        // expression kind, like a method call or a path. If this expression is `Result<T, E>` as1285        // well, then we also point at it.1286        prev_ty = self.resolve_vars_if_possible(1287            typeck.expr_ty_adjusted_opt(expr).unwrap_or(Ty::new_misc_error(self.tcx)),1288        );1289        chain.push((expr.span, prev_ty));12901291        let mut prev = None;1292        let mut iter = chain.into_iter().rev().peekable();1293        while let Some((span, err_ty)) = iter.next() {1294            let is_last = iter.peek().is_none();1295            let err_ty = get_e_type(err_ty);1296            let err_ty = match (err_ty, prev) {1297                (Some(err_ty), Some(prev)) if !self.can_eq(obligation.param_env, err_ty, prev) => {1298                    err_ty1299                }1300                (Some(err_ty), None) => err_ty,1301                _ => {1302                    prev = err_ty;1303                    continue;1304                }1305            };13061307            let implements_from = self1308                .infcx1309                .type_implements_trait(1310                    self.tcx.get_diagnostic_item(sym::From).unwrap(),1311                    [self_ty, err_ty],1312                    obligation.param_env,1313                )1314                .must_apply_modulo_regions();13151316            let err_ty_str = self.tcx.short_string(err_ty, err.long_ty_path());1317            let label = if !implements_from && is_last {1318                format!(1319                    "this can't be annotated with `?` because it has type `Result<_, {err_ty_str}>`"1320                )1321            } else {1322                format!("this has type `Result<_, {err_ty_str}>`")1323            };13241325            if !suggested || !implements_from {1326                err.span_label(span, label);1327            }1328            prev = Some(err_ty);1329        }1330        (suggested, noted_missing_impl)1331    }13321333    fn note_missing_impl_for_question_mark(1334        &self,1335        err: &mut Diag<'_>,1336        self_ty: Ty<'_>,1337        found_ty: Option<Ty<'_>>,1338        trait_pred: ty::PolyTraitPredicate<'tcx>,1339    ) -> bool {1340        match (self_ty.kind(), found_ty) {1341            (ty::Adt(def, _), Some(ty))1342                if let ty::Adt(found, _) = ty.kind()1343                    && def.did().is_local()1344                    && found.did().is_local() =>1345            {1346                err.span_note(1347                    self.tcx.def_span(def.did()),1348                    format!("`{self_ty}` needs to implement `From<{ty}>`"),1349                );1350            }1351            (ty::Adt(def, _), None) if def.did().is_local() => {1352                let trait_path = self.tcx.short_string(1353                    trait_pred.skip_binder().trait_ref.print_only_trait_path(),1354                    err.long_ty_path(),1355                );1356                err.span_note(1357                    self.tcx.def_span(def.did()),1358                    format!("`{self_ty}` needs to implement `{trait_path}`"),1359                );1360            }1361            (ty::Adt(def, _), Some(ty)) if def.did().is_local() => {1362                err.span_note(1363                    self.tcx.def_span(def.did()),1364                    format!("`{self_ty}` needs to implement `From<{ty}>`"),1365                );1366            }1367            (_, Some(ty))1368                if let ty::Adt(def, _) = ty.kind()1369                    && def.did().is_local() =>1370            {1371                err.span_note(1372                    self.tcx.def_span(def.did()),1373                    format!("`{ty}` needs to implement `Into<{self_ty}>`"),1374                );1375            }1376            _ => return false,1377        }1378        true1379    }13801381    fn report_const_param_not_wf(1382        &self,1383        ty: Ty<'tcx>,1384        obligation: &PredicateObligation<'tcx>,1385    ) -> Diag<'a> {1386        let def_id = obligation.cause.body_id;1387        let span = self.tcx.ty_span(def_id);13881389        let mut file = None;1390        let ty_str = self.tcx.short_string(ty, &mut file);1391        let mut diag = match ty.kind() {1392            ty::Float(_) => {1393                struct_span_code_err!(1394                    self.dcx(),1395                    span,1396                    E0741,1397                    "`{ty_str}` is forbidden as the type of a const generic parameter",1398                )1399            }1400            ty::FnPtr(..) => {1401                struct_span_code_err!(1402                    self.dcx(),1403                    span,1404                    E0741,1405                    "using function pointers as const generic parameters is forbidden",1406                )1407            }1408            ty::RawPtr(_, _) => {1409                struct_span_code_err!(1410                    self.dcx(),1411                    span,1412                    E0741,1413                    "using raw pointers as const generic parameters is forbidden",1414                )1415            }1416            ty::Adt(def, _) => {1417                // We should probably see if we're *allowed* to derive `ConstParamTy` on the type...1418                let mut diag = struct_span_code_err!(1419                    self.dcx(),1420                    span,1421                    E0741,1422                    "`{ty_str}` must implement `ConstParamTy` to be used as the type of a const generic parameter",1423                );1424                // Only suggest derive if this isn't a derived obligation,1425                // and the struct is local.1426                if let Some(span) = self.tcx.hir_span_if_local(def.did())1427                    && obligation.cause.code().parent().is_none()1428                {1429                    if ty.is_structural_eq_shallow(self.tcx) {1430                        diag.span_suggestion(1431                            span.shrink_to_lo(),1432                            format!("add `#[derive(ConstParamTy)]` to the {}", def.descr()),1433                            "#[derive(ConstParamTy)]\n",1434                            Applicability::MachineApplicable,1435                        );1436                    } else {1437                        // FIXME(adt_const_params): We should check there's not already an1438                        // overlapping `Eq`/`PartialEq` impl.1439                        diag.span_suggestion(1440                            span.shrink_to_lo(),1441                            format!(1442                                "add `#[derive(ConstParamTy, PartialEq, Eq)]` to the {}",1443                                def.descr()1444                            ),1445                            "#[derive(ConstParamTy, PartialEq, Eq)]\n",1446                            Applicability::MachineApplicable,1447                        );1448                    }1449                }1450                diag1451            }1452            _ => {1453                struct_span_code_err!(1454                    self.dcx(),1455                    span,1456                    E0741,1457                    "`{ty_str}` can't be used as a const parameter type",1458                )1459            }1460        };1461        diag.long_ty_path = file;14621463        let mut code = obligation.cause.code();1464        let mut pred = obligation.predicate.as_trait_clause();1465        while let Some((next_code, next_pred)) = code.parent_with_predicate() {1466            if let Some(pred) = pred {1467                self.enter_forall(pred, |pred| {1468                    let ty = self.tcx.short_string(pred.self_ty(), diag.long_ty_path());1469                    let trait_path = self1470                        .tcx1471                        .short_string(pred.print_modifiers_and_trait_path(), diag.long_ty_path());1472                    diag.note(format!("`{ty}` must implement `{trait_path}`, but it does not"));1473                })1474            }1475            code = next_code;1476            pred = next_pred;1477        }14781479        diag1480    }1481}14821483impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {1484    fn can_match_trait(1485        &self,1486        param_env: ty::ParamEnv<'tcx>,1487        goal: ty::TraitPredicate<'tcx>,1488        assumption: ty::PolyTraitPredicate<'tcx>,1489    ) -> bool {1490        // Fast path1491        if goal.polarity != assumption.polarity() {1492            return false;1493        }14941495        let trait_assumption = self.instantiate_binder_with_fresh_vars(1496            DUMMY_SP,1497            infer::BoundRegionConversionTime::HigherRankedType,1498            assumption,1499        );15001501        self.can_eq(param_env, goal.trait_ref, trait_assumption.trait_ref)1502    }15031504    fn can_match_host_effect(1505        &self,1506        param_env: ty::ParamEnv<'tcx>,1507        goal: ty::HostEffectPredicate<'tcx>,1508        assumption: ty::Binder<'tcx, ty::HostEffectPredicate<'tcx>>,1509    ) -> bool {1510        let assumption = self.instantiate_binder_with_fresh_vars(1511            DUMMY_SP,1512            infer::BoundRegionConversionTime::HigherRankedType,1513            assumption,1514        );15151516        assumption.constness.satisfies(goal.constness)1517            && self.can_eq(param_env, goal.trait_ref, assumption.trait_ref)1518    }15191520    fn as_host_effect_clause(1521        predicate: ty::Predicate<'tcx>,1522    ) -> Option<ty::Binder<'tcx, ty::HostEffectPredicate<'tcx>>> {1523        predicate.as_clause().and_then(|clause| match clause.kind().skip_binder() {1524            ty::ClauseKind::HostEffect(pred) => Some(clause.kind().rebind(pred)),1525            _ => None,1526        })1527    }15281529    fn can_match_projection(1530        &self,1531        param_env: ty::ParamEnv<'tcx>,1532        goal: ty::ProjectionPredicate<'tcx>,1533        assumption: ty::PolyProjectionPredicate<'tcx>,1534    ) -> bool {1535        let assumption = self.instantiate_binder_with_fresh_vars(1536            DUMMY_SP,1537            infer::BoundRegionConversionTime::HigherRankedType,1538            assumption,1539        );15401541        self.can_eq(param_env, goal.projection_term, assumption.projection_term)1542            && self.can_eq(param_env, goal.term, assumption.term)1543    }15441545    // returns if `cond` not occurring implies that `error` does not occur - i.e., that1546    // `error` occurring implies that `cond` occurs.1547    #[instrument(level = "debug", skip(self), ret)]1548    pub(super) fn error_implies(1549        &self,1550        cond: Goal<'tcx, ty::Predicate<'tcx>>,1551        error: Goal<'tcx, ty::Predicate<'tcx>>,1552    ) -> bool {1553        if cond == error {1554            return true;1555        }15561557        // FIXME: We could be smarter about this, i.e. if cond's param-env is a1558        // subset of error's param-env. This only matters when binders will carry1559        // predicates though, and obviously only matters for error reporting.1560        if cond.param_env != error.param_env {1561            return false;1562        }1563        let param_env = error.param_env;15641565        if let Some(error) = error.predicate.as_trait_clause() {1566            self.enter_forall(error, |error| {1567                elaborate(self.tcx, std::iter::once(cond.predicate))1568                    .filter_map(|implied| implied.as_trait_clause())1569                    .any(|implied| self.can_match_trait(param_env, error, implied))1570            })1571        } else if let Some(error) = Self::as_host_effect_clause(error.predicate) {1572            self.enter_forall(error, |error| {1573                elaborate(self.tcx, std::iter::once(cond.predicate))1574                    .filter_map(Self::as_host_effect_clause)1575                    .any(|implied| self.can_match_host_effect(param_env, error, implied))1576            })1577        } else if let Some(error) = error.predicate.as_projection_clause() {1578            self.enter_forall(error, |error| {1579                elaborate(self.tcx, std::iter::once(cond.predicate))1580                    .filter_map(|implied| implied.as_projection_clause())1581                    .any(|implied| self.can_match_projection(param_env, error, implied))1582            })1583        } else {1584            false1585        }1586    }15871588    #[instrument(level = "debug", skip_all)]1589    pub(super) fn report_projection_error(1590        &self,1591        obligation: &PredicateObligation<'tcx>,1592        error: &MismatchedProjectionTypes<'tcx>,1593    ) -> ErrorGuaranteed {1594        let predicate = self.resolve_vars_if_possible(obligation.predicate);15951596        if let Err(e) = predicate.error_reported() {1597            return e;1598        }15991600        self.probe(|_| {1601            // try to find the mismatched types to report the error with.1602            //1603            // this can fail if the problem was higher-ranked, in which1604            // cause I have no idea for a good error message.1605            let bound_predicate = predicate.kind();1606            let (values, err) = match bound_predicate.skip_binder() {1607                ty::PredicateKind::Clause(ty::ClauseKind::Projection(data)) => {1608                    let ocx = ObligationCtxt::new(self);16091610                    let data = self.instantiate_binder_with_fresh_vars(1611                        obligation.cause.span,1612                        infer::BoundRegionConversionTime::HigherRankedType,1613                        bound_predicate.rebind(data),1614                    );1615                    let unnormalized_term = data.projection_term.to_term(self.tcx);1616                    // FIXME(-Znext-solver): For diagnostic purposes, it would be nice1617                    // to deeply normalize this type.1618                    let normalized_term = ocx.normalize(1619                        &obligation.cause,1620                        obligation.param_env,1621                        Unnormalized::new_wip(unnormalized_term),1622                    );16231624                    // constrain inference variables a bit more to nested obligations from normalize so1625                    // we can have more helpful errors.1626                    //1627                    // we intentionally drop errors from normalization here,1628                    // since the normalization is just done to improve the error message.1629                    let _ = ocx.try_evaluate_obligations();16301631                    if let Err(new_err) =1632                        ocx.eq(&obligation.cause, obligation.param_env, data.term, normalized_term)1633                    {1634                        (1635                            Some((1636                                data.projection_term,1637                                self.resolve_vars_if_possible(normalized_term),1638                                data.term,1639                            )),1640                            new_err,1641                        )1642                    } else {1643                        (None, error.err)1644                    }1645                }1646                ty::PredicateKind::AliasRelate(lhs, rhs, _) => {1647                    let derive_better_type_error =1648                        |alias_term: ty::AliasTerm<'tcx>, expected_term: ty::Term<'tcx>| {1649                            let ocx = ObligationCtxt::new(self);16501651                            let normalized_term = ocx.normalize(1652                                &ObligationCause::dummy(),1653                                obligation.param_env,1654                                Unnormalized::new_wip(alias_term.to_term(self.tcx)),1655                            );16561657                            if let Err(terr) = ocx.eq(1658                                &ObligationCause::dummy(),1659                                obligation.param_env,1660                                expected_term,1661                                normalized_term,1662                            ) {1663                                Some((terr, self.resolve_vars_if_possible(normalized_term)))1664                            } else {1665                                None1666                            }1667                        };16681669                    if let Some(lhs) = lhs.to_alias_term()1670                        && let ty::AliasTermKind::ProjectionTy { .. }1671                        | ty::AliasTermKind::ProjectionConst { .. } = lhs.kind1672                        && let Some((better_type_err, expected_term)) =1673                            derive_better_type_error(lhs, rhs)1674                    {1675                        (1676                            Some((lhs, self.resolve_vars_if_possible(expected_term), rhs)),1677                            better_type_err,1678                        )1679                    } else if let Some(rhs) = rhs.to_alias_term()1680                        && let ty::AliasTermKind::ProjectionTy { .. }1681                        | ty::AliasTermKind::ProjectionConst { .. } = rhs.kind1682                        && let Some((better_type_err, expected_term)) =1683                            derive_better_type_error(rhs, lhs)1684                    {1685                        (1686                            Some((rhs, self.resolve_vars_if_possible(expected_term), lhs)),1687                            better_type_err,1688                        )1689                    } else {1690                        (None, error.err)1691                    }1692                }1693                _ => (None, error.err),1694            };16951696            let mut file = None;1697            let (msg, span, closure_span) = values1698                .and_then(|(predicate, normalized_term, expected_term)| {1699                    self.maybe_detailed_projection_msg(1700                        obligation.cause.span,1701                        predicate,1702                        normalized_term,1703                        expected_term,1704                        &mut file,1705                    )1706                })1707                .unwrap_or_else(|| {1708                    (1709                        with_forced_trimmed_paths!(format!(1710                            "type mismatch resolving `{}`",1711                            self.tcx1712                                .short_string(self.resolve_vars_if_possible(predicate), &mut file),1713                        )),1714                        obligation.cause.span,1715                        None,1716                    )1717                });1718            let mut diag = struct_span_code_err!(self.dcx(), span, E0271, "{msg}");1719            *diag.long_ty_path() = file;1720            if let Some(span) = closure_span {1721                // Mark the closure decl so that it is seen even if we are pointing at the return1722                // type or expression.1723                //1724                // error[E0271]: expected `{closure@foo.rs:41:16}` to be a closure that returns1725                //               `Unit3`, but it returns `Unit4`1726                //   --> $DIR/foo.rs:43:171727                //    |1728                // LL |     let v = Unit2.m(1729                //    |                   - required by a bound introduced by this call1730                // ...1731                // LL |             f: |x| {1732                //    |                --- /* this span */1733                // LL |                 drop(x);1734                // LL |                 Unit41735                //    |                 ^^^^^ expected `Unit3`, found `Unit4`1736                //    |1737                diag.span_label(span, "this closure");1738                if !span.overlaps(obligation.cause.span) {1739                    // Point at the binding corresponding to the closure where it is used.1740                    diag.span_label(obligation.cause.span, "closure used here");1741                }1742            }17431744            let secondary_span = self.probe(|_| {1745                let ty::PredicateKind::Clause(ty::ClauseKind::Projection(proj)) =1746                    predicate.kind().skip_binder()1747                else {1748                    return None;1749                };1750                if !proj.projection_term.kind.is_trait_projection() {1751                    return None;1752                }17531754                let trait_ref = self.enter_forall_and_leak_universe(1755                    predicate.kind().rebind(proj.projection_term.trait_ref(self.tcx)),1756                );1757                let Ok(Some(ImplSource::UserDefined(impl_data))) =1758                    SelectionContext::new(self).select(&obligation.with(self.tcx, trait_ref))1759                else {1760                    return None;1761                };17621763                let Ok(node) =1764                    specialization_graph::assoc_def(self.tcx, impl_data.impl_def_id, proj.def_id())1765                else {1766                    return None;1767                };17681769                if !node.is_final() {1770                    return None;1771                }17721773                match self.tcx.hir_get_if_local(node.item.def_id) {1774                    Some(1775                        hir::Node::TraitItem(hir::TraitItem {1776                            kind: hir::TraitItemKind::Type(_, Some(ty)),1777                            ..1778                        })1779                        | hir::Node::ImplItem(hir::ImplItem {1780                            kind: hir::ImplItemKind::Type(ty),1781                            ..1782                        }),1783                    ) => Some((1784                        ty.span,1785                        with_forced_trimmed_paths!(Cow::from(format!(1786                            "type mismatch resolving `{}`",1787                            self.tcx.short_string(1788                                self.resolve_vars_if_possible(predicate),1789                                diag.long_ty_path()1790                            ),1791                        ))),1792                        true,1793                    )),1794                    _ => None,1795                }1796            });17971798            self.note_type_err(1799                &mut diag,1800                &obligation.cause,1801                secondary_span,1802                values.map(|(_, normalized_ty, expected_ty)| {1803                    obligation.param_env.and(infer::ValuePairs::Terms(ExpectedFound::new(1804                        expected_ty,1805                        normalized_ty,1806                    )))1807                }),1808                err,1809                false,1810                Some(span),1811            );1812            self.note_obligation_cause(&mut diag, obligation);1813            diag.emit()1814        })1815    }18161817    fn maybe_detailed_projection_msg(1818        &self,1819        mut span: Span,1820        projection_term: ty::AliasTerm<'tcx>,1821        normalized_ty: ty::Term<'tcx>,1822        expected_ty: ty::Term<'tcx>,1823        long_ty_path: &mut Option<PathBuf>,1824    ) -> Option<(String, Span, Option<Span>)> {1825        if !projection_term.kind.is_trait_projection() {1826            return None;1827        }18281829        let projection_def_id = projection_term.expect_projection_def_id();1830        let trait_def_id = projection_term.trait_def_id(self.tcx);1831        let self_ty = projection_term.self_ty();18321833        with_forced_trimmed_paths! {1834            if self.tcx.is_lang_item(projection_def_id, LangItem::FnOnceOutput) {1835                let (span, closure_span) = if let ty::Closure(def_id, _) = *self_ty.kind() {1836                    let def_span = self.tcx.def_span(def_id);1837                    if let Some(local_def_id) = def_id.as_local()1838                        && let node = self.tcx.hir_node_by_def_id(local_def_id)1839                        && let Some(fn_decl) = node.fn_decl()1840                        && let Some(id) = node.body_id()1841                    {1842                        span = match fn_decl.output {1843                            hir::FnRetTy::Return(ty) => ty.span,1844                            hir::FnRetTy::DefaultReturn(_) => {1845                                let body = self.tcx.hir_body(id);1846                                match body.value.kind {1847                                    hir::ExprKind::Block(1848                                        hir::Block { expr: Some(expr), .. },1849                                        _,1850                                    ) => expr.span,1851                                    hir::ExprKind::Block(1852                                        hir::Block {1853                                            expr: None, stmts: [.., last], ..1854                                        },1855                                        _,1856                                    ) => last.span,1857                                    _ => body.value.span,1858                                }1859                            }1860                        };1861                    }1862                    (span, Some(def_span))1863                } else {1864                    (span, None)1865                };1866                let item = match self_ty.kind() {1867                    ty::FnDef(def, _) => self.tcx.item_name(*def).to_string(),1868                    _ => self.tcx.short_string(self_ty, long_ty_path),1869                };1870                let expected_ty = self.tcx.short_string(expected_ty, long_ty_path);1871                let normalized_ty = self.tcx.short_string(normalized_ty, long_ty_path);1872                Some((format!(1873                    "expected `{item}` to return `{expected_ty}`, but it returns `{normalized_ty}`",1874                ), span, closure_span))1875            } else if self.tcx.is_lang_item(trait_def_id, LangItem::Future) {1876                let self_ty = self.tcx.short_string(self_ty, long_ty_path);1877                let expected_ty = self.tcx.short_string(expected_ty, long_ty_path);1878                let normalized_ty = self.tcx.short_string(normalized_ty, long_ty_path);1879                Some((format!(1880                    "expected `{self_ty}` to be a future that resolves to `{expected_ty}`, but it \1881                     resolves to `{normalized_ty}`"1882                ), span, None))1883            } else if Some(trait_def_id) == self.tcx.get_diagnostic_item(sym::Iterator) {1884                let self_ty = self.tcx.short_string(self_ty, long_ty_path);1885                let expected_ty = self.tcx.short_string(expected_ty, long_ty_path);1886                let normalized_ty = self.tcx.short_string(normalized_ty, long_ty_path);1887                Some((format!(1888                    "expected `{self_ty}` to be an iterator that yields `{expected_ty}`, but it \1889                     yields `{normalized_ty}`"1890                ), span, None))1891            } else {1892                None1893            }1894        }1895    }18961897    pub fn fuzzy_match_tys(1898        &self,1899        mut a: Ty<'tcx>,1900        mut b: Ty<'tcx>,1901        ignoring_lifetimes: bool,1902    ) -> Option<CandidateSimilarity> {1903        /// returns the fuzzy category of a given type, or None1904        /// if the type can be equated to any type.1905        fn type_category(tcx: TyCtxt<'_>, t: Ty<'_>) -> Option<u32> {1906            match t.kind() {1907                ty::Bool => Some(0),1908                ty::Char => Some(1),1909                ty::Str => Some(2),1910                ty::Adt(def, _) if tcx.is_lang_item(def.did(), LangItem::String) => Some(2),1911                ty::Int(..)1912                | ty::Uint(..)1913                | ty::Float(..)1914                | ty::Infer(ty::IntVar(..) | ty::FloatVar(..)) => Some(4),1915                ty::Ref(..) | ty::RawPtr(..) => Some(5),1916                ty::Array(..) | ty::Slice(..) => Some(6),1917                ty::FnDef(..) | ty::FnPtr(..) => Some(7),1918                ty::Dynamic(..) => Some(8),1919                ty::Closure(..) => Some(9),1920                ty::Tuple(..) => Some(10),1921                ty::Param(..) => Some(11),1922                ty::Alias(ty::AliasTy { kind: ty::Projection { .. }, .. }) => Some(12),1923                ty::Alias(ty::AliasTy { kind: ty::Inherent { .. }, .. }) => Some(13),1924                ty::Alias(ty::AliasTy { kind: ty::Opaque { .. }, .. }) => Some(14),1925                ty::Alias(ty::AliasTy { kind: ty::Free { .. }, .. }) => Some(15),1926                ty::Never => Some(16),1927                ty::Adt(..) => Some(17),1928                ty::Coroutine(..) => Some(18),1929                ty::Foreign(..) => Some(19),1930                ty::CoroutineWitness(..) => Some(20),1931                ty::CoroutineClosure(..) => Some(21),1932                ty::Pat(..) => Some(22),1933                ty::UnsafeBinder(..) => Some(23),1934                ty::Placeholder(..) | ty::Bound(..) | ty::Infer(..) | ty::Error(_) => None,1935            }1936        }19371938        let strip_references = |mut t: Ty<'tcx>| -> Ty<'tcx> {1939            loop {1940                match t.kind() {1941                    ty::Ref(_, inner, _) | ty::RawPtr(inner, _) => t = *inner,1942                    _ => break t,1943                }1944            }1945        };19461947        if !ignoring_lifetimes {1948            a = strip_references(a);1949            b = strip_references(b);1950        }19511952        let cat_a = type_category(self.tcx, a)?;1953        let cat_b = type_category(self.tcx, b)?;1954        if a == b {1955            Some(CandidateSimilarity::Exact { ignoring_lifetimes })1956        } else if cat_a == cat_b {1957            match (a.kind(), b.kind()) {1958                (ty::Adt(def_a, _), ty::Adt(def_b, _)) => def_a == def_b,1959                (ty::Foreign(def_a), ty::Foreign(def_b)) => def_a == def_b,1960                // Matching on references results in a lot of unhelpful1961                // suggestions, so let's just not do that for now.1962                //1963                // We still upgrade successful matches to `ignoring_lifetimes: true`1964                // to prioritize that impl.1965                (ty::Ref(..) | ty::RawPtr(..), ty::Ref(..) | ty::RawPtr(..)) => {1966                    self.fuzzy_match_tys(a, b, true).is_some()1967                }1968                _ => true,1969            }1970            .then_some(CandidateSimilarity::Fuzzy { ignoring_lifetimes })1971        } else if ignoring_lifetimes {1972            None1973        } else {1974            self.fuzzy_match_tys(a, b, true)1975        }1976    }19771978    pub(super) fn describe_closure(&self, kind: hir::ClosureKind) -> &'static str {1979        match kind {1980            hir::ClosureKind::Closure => "a closure",1981            hir::ClosureKind::Coroutine(hir::CoroutineKind::Coroutine(_)) => "a coroutine",1982            hir::ClosureKind::Coroutine(hir::CoroutineKind::Desugared(1983                hir::CoroutineDesugaring::Async,1984                hir::CoroutineSource::Block,1985            )) => "an async block",1986            hir::ClosureKind::Coroutine(hir::CoroutineKind::Desugared(1987                hir::CoroutineDesugaring::Async,1988                hir::CoroutineSource::Fn,1989            )) => "an async function",1990            hir::ClosureKind::Coroutine(hir::CoroutineKind::Desugared(1991                hir::CoroutineDesugaring::Async,1992                hir::CoroutineSource::Closure,1993            ))1994            | hir::ClosureKind::CoroutineClosure(hir::CoroutineDesugaring::Async) => {1995                "an async closure"1996            }1997            hir::ClosureKind::Coroutine(hir::CoroutineKind::Desugared(1998                hir::CoroutineDesugaring::AsyncGen,1999                hir::CoroutineSource::Block,2000            )) => "an async gen block",

Findings

✓ No findings reported for this file.

Get this view in your editor

Same data, no extra tab — call code_get_file + code_get_findings over MCP from Claude/Cursor/Copilot.