compiler/rustc_hir_analysis/src/check/wfcheck.rs RUST 2,558 lines View on github.com → Search inside
File is large — showing lines 1–2,000 of 2,558.
1use std::cell::LazyCell;2use std::ops::{ControlFlow, Deref};34use hir::intravisit::{self, Visitor};5use rustc_abi::{ExternAbi, ScalableElt};6use rustc_ast as ast;7use rustc_data_structures::fx::{FxHashSet, FxIndexMap, FxIndexSet};8use rustc_errors::codes::*;9use rustc_errors::{Applicability, ErrorGuaranteed, msg, pluralize, struct_span_code_err};10use rustc_hir as hir;11use rustc_hir::attrs::{EiiDecl, EiiImpl, EiiImplResolution};12use rustc_hir::def::{DefKind, Res};13use rustc_hir::def_id::{DefId, LocalDefId};14use rustc_hir::lang_items::LangItem;15use rustc_hir::{AmbigArg, ItemKind, find_attr};16use rustc_infer::infer::outlives::env::OutlivesEnvironment;17use rustc_infer::infer::{self, InferCtxt, SubregionOrigin, TyCtxtInferExt};18use rustc_infer::traits::PredicateObligations;19use rustc_lint_defs::builtin::SHADOWING_SUPERTRAIT_ITEMS;20use rustc_macros::Diagnostic;21use rustc_middle::mir::interpret::ErrorHandled;22use rustc_middle::traits::solve::NoSolution;23use rustc_middle::ty::trait_def::TraitSpecializationKind;24use rustc_middle::ty::{25    self, GenericArgKind, GenericArgs, GenericParamDefKind, Ty, TyCtxt, TypeFlags, TypeFoldable,26    TypeSuperVisitable, TypeVisitable, TypeVisitableExt, TypeVisitor, TypingMode, Unnormalized,27    Upcast,28};29use rustc_middle::{bug, span_bug};30use rustc_session::errors::feature_err;31use rustc_span::{DUMMY_SP, Span, sym};32use rustc_trait_selection::error_reporting::InferCtxtErrorExt;33use rustc_trait_selection::regions::{InferCtxtRegionExt, OutlivesEnvironmentBuildExt};34use rustc_trait_selection::traits::misc::{35    ConstParamTyImplementationError, type_allowed_to_implement_const_param_ty,36};37use rustc_trait_selection::traits::query::evaluate_obligation::InferCtxtExt as _;38use rustc_trait_selection::traits::{39    self, FulfillmentError, Obligation, ObligationCause, ObligationCauseCode, ObligationCtxt,40    WellFormedLoc,41};42use tracing::{debug, instrument};4344use super::compare_eii::{compare_eii_function_types, compare_eii_statics};45use crate::autoderef::Autoderef;46use crate::constrained_generic_params::{Parameter, identify_constrained_generic_params};47use crate::diagnostics;48use crate::diagnostics::InvalidReceiverTyHint;4950pub(super) struct WfCheckingCtxt<'a, 'tcx> {51    pub(super) ocx: ObligationCtxt<'a, 'tcx, FulfillmentError<'tcx>>,52    body_def_id: LocalDefId,53    param_env: ty::ParamEnv<'tcx>,54}55impl<'a, 'tcx> Deref for WfCheckingCtxt<'a, 'tcx> {56    type Target = ObligationCtxt<'a, 'tcx, FulfillmentError<'tcx>>;57    fn deref(&self) -> &Self::Target {58        &self.ocx59    }60}6162impl<'tcx> WfCheckingCtxt<'_, 'tcx> {63    fn tcx(&self) -> TyCtxt<'tcx> {64        self.ocx.infcx.tcx65    }6667    // Convenience function to normalize during wfcheck. This performs68    // `ObligationCtxt::normalize`, but provides a nice `ObligationCauseCode`.69    fn normalize<T>(70        &self,71        span: Span,72        loc: Option<WellFormedLoc>,73        value: Unnormalized<'tcx, T>,74    ) -> T75    where76        T: TypeFoldable<TyCtxt<'tcx>>,77    {78        self.ocx.normalize(79            &ObligationCause::new(span, self.body_def_id, ObligationCauseCode::WellFormed(loc)),80            self.param_env,81            value,82        )83    }8485    /// Convenience function to *deeply* normalize during wfcheck. In the old solver,86    /// this just dispatches to [`WfCheckingCtxt::normalize`], but in the new solver87    /// this calls `deeply_normalize` and reports errors if they are encountered.88    ///89    /// This function should be called in favor of `normalize` in cases where we will90    /// then check the well-formedness of the type, since we only use the normalized91    /// signature types for implied bounds when checking regions.92    // FIXME(-Znext-solver): This should be removed when we compute implied outlives93    // bounds using the unnormalized signature of the function we're checking.94    pub(super) fn deeply_normalize<T>(95        &self,96        span: Span,97        loc: Option<WellFormedLoc>,98        value: Unnormalized<'tcx, T>,99    ) -> T100    where101        T: TypeFoldable<TyCtxt<'tcx>>,102    {103        if self.infcx.next_trait_solver() {104            match self.ocx.deeply_normalize(105                &ObligationCause::new(span, self.body_def_id, ObligationCauseCode::WellFormed(loc)),106                self.param_env,107                value.clone(),108            ) {109                Ok(value) => value,110                Err(errors) => {111                    self.infcx.err_ctxt().report_fulfillment_errors(errors);112                    value.skip_norm_wip()113                }114            }115        } else {116            self.normalize(span, loc, value)117        }118    }119120    pub(super) fn register_wf_obligation(121        &self,122        span: Span,123        loc: Option<WellFormedLoc>,124        term: ty::Term<'tcx>,125    ) {126        let cause = traits::ObligationCause::new(127            span,128            self.body_def_id,129            ObligationCauseCode::WellFormed(loc),130        );131        self.ocx.register_obligation(Obligation::new(132            self.tcx(),133            cause,134            self.param_env,135            ty::ClauseKind::WellFormed(term),136        ));137    }138139    pub(super) fn unnormalized_obligations(140        &self,141        span: Span,142        ty: Ty<'tcx>,143    ) -> Option<PredicateObligations<'tcx>> {144        traits::wf::unnormalized_obligations(145            self.ocx.infcx,146            self.param_env,147            ty.into(),148            span,149            self.body_def_id,150        )151    }152}153154pub(super) fn enter_wf_checking_ctxt<'tcx, F>(155    tcx: TyCtxt<'tcx>,156    body_def_id: LocalDefId,157    f: F,158) -> Result<(), ErrorGuaranteed>159where160    F: for<'a> FnOnce(&WfCheckingCtxt<'a, 'tcx>) -> Result<(), ErrorGuaranteed>,161{162    let param_env = tcx.param_env(body_def_id);163    let infcx = &tcx.infer_ctxt().build(TypingMode::non_body_analysis());164    let ocx = ObligationCtxt::new_with_diagnostics(infcx);165166    let mut wfcx = WfCheckingCtxt { ocx, body_def_id, param_env };167168    // As of now, bounds are only checked on lazy type aliases, they're ignored for most type169    // aliases. So, only check for false global bounds if we're not ignoring bounds altogether.170    let ignore_bounds =171        tcx.def_kind(body_def_id) == DefKind::TyAlias && !tcx.type_alias_is_lazy(body_def_id);172173    if !ignore_bounds && !tcx.features().trivial_bounds() {174        wfcx.check_false_global_bounds()175    }176    f(&mut wfcx)?;177178    let errors = wfcx.evaluate_obligations_error_on_ambiguity();179    if !errors.is_empty() {180        return Err(infcx.err_ctxt().report_fulfillment_errors(errors));181    }182183    let assumed_wf_types = wfcx.ocx.assumed_wf_types_and_report_errors(param_env, body_def_id)?;184    debug!(?assumed_wf_types);185186    let infcx_compat = infcx.fork();187188    // We specifically want to *disable* the implied bounds hack, first,189    // so we can detect when failures are due to bevy's implied bounds.190    let outlives_env = OutlivesEnvironment::new_with_implied_bounds_compat(191        &infcx,192        body_def_id,193        param_env,194        assumed_wf_types.iter().copied(),195        true,196    );197198    lint_redundant_lifetimes(tcx, body_def_id, &outlives_env);199200    let errors = infcx.resolve_regions_with_outlives_env(&outlives_env, tcx.def_span(body_def_id));201    if errors.is_empty() {202        return Ok(());203    }204205    let outlives_env = OutlivesEnvironment::new_with_implied_bounds_compat(206        &infcx_compat,207        body_def_id,208        param_env,209        assumed_wf_types,210        // Don't *disable* the implied bounds hack; though this will only apply211        // the implied bounds hack if this contains `bevy_ecs`'s `ParamSet` type.212        false,213    );214    let errors_compat =215        infcx_compat.resolve_regions_with_outlives_env(&outlives_env, tcx.def_span(body_def_id));216    if errors_compat.is_empty() {217        // FIXME: Once we fix bevy, this would be the place to insert a warning218        // to upgrade bevy.219        Ok(())220    } else {221        Err(infcx_compat.err_ctxt().report_region_errors(body_def_id, &errors_compat))222    }223}224225pub(super) fn check_well_formed(226    tcx: TyCtxt<'_>,227    def_id: LocalDefId,228) -> Result<(), ErrorGuaranteed> {229    let mut res = crate::check::check::check_item_type(tcx, def_id);230231    for param in &tcx.generics_of(def_id).own_params {232        res = res.and(check_param_wf(tcx, param));233    }234235    res236}237238/// Checks that the field types (in a struct def'n) or argument types (in an enum def'n) are239/// well-formed, meaning that they do not require any constraints not declared in the struct240/// definition itself. For example, this definition would be illegal:241///242/// ```rust243/// struct StaticRef<T> { x: &'static T }244/// ```245///246/// because the type did not declare that `T: 'static`.247///248/// We do this check as a pre-pass before checking fn bodies because if these constraints are249/// not included it frequently leads to confusing errors in fn bodies. So it's better to check250/// the types first.251#[instrument(skip(tcx), level = "debug")]252pub(super) fn check_item<'tcx>(253    tcx: TyCtxt<'tcx>,254    item: &'tcx hir::Item<'tcx>,255) -> Result<(), ErrorGuaranteed> {256    let def_id = item.owner_id.def_id;257258    debug!(259        ?item.owner_id,260        item.name = ? tcx.def_path_str(def_id)261    );262263    match item.kind {264        // Right now we check that every default trait implementation265        // has an implementation of itself. Basically, a case like:266        //267        //     impl Trait for T {}268        //269        // has a requirement of `T: Trait` which was required for default270        // method implementations. Although this could be improved now that271        // there's a better infrastructure in place for this, it's being left272        // for a follow-up work.273        //274        // Since there's such a requirement, we need to check *just* positive275        // implementations, otherwise things like:276        //277        //     impl !Send for T {}278        //279        // won't be allowed unless there's an *explicit* implementation of `Send`280        // for `T`281        hir::ItemKind::Impl(ref impl_) => {282            crate::impl_wf_check::check_impl_wf(tcx, def_id, impl_.of_trait.is_some())?;283            let mut res = Ok(());284            if let Some(of_trait) = impl_.of_trait {285                let header = tcx.impl_trait_header(def_id);286                let is_auto = tcx.trait_is_auto(header.trait_ref.skip_binder().def_id);287                if let (hir::Defaultness::Default { .. }, true) = (of_trait.defaultness, is_auto) {288                    let sp = of_trait.trait_ref.path.span;289                    res = Err(tcx290                        .dcx()291                        .struct_span_err(sp, "impls of auto traits cannot be default")292                        .with_span_labels(of_trait.defaultness_span, "default because of this")293                        .with_span_label(sp, "auto trait")294                        .emit());295                }296                match header.polarity {297                    ty::ImplPolarity::Positive => {298                        res = res.and(check_impl(tcx, item, impl_));299                    }300                    ty::ImplPolarity::Negative => {301                        let ast::ImplPolarity::Negative(span) = of_trait.polarity else {302                            bug!("impl_polarity query disagrees with impl's polarity in HIR");303                        };304                        // FIXME(#27579): what amount of WF checking do we need for neg impls?305                        if let hir::Defaultness::Default { .. } = of_trait.defaultness {306                            let mut spans = vec![span];307                            spans.extend(of_trait.defaultness_span);308                            res = Err(struct_span_code_err!(309                                tcx.dcx(),310                                spans,311                                E0750,312                                "negative impls cannot be default impls"313                            )314                            .emit());315                        }316                    }317                    ty::ImplPolarity::Reservation => {318                        // FIXME: what amount of WF checking do we need for reservation impls?319                    }320                }321            } else {322                res = res.and(check_impl(tcx, item, impl_));323            }324            res325        }326        hir::ItemKind::Fn { sig, .. } => check_item_fn(tcx, def_id, sig.decl),327        // Note: do not add new entries to this match. Instead add all new logic in `check_item_type`328        _ => span_bug!(item.span, "should have been handled by the type based wf check: {item:?}"),329    }330}331332pub(super) fn check_foreign_item<'tcx>(333    tcx: TyCtxt<'tcx>,334    item: &'tcx hir::ForeignItem<'tcx>,335) -> Result<(), ErrorGuaranteed> {336    let def_id = item.owner_id.def_id;337338    debug!(339        ?item.owner_id,340        item.name = ? tcx.def_path_str(def_id)341    );342343    match item.kind {344        hir::ForeignItemKind::Fn(sig, ..) => check_item_fn(tcx, def_id, sig.decl),345        hir::ForeignItemKind::Static(..) | hir::ForeignItemKind::Type => Ok(()),346    }347}348349pub(crate) fn check_trait_item<'tcx>(350    tcx: TyCtxt<'tcx>,351    def_id: LocalDefId,352) -> Result<(), ErrorGuaranteed> {353    // Check that an item definition in a subtrait is shadowing a supertrait item.354    lint_item_shadowing_supertrait_item(tcx, def_id);355356    let mut res = Ok(());357358    if tcx.def_kind(def_id) == DefKind::AssocFn {359        for &assoc_ty_def_id in360            tcx.associated_types_for_impl_traits_in_associated_fn(def_id.to_def_id())361        {362            res = res.and(check_associated_item(tcx, assoc_ty_def_id.expect_local()));363        }364    }365    res366}367368/// Require that the user writes where clauses on GATs for the implicit369/// outlives bounds involving trait parameters in trait functions and370/// lifetimes passed as GAT args. See `self-outlives-lint` test.371///372/// We use the following trait as an example throughout this function:373/// ```rust,ignore (this code fails due to this lint)374/// trait IntoIter {375///     type Iter<'a>: Iterator<Item = Self::Item<'a>>;376///     type Item<'a>;377///     fn into_iter<'a>(&'a self) -> Self::Iter<'a>;378/// }379/// ```380pub(crate) fn check_gat_where_clauses(tcx: TyCtxt<'_>, trait_def_id: LocalDefId) {381    // Associates every GAT's def_id to a list of possibly missing bounds detected by this lint.382    let mut required_bounds_by_item = FxIndexMap::default();383    let associated_items = tcx.associated_items(trait_def_id);384385    // Loop over all GATs together, because if this lint suggests adding a where-clause bound386    // to one GAT, it might then require us to an additional bound on another GAT.387    // In our `IntoIter` example, we discover a missing `Self: 'a` bound on `Iter<'a>`, which388    // then in a second loop adds a `Self: 'a` bound to `Item` due to the relationship between389    // those GATs.390    loop {391        let mut should_continue = false;392        for gat_item in associated_items.in_definition_order() {393            let gat_def_id = gat_item.def_id.expect_local();394            let gat_item = tcx.associated_item(gat_def_id);395            // If this item is not an assoc ty, or has no args, then it's not a GAT396            if !gat_item.is_type() {397                continue;398            }399            let gat_generics = tcx.generics_of(gat_def_id);400            // FIXME(jackh726): we can also warn in the more general case401            if gat_generics.is_own_empty() {402                continue;403            }404405            // Gather the bounds with which all other items inside of this trait constrain the GAT.406            // This is calculated by taking the intersection of the bounds that each item407            // constrains the GAT with individually.408            let mut new_required_bounds: Option<FxIndexSet<ty::Clause<'_>>> = None;409            for item in associated_items.in_definition_order() {410                let item_def_id = item.def_id.expect_local();411                // Skip our own GAT, since it does not constrain itself at all.412                if item_def_id == gat_def_id {413                    continue;414                }415416                let param_env = tcx.param_env(item_def_id);417418                let item_required_bounds = match tcx.associated_item(item_def_id).kind {419                    // In our example, this corresponds to `into_iter` method420                    ty::AssocKind::Fn { .. } => {421                        // For methods, we check the function signature's return type for any GATs422                        // to constrain. In the `into_iter` case, we see that the return type423                        // `Self::Iter<'a>` is a GAT we want to gather any potential missing bounds from.424                        let sig: ty::FnSig<'_> = tcx.liberate_late_bound_regions(425                            item_def_id.to_def_id(),426                            tcx.fn_sig(item_def_id).instantiate_identity().skip_norm_wip(),427                        );428                        gather_gat_bounds(429                            tcx,430                            param_env,431                            item_def_id,432                            sig.inputs_and_output,433                            // We also assume that all of the function signature's parameter types434                            // are well formed.435                            &sig.inputs().iter().copied().collect(),436                            gat_def_id,437                            gat_generics,438                        )439                    }440                    // In our example, this corresponds to the `Iter` and `Item` associated types441                    ty::AssocKind::Type { .. } => {442                        // If our associated item is a GAT with missing bounds, add them to443                        // the param-env here. This allows this GAT to propagate missing bounds444                        // to other GATs.445                        let param_env = augment_param_env(446                            tcx,447                            param_env,448                            required_bounds_by_item.get(&item_def_id),449                        );450                        gather_gat_bounds(451                            tcx,452                            param_env,453                            item_def_id,454                            tcx.explicit_item_bounds(item_def_id)455                                .iter_identity_copied()456                                .map(Unnormalized::skip_norm_wip)457                                .collect::<Vec<_>>(),458                            &FxIndexSet::default(),459                            gat_def_id,460                            gat_generics,461                        )462                    }463                    ty::AssocKind::Const { .. } => None,464                };465466                if let Some(item_required_bounds) = item_required_bounds {467                    // Take the intersection of the required bounds for this GAT, and468                    // the item_required_bounds which are the ones implied by just469                    // this item alone.470                    // This is why we use an Option<_>, since we need to distinguish471                    // the empty set of bounds from the _uninitialized_ set of bounds.472                    if let Some(new_required_bounds) = &mut new_required_bounds {473                        new_required_bounds.retain(|b| item_required_bounds.contains(b));474                    } else {475                        new_required_bounds = Some(item_required_bounds);476                    }477                }478            }479480            if let Some(new_required_bounds) = new_required_bounds {481                let required_bounds = required_bounds_by_item.entry(gat_def_id).or_default();482                if new_required_bounds.into_iter().any(|p| required_bounds.insert(p)) {483                    // Iterate until our required_bounds no longer change484                    // Since they changed here, we should continue the loop485                    should_continue = true;486                }487            }488        }489        // We know that this loop will eventually halt, since we only set `should_continue` if the490        // `required_bounds` for this item grows. Since we are not creating any new region or type491        // variables, the set of all region and type bounds that we could ever insert are limited492        // by the number of unique types and regions we observe in a given item.493        if !should_continue {494            break;495        }496    }497498    for (gat_def_id, required_bounds) in required_bounds_by_item {499        // Don't suggest adding `Self: 'a` to a GAT that can't be named500        if tcx.is_impl_trait_in_trait(gat_def_id.to_def_id()) {501            continue;502        }503504        let gat_item_hir = tcx.hir_expect_trait_item(gat_def_id);505        debug!(?required_bounds);506        let param_env = tcx.param_env(gat_def_id);507508        let unsatisfied_bounds: Vec<_> = required_bounds509            .into_iter()510            .filter(|clause| match clause.kind().skip_binder() {511                ty::ClauseKind::RegionOutlives(ty::OutlivesPredicate(a, b)) => {512                    !region_known_to_outlive(513                        tcx,514                        gat_def_id,515                        param_env,516                        &FxIndexSet::default(),517                        a,518                        b,519                    )520                }521                ty::ClauseKind::TypeOutlives(ty::OutlivesPredicate(a, b)) => {522                    !ty_known_to_outlive(tcx, gat_def_id, param_env, &FxIndexSet::default(), a, b)523                }524                _ => bug!("Unexpected ClauseKind"),525            })526            .map(|clause| clause.to_string())527            .collect();528529        if !unsatisfied_bounds.is_empty() {530            let plural = pluralize!(unsatisfied_bounds.len());531            let suggestion = format!(532                "{} {}",533                gat_item_hir.generics.add_where_or_trailing_comma(),534                unsatisfied_bounds.join(", "),535            );536            let bound =537                if unsatisfied_bounds.len() > 1 { "these bounds are" } else { "this bound is" };538            tcx.dcx()539                .struct_span_err(540                    gat_item_hir.span,541                    format!("missing required bound{} on `{}`", plural, gat_item_hir.ident),542                )543                .with_span_suggestion(544                    gat_item_hir.generics.tail_span_for_predicate_suggestion(),545                    format!("add the required where clause{plural}"),546                    suggestion,547                    Applicability::MachineApplicable,548                )549                .with_note(format!(550                    "{bound} currently required to ensure that impls have maximum flexibility"551                ))552                .with_note(553                    "we are soliciting feedback, see issue #87479 \554                     <https://github.com/rust-lang/rust/issues/87479> for more information",555                )556                .emit();557        }558    }559}560561/// Add a new set of predicates to the caller_bounds of an existing param_env.562fn augment_param_env<'tcx>(563    tcx: TyCtxt<'tcx>,564    param_env: ty::ParamEnv<'tcx>,565    new_predicates: Option<&FxIndexSet<ty::Clause<'tcx>>>,566) -> ty::ParamEnv<'tcx> {567    let Some(new_predicates) = new_predicates else {568        return param_env;569    };570571    if new_predicates.is_empty() {572        return param_env;573    }574575    let bounds = tcx.mk_clauses_from_iter(576        param_env.caller_bounds().iter().chain(new_predicates.iter().cloned()),577    );578    // FIXME(compiler-errors): Perhaps there is a case where we need to normalize this579    // i.e. traits::normalize_param_env_or_error580    ty::ParamEnv::new(bounds)581}582583/// We use the following trait as an example throughout this function.584/// Specifically, let's assume that `to_check` here is the return type585/// of `into_iter`, and the GAT we are checking this for is `Iter`.586/// ```rust,ignore (this code fails due to this lint)587/// trait IntoIter {588///     type Iter<'a>: Iterator<Item = Self::Item<'a>>;589///     type Item<'a>;590///     fn into_iter<'a>(&'a self) -> Self::Iter<'a>;591/// }592/// ```593fn gather_gat_bounds<'tcx, T: TypeFoldable<TyCtxt<'tcx>>>(594    tcx: TyCtxt<'tcx>,595    param_env: ty::ParamEnv<'tcx>,596    item_def_id: LocalDefId,597    to_check: T,598    wf_tys: &FxIndexSet<Ty<'tcx>>,599    gat_def_id: LocalDefId,600    gat_generics: &'tcx ty::Generics,601) -> Option<FxIndexSet<ty::Clause<'tcx>>> {602    // The bounds we that we would require from `to_check`603    let mut bounds = FxIndexSet::default();604605    let (regions, types) = GATArgsCollector::visit(gat_def_id.to_def_id(), to_check);606607    // If both regions and types are empty, then this GAT isn't in the608    // set of types we are checking, and we shouldn't try to do clause analysis609    // (particularly, doing so would end up with an empty set of clauses,610    // since the current method would require none, and we take the611    // intersection of requirements of all methods)612    if types.is_empty() && regions.is_empty() {613        return None;614    }615616    for (region_a, region_a_idx) in &regions {617        // Ignore `'static` lifetimes for the purpose of this lint: it's618        // because we know it outlives everything and so doesn't give meaningful619        // clues. Also ignore `ReError`, to avoid knock-down errors.620        if let ty::ReStatic | ty::ReError(_) = region_a.kind() {621            continue;622        }623        // For each region argument (e.g., `'a` in our example), check for a624        // relationship to the type arguments (e.g., `Self`). If there is an625        // outlives relationship (`Self: 'a`), then we want to ensure that is626        // reflected in a where clause on the GAT itself.627        for (ty, ty_idx) in &types {628            // In our example, requires that `Self: 'a`629            if ty_known_to_outlive(tcx, item_def_id, param_env, wf_tys, *ty, *region_a) {630                debug!(?ty_idx, ?region_a_idx);631                debug!("required clause: {ty} must outlive {region_a}");632                // Translate into the generic parameters of the GAT. In633                // our example, the type was `Self`, which will also be634                // `Self` in the GAT.635                let ty_param = gat_generics.param_at(*ty_idx, tcx);636                let ty_param = Ty::new_param(tcx, ty_param.index, ty_param.name);637                // Same for the region. In our example, 'a corresponds638                // to the 'me parameter.639                let region_param = gat_generics.param_at(*region_a_idx, tcx);640                let region_param = ty::Region::new_early_param(641                    tcx,642                    ty::EarlyParamRegion { index: region_param.index, name: region_param.name },643                );644                // The predicate we expect to see. (In our example,645                // `Self: 'me`.)646                bounds.insert(647                    ty::ClauseKind::TypeOutlives(ty::OutlivesPredicate(ty_param, region_param))648                        .upcast(tcx),649                );650            }651        }652653        // For each region argument (e.g., `'a` in our example), also check for a654        // relationship to the other region arguments. If there is an outlives655        // relationship, then we want to ensure that is reflected in the where clause656        // on the GAT itself.657        for (region_b, region_b_idx) in &regions {658            // Again, skip `'static` because it outlives everything. Also, we trivially659            // know that a region outlives itself. Also ignore `ReError`, to avoid660            // knock-down errors.661            if matches!(region_b.kind(), ty::ReStatic | ty::ReError(_)) || region_a == region_b {662                continue;663            }664            if region_known_to_outlive(tcx, item_def_id, param_env, wf_tys, *region_a, *region_b) {665                debug!(?region_a_idx, ?region_b_idx);666                debug!("required clause: {region_a} must outlive {region_b}");667                // Translate into the generic parameters of the GAT.668                let region_a_param = gat_generics.param_at(*region_a_idx, tcx);669                let region_a_param = ty::Region::new_early_param(670                    tcx,671                    ty::EarlyParamRegion { index: region_a_param.index, name: region_a_param.name },672                );673                // Same for the region.674                let region_b_param = gat_generics.param_at(*region_b_idx, tcx);675                let region_b_param = ty::Region::new_early_param(676                    tcx,677                    ty::EarlyParamRegion { index: region_b_param.index, name: region_b_param.name },678                );679                // The predicate we expect to see.680                bounds.insert(681                    ty::ClauseKind::RegionOutlives(ty::OutlivesPredicate(682                        region_a_param,683                        region_b_param,684                    ))685                    .upcast(tcx),686                );687            }688        }689    }690691    Some(bounds)692}693694/// Given a known `param_env` and a set of well formed types, can we prove that695/// `ty` outlives `region`.696fn ty_known_to_outlive<'tcx>(697    tcx: TyCtxt<'tcx>,698    id: LocalDefId,699    param_env: ty::ParamEnv<'tcx>,700    wf_tys: &FxIndexSet<Ty<'tcx>>,701    ty: Ty<'tcx>,702    region: ty::Region<'tcx>,703) -> bool {704    test_region_obligations(tcx, id, param_env, wf_tys, |infcx| {705        infcx.register_type_outlives_constraint_inner(infer::TypeOutlivesConstraint {706            sub_region: region,707            sup_type: ty,708            origin: SubregionOrigin::RelateParamBound(DUMMY_SP, ty, None),709        });710    })711}712713/// Given a known `param_env` and a set of well formed types, can we prove that714/// `region_a` outlives `region_b`715fn region_known_to_outlive<'tcx>(716    tcx: TyCtxt<'tcx>,717    id: LocalDefId,718    param_env: ty::ParamEnv<'tcx>,719    wf_tys: &FxIndexSet<Ty<'tcx>>,720    region_a: ty::Region<'tcx>,721    region_b: ty::Region<'tcx>,722) -> bool {723    test_region_obligations(tcx, id, param_env, wf_tys, |infcx| {724        infcx.sub_regions(725            SubregionOrigin::RelateRegionParamBound(DUMMY_SP, None),726            region_b,727            region_a,728            ty::VisibleForLeakCheck::Unreachable,729        );730    })731}732733/// Given a known `param_env` and a set of well formed types, set up an734/// `InferCtxt`, call the passed function (to e.g. set up region constraints735/// to be tested), then resolve region and return errors736fn test_region_obligations<'tcx>(737    tcx: TyCtxt<'tcx>,738    id: LocalDefId,739    param_env: ty::ParamEnv<'tcx>,740    wf_tys: &FxIndexSet<Ty<'tcx>>,741    add_constraints: impl FnOnce(&InferCtxt<'tcx>),742) -> bool {743    // Unfortunately, we have to use a new `InferCtxt` each call, because744    // region constraints get added and solved there and we need to test each745    // call individually.746    let infcx = tcx.infer_ctxt().build(TypingMode::non_body_analysis());747748    add_constraints(&infcx);749750    let errors = infcx.resolve_regions(id, param_env, wf_tys.iter().copied());751    debug!(?errors, "errors");752753    // If we were able to prove that the type outlives the region without754    // an error, it must be because of the implied or explicit bounds...755    errors.is_empty()756}757758/// TypeVisitor that looks for uses of GATs like759/// `<P0 as Trait<P1..Pn>>::GAT<Pn..Pm>` and adds the arguments `P0..Pm` into760/// the two vectors, `regions` and `types` (depending on their kind). For each761/// parameter `Pi` also track the index `i`.762struct GATArgsCollector<'tcx> {763    gat: DefId,764    // Which region appears and which parameter index its instantiated with765    regions: FxIndexSet<(ty::Region<'tcx>, usize)>,766    // Which params appears and which parameter index its instantiated with767    types: FxIndexSet<(Ty<'tcx>, usize)>,768}769770impl<'tcx> GATArgsCollector<'tcx> {771    fn visit<T: TypeFoldable<TyCtxt<'tcx>>>(772        gat: DefId,773        t: T,774    ) -> (FxIndexSet<(ty::Region<'tcx>, usize)>, FxIndexSet<(Ty<'tcx>, usize)>) {775        let mut visitor =776            GATArgsCollector { gat, regions: FxIndexSet::default(), types: FxIndexSet::default() };777        t.visit_with(&mut visitor);778        (visitor.regions, visitor.types)779    }780}781782impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for GATArgsCollector<'tcx> {783    fn visit_ty(&mut self, t: Ty<'tcx>) {784        match t.kind() {785            &ty::Alias(ty::AliasTy { kind: ty::Projection { def_id }, args, .. })786                if def_id == self.gat =>787            {788                for (idx, arg) in args.iter().enumerate() {789                    match arg.kind() {790                        GenericArgKind::Lifetime(lt) if !lt.is_bound() => {791                            self.regions.insert((lt, idx));792                        }793                        GenericArgKind::Type(t) => {794                            self.types.insert((t, idx));795                        }796                        _ => {}797                    }798                }799            }800            _ => {}801        }802        t.super_visit_with(self)803    }804}805806fn lint_item_shadowing_supertrait_item<'tcx>(tcx: TyCtxt<'tcx>, trait_item_def_id: LocalDefId) {807    let item_name = tcx.item_name(trait_item_def_id.to_def_id());808    let trait_def_id = tcx.local_parent(trait_item_def_id);809810    let shadowed: Vec<_> = traits::supertrait_def_ids(tcx, trait_def_id.to_def_id())811        .skip(1)812        .flat_map(|supertrait_def_id| {813            tcx.associated_items(supertrait_def_id).filter_by_name_unhygienic(item_name)814        })815        .collect();816    if !shadowed.is_empty() {817        let shadowee = if let [shadowed] = shadowed[..] {818            diagnostics::SupertraitItemShadowee::Labeled {819                span: tcx.def_span(shadowed.def_id),820                supertrait: tcx.item_name(shadowed.trait_container(tcx).unwrap()),821            }822        } else {823            let (traits, spans): (Vec<_>, Vec<_>) = shadowed824                .iter()825                .map(|item| {826                    (tcx.item_name(item.trait_container(tcx).unwrap()), tcx.def_span(item.def_id))827                })828                .unzip();829            diagnostics::SupertraitItemShadowee::Several {830                traits: traits.into(),831                spans: spans.into(),832            }833        };834835        tcx.emit_node_span_lint(836            SHADOWING_SUPERTRAIT_ITEMS,837            tcx.local_def_id_to_hir_id(trait_item_def_id),838            tcx.def_span(trait_item_def_id),839            diagnostics::SupertraitItemShadowing {840                item: item_name,841                subtrait: tcx.item_name(trait_def_id.to_def_id()),842                shadowee,843            },844        );845    }846}847848fn check_param_wf(tcx: TyCtxt<'_>, param: &ty::GenericParamDef) -> Result<(), ErrorGuaranteed> {849    match param.kind {850        // We currently only check wf of const params here.851        ty::GenericParamDefKind::Lifetime | ty::GenericParamDefKind::Type { .. } => Ok(()),852853        // Const parameters are well formed if their type is structural match.854        ty::GenericParamDefKind::Const { .. } => {855            let ty = tcx.type_of(param.def_id).instantiate_identity().skip_norm_wip();856            let span = tcx.def_span(param.def_id);857            let def_id = param.def_id.expect_local();858859            if tcx.features().const_param_ty_unchecked() {860                enter_wf_checking_ctxt(tcx, tcx.local_parent(def_id), |wfcx| {861                    wfcx.register_wf_obligation(span, None, ty.into());862                    Ok(())863                })864            } else if tcx.features().adt_const_params() || tcx.features().min_adt_const_params() {865                enter_wf_checking_ctxt(tcx, tcx.local_parent(def_id), |wfcx| {866                    wfcx.register_bound(867                        ObligationCause::new(span, def_id, ObligationCauseCode::ConstParam(ty)),868                        wfcx.param_env,869                        ty,870                        tcx.require_lang_item(LangItem::ConstParamTy, span),871                    );872                    Ok(())873                })874            } else {875                let span = || {876                    let hir::GenericParamKind::Const { ty: &hir::Ty { span, .. }, .. } =877                        tcx.hir_node_by_def_id(def_id).expect_generic_param().kind878                    else {879                        bug!()880                    };881                    span882                };883                let mut diag = match ty.kind() {884                    ty::Bool | ty::Char | ty::Int(_) | ty::Uint(_) | ty::Error(_) => return Ok(()),885                    ty::FnPtr(..) => tcx.dcx().struct_span_err(886                        span(),887                        "using function pointers as const generic parameters is forbidden",888                    ),889                    ty::RawPtr(_, _) => tcx.dcx().struct_span_err(890                        span(),891                        "using raw pointers as const generic parameters is forbidden",892                    ),893                    _ => {894                        // Avoid showing "{type error}" to users. See #118179.895                        ty.error_reported()?;896897                        tcx.dcx().struct_span_err(898                            span(),899                            format!(900                                "`{ty}` is forbidden as the type of a const generic parameter",901                            ),902                        )903                    }904                };905906                diag.note("the only supported types are integers, `bool`, and `char`");907908                let cause = ObligationCause::misc(span(), def_id);909                let adt_const_params_feature_string =910                    " more complex and user defined types".to_string();911                let may_suggest_feature = match type_allowed_to_implement_const_param_ty(912                    tcx,913                    tcx.param_env(param.def_id),914                    ty,915                    cause,916                ) {917                    // Can never implement `ConstParamTy`, don't suggest anything.918                    Err(919                        ConstParamTyImplementationError::NotAnAdtOrBuiltinAllowed920                        | ConstParamTyImplementationError::NonExhaustive(..)921                        | ConstParamTyImplementationError::InvalidInnerTyOfBuiltinTy(..),922                    ) => None,923                    Err(ConstParamTyImplementationError::UnsizedConstParamsFeatureRequired) => {924                        Some(vec![925                            (adt_const_params_feature_string, sym::min_adt_const_params),926                            (927                                " references to implement the `ConstParamTy` trait".into(),928                                sym::unsized_const_params,929                            ),930                        ])931                    }932                    // May be able to implement `ConstParamTy`. Only emit the feature help933                    // if the type is local, since the user may be able to fix the local type.934                    Err(ConstParamTyImplementationError::InfrigingFields(..)) => {935                        fn ty_is_local(ty: Ty<'_>) -> bool {936                            match ty.kind() {937                                ty::Adt(adt_def, ..) => adt_def.did().is_local(),938                                // Arrays and slices use the inner type's `ConstParamTy`.939                                ty::Array(ty, ..) | ty::Slice(ty) => ty_is_local(*ty),940                                // `&` references use the inner type's `ConstParamTy`.941                                // `&mut` are not supported.942                                ty::Ref(_, ty, ast::Mutability::Not) => ty_is_local(*ty),943                                // Say that a tuple is local if any of its components are local.944                                // This is not strictly correct, but it's likely that the user can fix the local component.945                                ty::Tuple(tys) => tys.iter().any(|ty| ty_is_local(ty)),946                                _ => false,947                            }948                        }949950                        ty_is_local(ty).then_some(vec![(951                            adt_const_params_feature_string,952                            sym::min_adt_const_params,953                        )])954                    }955                    // Implements `ConstParamTy`, suggest adding the feature to enable.956                    Ok(..) => {957                        Some(vec![(adt_const_params_feature_string, sym::min_adt_const_params)])958                    }959                };960                if let Some(features) = may_suggest_feature {961                    tcx.disabled_nightly_features(&mut diag, features);962                }963964                Err(diag.emit())965            }966        }967    }968}969970#[instrument(level = "debug", skip(tcx))]971pub(crate) fn check_associated_item(972    tcx: TyCtxt<'_>,973    def_id: LocalDefId,974) -> Result<(), ErrorGuaranteed> {975    let loc = Some(WellFormedLoc::Ty(def_id));976    enter_wf_checking_ctxt(tcx, def_id, |wfcx| {977        let item = tcx.associated_item(def_id);978979        // Avoid bogus "type annotations needed `Foo: Bar`" errors on `impl Bar for Foo` in case980        // other `Foo` impls are incoherent.981        tcx.ensure_result().coherent_trait(tcx.parent(item.trait_item_or_self()?))?;982983        let self_ty = match item.container {984            ty::AssocContainer::Trait => tcx.types.self_param,985            ty::AssocContainer::InherentImpl | ty::AssocContainer::TraitImpl(_) => {986                tcx.type_of(item.container_id(tcx)).instantiate_identity().skip_norm_wip()987            }988        };989990        let span = tcx.def_span(def_id);991992        match item.kind {993            ty::AssocKind::Const { .. } => {994                let ty = tcx.type_of(def_id).instantiate_identity();995                let ty = wfcx.deeply_normalize(span, Some(WellFormedLoc::Ty(def_id)), ty);996                wfcx.register_wf_obligation(span, loc, ty.into());997998                let has_value = item.defaultness(tcx).has_value();999                if tcx.is_type_const(def_id) {1000                    check_type_const(wfcx, def_id, ty, has_value)?;1001                }10021003                if has_value {1004                    let code = ObligationCauseCode::SizedConstOrStatic;1005                    wfcx.register_bound(1006                        ObligationCause::new(span, def_id, code),1007                        wfcx.param_env,1008                        ty,1009                        tcx.require_lang_item(LangItem::Sized, span),1010                    );1011                }10121013                Ok(())1014            }1015            ty::AssocKind::Fn { .. } => {1016                let sig = tcx.fn_sig(def_id).instantiate_identity().skip_norm_wip();1017                let hir_sig =1018                    tcx.hir_node_by_def_id(def_id).fn_sig().expect("bad signature for method");1019                check_fn_or_method(wfcx, sig, hir_sig.decl, def_id);1020                check_method_receiver(wfcx, hir_sig, item, self_ty)1021            }1022            ty::AssocKind::Type { .. } => {1023                if let ty::AssocContainer::Trait = item.container {1024                    check_associated_type_bounds(wfcx, item, span)1025                }1026                if item.defaultness(tcx).has_value() {1027                    let ty = tcx.type_of(def_id).instantiate_identity();1028                    let ty = wfcx.deeply_normalize(span, Some(WellFormedLoc::Ty(def_id)), ty);1029                    wfcx.register_wf_obligation(span, loc, ty.into());1030                }1031                Ok(())1032            }1033        }1034    })1035}10361037/// In a type definition, we check that to ensure that the types of the fields are well-formed.1038pub(crate) fn check_type_defn<'tcx>(1039    tcx: TyCtxt<'tcx>,1040    item: LocalDefId,1041    all_sized: bool,1042) -> Result<(), ErrorGuaranteed> {1043    tcx.ensure_ok().check_representability(item);1044    let adt_def = tcx.adt_def(item);10451046    enter_wf_checking_ctxt(tcx, item, |wfcx| {1047        let variants = adt_def.variants();1048        let packed = adt_def.repr().packed();10491050        for variant in variants.iter() {1051            // All field types must be well-formed.1052            for field in &variant.fields {1053                if let Some(def_id) = field.value1054                    && let Some(_ty) = tcx.type_of(def_id).no_bound_vars()1055                {1056                    // FIXME(generic_const_exprs, default_field_values): this is a hack and needs to1057                    // be refactored to check the instantiate-ability of the code better.1058                    if let Some(def_id) = def_id.as_local()1059                        && let DefKind::AnonConst = tcx.def_kind(def_id)1060                        && let hir::Node::AnonConst(anon) = tcx.hir_node_by_def_id(def_id)1061                        && let expr = &tcx.hir_body(anon.body).value1062                        && let hir::ExprKind::Path(hir::QPath::Resolved(None, path)) = expr.kind1063                        && let Res::Def(DefKind::ConstParam, _def_id) = path.res1064                    {1065                        // Do not evaluate bare `const` params, as those would ICE and are only1066                        // usable if `#![feature(generic_const_exprs)]` is enabled.1067                    } else {1068                        // Evaluate the constant proactively, to emit an error if the constant has1069                        // an unconditional error. We only do so if the const has no type params.1070                        let _ = tcx.const_eval_poly(def_id);1071                    }1072                }1073                let field_id = field.did.expect_local();1074                let span = tcx.ty_span(field_id);1075                let ty = wfcx.deeply_normalize(1076                    span,1077                    None,1078                    tcx.type_of(field.did).instantiate_identity(),1079                );1080                wfcx.register_wf_obligation(span, Some(WellFormedLoc::Ty(field_id)), ty.into());10811082                if matches!(ty.kind(), ty::Adt(def, _) if def.repr().scalable())1083                    && !matches!(adt_def.repr().scalable, Some(ScalableElt::Container))1084                {1085                    // Scalable vectors can only be fields of structs if the type has a1086                    // `rustc_scalable_vector` attribute w/out specifying an element count1087                    tcx.dcx().span_err(1088                        span,1089                        format!(1090                            "scalable vectors cannot be fields of a {}",1091                            adt_def.variant_descr()1092                        ),1093                    );1094                }1095            }10961097            // For DST, or when drop needs to copy things around, all1098            // intermediate types must be sized.1099            let needs_drop_copy = || {1100                packed && {1101                    let ty = tcx.type_of(variant.tail().did).instantiate_identity().skip_norm_wip();1102                    let ty = tcx.erase_and_anonymize_regions(ty);1103                    assert!(!ty.has_infer());1104                    ty.needs_drop(tcx, wfcx.infcx.typing_env(wfcx.param_env))1105                }1106            };1107            // All fields (except for possibly the last) should be sized.1108            let all_sized = all_sized || variant.fields.is_empty() || needs_drop_copy();1109            let unsized_len = if all_sized { 0 } else { 1 };1110            for (idx, field) in1111                variant.fields.raw[..variant.fields.len() - unsized_len].iter().enumerate()1112            {1113                let last = idx == variant.fields.len() - 1;1114                let span = tcx.ty_span(field.did.expect_local());1115                let ty = wfcx.normalize(span, None, tcx.type_of(field.did).instantiate_identity());1116                wfcx.register_bound(1117                    traits::ObligationCause::new(1118                        span,1119                        wfcx.body_def_id,1120                        ObligationCauseCode::FieldSized {1121                            adt_kind: adt_def.adt_kind(),1122                            span,1123                            last,1124                        },1125                    ),1126                    wfcx.param_env,1127                    ty,1128                    tcx.require_lang_item(LangItem::Sized, span),1129                );1130            }11311132            // Explicit `enum` discriminant values must const-evaluate successfully.1133            if let ty::VariantDiscr::Explicit(discr_def_id) = variant.discr {1134                match tcx.const_eval_poly(discr_def_id) {1135                    Ok(_) => {}1136                    Err(ErrorHandled::Reported(..)) => {}1137                    Err(ErrorHandled::TooGeneric(sp)) => {1138                        span_bug!(sp, "enum variant discr was too generic to eval")1139                    }1140                }1141            }1142        }11431144        check_where_clauses(wfcx, item);1145        Ok(())1146    })1147}11481149#[instrument(skip(tcx))]1150pub(crate) fn check_trait(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Result<(), ErrorGuaranteed> {1151    if tcx.is_lang_item(def_id.into(), LangItem::PointeeSized) {1152        // `PointeeSized` is removed during lowering.1153        return Ok(());1154    }11551156    let trait_def = tcx.trait_def(def_id);1157    if trait_def.is_marker1158        || matches!(trait_def.specialization_kind, TraitSpecializationKind::Marker)1159    {1160        for associated_def_id in &*tcx.associated_item_def_ids(def_id) {1161            struct_span_code_err!(1162                tcx.dcx(),1163                tcx.def_span(*associated_def_id),1164                E0714,1165                "marker traits cannot have associated items",1166            )1167            .emit();1168        }1169    }11701171    let res = enter_wf_checking_ctxt(tcx, def_id, |wfcx| {1172        check_where_clauses(wfcx, def_id);1173        Ok(())1174    });11751176    res1177}11781179/// Checks all associated type defaults of trait `trait_def_id`.1180///1181/// Assuming the defaults are used, check that all predicates (bounds on the1182/// assoc type and where clauses on the trait) hold.1183fn check_associated_type_bounds(wfcx: &WfCheckingCtxt<'_, '_>, item: ty::AssocItem, _span: Span) {1184    let bounds = wfcx.tcx().explicit_item_bounds(item.def_id);11851186    debug!("check_associated_type_bounds: bounds={:?}", bounds);1187    let wf_obligations = bounds.iter_identity_copied().map(Unnormalized::skip_norm_wip).flat_map(1188        |(bound, bound_span)| {1189            traits::wf::clause_obligations(1190                wfcx.infcx,1191                wfcx.param_env,1192                wfcx.body_def_id,1193                bound,1194                bound_span,1195            )1196        },1197    );11981199    wfcx.register_obligations(wf_obligations);1200}12011202fn check_item_fn(1203    tcx: TyCtxt<'_>,1204    def_id: LocalDefId,1205    decl: &hir::FnDecl<'_>,1206) -> Result<(), ErrorGuaranteed> {1207    enter_wf_checking_ctxt(tcx, def_id, |wfcx| {1208        check_eiis_fn(tcx, def_id);12091210        let sig = tcx.fn_sig(def_id).instantiate_identity().skip_norm_wip();1211        check_fn_or_method(wfcx, sig, decl, def_id);1212        Ok(())1213    })1214}12151216fn check_eiis_fn(tcx: TyCtxt<'_>, def_id: LocalDefId) {1217    // does the function have an EiiImpl attribute? that contains the defid of a *macro*1218    // that was used to mark the implementation. This is a two step process.1219    for EiiImpl { resolution, span, .. } in1220        find_attr!(tcx, def_id, EiiImpls(impls) => impls).into_iter().flatten()1221    {1222        let (foreign_item, name) = match resolution {1223            EiiImplResolution::Macro(def_id) => {1224                // we expect this macro to have the `EiiMacroFor` attribute, that points to a function1225                // signature that we'd like to compare the function we're currently checking with1226                if let Some(foreign_item) =1227                    find_attr!(tcx, *def_id, EiiDeclaration(EiiDecl {foreign_item: t, ..}) => *t)1228                {1229                    (foreign_item, tcx.item_name(*def_id))1230                } else {1231                    tcx.dcx().span_delayed_bug(*span, "resolved to something that's not an EII");1232                    continue;1233                }1234            }1235            EiiImplResolution::Known(decl) => (decl.foreign_item, decl.name.name),1236            EiiImplResolution::Error(_eg) => continue,1237        };12381239        let _ = compare_eii_function_types(tcx, def_id, foreign_item, name, *span);1240    }1241}12421243fn check_eiis_static<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId, ty: Ty<'tcx>) {1244    // does the function have an EiiImpl attribute? that contains the defid of a *macro*1245    // that was used to mark the implementation. This is a two step process.1246    for EiiImpl { resolution, span, .. } in1247        find_attr!(tcx, def_id, EiiImpls(impls) => impls).into_iter().flatten()1248    {1249        let (foreign_item, name) = match resolution {1250            EiiImplResolution::Macro(def_id) => {1251                // we expect this macro to have the `EiiMacroFor` attribute, that points to a function1252                // signature that we'd like to compare the function we're currently checking with1253                if let Some(foreign_item) =1254                    find_attr!(tcx, *def_id, EiiDeclaration(EiiDecl {foreign_item: t, ..}) => *t)1255                {1256                    (foreign_item, tcx.item_name(*def_id))1257                } else {1258                    tcx.dcx().span_delayed_bug(*span, "resolved to something that's not an EII");1259                    continue;1260                }1261            }1262            EiiImplResolution::Known(decl) => (decl.foreign_item, decl.name.name),1263            EiiImplResolution::Error(_eg) => continue,1264        };12651266        let _ = compare_eii_statics(tcx, def_id, ty, foreign_item, name, *span);1267    }1268}12691270#[instrument(level = "debug", skip(tcx))]1271pub(crate) fn check_static_item<'tcx>(1272    tcx: TyCtxt<'tcx>,1273    item_id: LocalDefId,1274    ty: Ty<'tcx>,1275    should_check_for_sync: bool,1276) -> Result<(), ErrorGuaranteed> {1277    enter_wf_checking_ctxt(tcx, item_id, |wfcx| {1278        if should_check_for_sync {1279            check_eiis_static(tcx, item_id, ty);1280        }12811282        let span = tcx.ty_span(item_id);1283        let loc = Some(WellFormedLoc::Ty(item_id));1284        let item_ty = wfcx.deeply_normalize(span, loc, Unnormalized::new_wip(ty));12851286        let is_foreign_item = tcx.is_foreign_item(item_id);1287        let is_structurally_foreign_item = || {1288            let tail = tcx.struct_tail_raw(1289                item_ty,1290                &ObligationCause::dummy(),1291                |ty| wfcx.deeply_normalize(span, loc, ty),1292                || {},1293            );12941295            matches!(tail.kind(), ty::Foreign(_))1296        };1297        let forbid_unsized = !(is_foreign_item && is_structurally_foreign_item());12981299        wfcx.register_wf_obligation(span, Some(WellFormedLoc::Ty(item_id)), item_ty.into());1300        if forbid_unsized {1301            let span = tcx.def_span(item_id);1302            wfcx.register_bound(1303                traits::ObligationCause::new(1304                    span,1305                    wfcx.body_def_id,1306                    ObligationCauseCode::SizedConstOrStatic,1307                ),1308                wfcx.param_env,1309                item_ty,1310                tcx.require_lang_item(LangItem::Sized, span),1311            );1312        }13131314        // Ensure that the end result is `Sync` in a non-thread local `static`.1315        let should_check_for_sync = should_check_for_sync1316            && !is_foreign_item1317            && tcx.static_mutability(item_id.to_def_id()) == Some(hir::Mutability::Not)1318            && !tcx.is_thread_local_static(item_id.to_def_id());13191320        if should_check_for_sync {1321            wfcx.register_bound(1322                traits::ObligationCause::new(1323                    span,1324                    wfcx.body_def_id,1325                    ObligationCauseCode::SharedStatic,1326                ),1327                wfcx.param_env,1328                item_ty,1329                tcx.require_lang_item(LangItem::Sync, span),1330            );1331        }1332        Ok(())1333    })1334}13351336#[instrument(level = "debug", skip(wfcx))]1337pub(super) fn check_type_const<'tcx>(1338    wfcx: &WfCheckingCtxt<'_, 'tcx>,1339    def_id: LocalDefId,1340    item_ty: Ty<'tcx>,1341    has_value: bool,1342) -> Result<(), ErrorGuaranteed> {1343    let tcx = wfcx.tcx();1344    let span = tcx.def_span(def_id);13451346    if !tcx.features().const_param_ty_unchecked() {1347        wfcx.register_bound(1348            ObligationCause::new(span, def_id, ObligationCauseCode::ConstParam(item_ty)),1349            wfcx.param_env,1350            item_ty,1351            tcx.require_lang_item(LangItem::ConstParamTy, span),1352        );1353    }13541355    if has_value {1356        let raw_ct = tcx.const_of_item(def_id).instantiate_identity();1357        let norm_ct = wfcx.deeply_normalize(span, Some(WellFormedLoc::Ty(def_id)), raw_ct);1358        wfcx.register_wf_obligation(span, Some(WellFormedLoc::Ty(def_id)), norm_ct.into());13591360        wfcx.register_obligation(Obligation::new(1361            tcx,1362            ObligationCause::new(span, def_id, ObligationCauseCode::WellFormed(None)),1363            wfcx.param_env,1364            ty::PredicateKind::Clause(ty::ClauseKind::ConstArgHasType(norm_ct, item_ty)),1365        ));1366    }1367    Ok(())1368}13691370#[instrument(level = "debug", skip(tcx, impl_))]1371fn check_impl<'tcx>(1372    tcx: TyCtxt<'tcx>,1373    item: &'tcx hir::Item<'tcx>,1374    impl_: &hir::Impl<'_>,1375) -> Result<(), ErrorGuaranteed> {1376    enter_wf_checking_ctxt(tcx, item.owner_id.def_id, |wfcx| {1377        match impl_.of_trait {1378            Some(of_trait) => {1379                // `#[rustc_reservation_impl]` impls are not real impls and1380                // therefore don't need to be WF (the trait's `Self: Trait` predicate1381                // won't hold).1382                let trait_ref = tcx.impl_trait_ref(item.owner_id).instantiate_identity();1383                // Avoid bogus "type annotations needed `Foo: Bar`" errors on `impl Bar for Foo` in1384                // case other `Foo` impls are incoherent.1385                tcx.ensure_result().coherent_trait(trait_ref.skip_normalization().def_id)?;1386                let trait_span = of_trait.trait_ref.path.span;1387                let trait_ref = wfcx.deeply_normalize(1388                    trait_span,1389                    Some(WellFormedLoc::Ty(item.hir_id().expect_owner().def_id)),1390                    trait_ref,1391                );1392                let trait_pred =1393                    ty::TraitPredicate { trait_ref, polarity: ty::PredicatePolarity::Positive };1394                let mut obligations = traits::wf::trait_obligations(1395                    wfcx.infcx,1396                    wfcx.param_env,1397                    wfcx.body_def_id,1398                    trait_pred,1399                    trait_span,1400                    item,1401                );1402                for obligation in &mut obligations {1403                    if obligation.cause.span != trait_span {1404                        // We already have a better span.1405                        continue;1406                    }1407                    if let Some(pred) = obligation.predicate.as_trait_clause()1408                        && pred.skip_binder().self_ty() == trait_ref.self_ty()1409                    {1410                        obligation.cause.span = impl_.self_ty.span;1411                    }1412                    if let Some(pred) = obligation.predicate.as_projection_clause()1413                        && pred.skip_binder().self_ty() == trait_ref.self_ty()1414                    {1415                        obligation.cause.span = impl_.self_ty.span;1416                    }1417                }14181419                // Ensure that the `[const]` where clauses of the trait hold for the impl.1420                if tcx.is_conditionally_const(item.owner_id.def_id) {1421                    for (bound, _) in1422                        tcx.const_conditions(trait_ref.def_id).instantiate(tcx, trait_ref.args)1423                    {1424                        let bound = wfcx.normalize(1425                            item.span,1426                            Some(WellFormedLoc::Ty(item.hir_id().expect_owner().def_id)),1427                            bound,1428                        );1429                        wfcx.register_obligation(Obligation::new(1430                            tcx,1431                            ObligationCause::new(1432                                impl_.self_ty.span,1433                                wfcx.body_def_id,1434                                ObligationCauseCode::WellFormed(None),1435                            ),1436                            wfcx.param_env,1437                            bound.to_host_effect_clause(tcx, ty::BoundConstness::Maybe),1438                        ))1439                    }1440                }14411442                debug!(?obligations);1443                wfcx.register_obligations(obligations);1444            }1445            None => {1446                let self_ty = tcx.type_of(item.owner_id).instantiate_identity().skip_norm_wip();1447                let self_ty = wfcx.deeply_normalize(1448                    item.span,1449                    Some(WellFormedLoc::Ty(item.hir_id().expect_owner().def_id)),1450                    Unnormalized::new_wip(self_ty),1451                );1452                wfcx.register_wf_obligation(1453                    impl_.self_ty.span,1454                    Some(WellFormedLoc::Ty(item.hir_id().expect_owner().def_id)),1455                    self_ty.into(),1456                );1457            }1458        }14591460        check_where_clauses(wfcx, item.owner_id.def_id);1461        Ok(())1462    })1463}14641465/// Checks where-clauses and inline bounds that are declared on `def_id`.1466#[instrument(level = "debug", skip(wfcx))]1467pub(super) fn check_where_clauses<'tcx>(wfcx: &WfCheckingCtxt<'_, 'tcx>, def_id: LocalDefId) {1468    let infcx = wfcx.infcx;1469    let tcx = wfcx.tcx();14701471    let predicates = tcx.predicates_of(def_id.to_def_id());1472    let generics = tcx.generics_of(def_id);14731474    // Check that concrete defaults are well-formed. See test `type-check-defaults.rs`.1475    // For example, this forbids the declaration:1476    //1477    //     struct Foo<T = Vec<[u32]>> { .. }1478    //1479    // Here, the default `Vec<[u32]>` is not WF because `[u32]: Sized` does not hold.1480    for param in &generics.own_params {1481        if let Some(default) = param1482            .default_value(tcx)1483            .map(ty::EarlyBinder::instantiate_identity)1484            .map(Unnormalized::skip_norm_wip)1485        {1486            // Ignore dependent defaults -- that is, where the default of one type1487            // parameter includes another (e.g., `<T, U = T>`). In those cases, we can't1488            // be sure if it will error or not as user might always specify the other.1489            // FIXME(generic_const_exprs): This is incorrect when dealing with unused const params.1490            // E.g: `struct Foo<const N: usize, const M: usize = { 1 - 2 }>;`. Here, we should1491            // eagerly error but we don't as we have `ConstKind::Unevaluated(.., [N, M])`.1492            if !default.has_param() {1493                wfcx.register_wf_obligation(1494                    tcx.def_span(param.def_id),1495                    matches!(param.kind, GenericParamDefKind::Type { .. })1496                        .then(|| WellFormedLoc::Ty(param.def_id.expect_local())),1497                    default.as_term().unwrap(),1498                );1499            } else {1500                // If we've got a generic const parameter we still want to check its1501                // type is correct in case both it and the param type are fully concrete.1502                let GenericArgKind::Const(ct) = default.kind() else {1503                    continue;1504                };15051506                let ct_ty = match ct.kind() {1507                    ty::ConstKind::Infer(_)1508                    | ty::ConstKind::Placeholder(_)1509                    | ty::ConstKind::Bound(_, _) => unreachable!(),1510                    ty::ConstKind::Error(_) | ty::ConstKind::Expr(_) => continue,1511                    ty::ConstKind::Value(cv) => cv.ty,1512                    ty::ConstKind::Unevaluated(uv) => uv.type_of(infcx.tcx).skip_norm_wip(),1513                    ty::ConstKind::Param(param_ct) => {1514                        param_ct.find_const_ty_from_env(wfcx.param_env)1515                    }1516                };15171518                let param_ty = tcx.type_of(param.def_id).instantiate_identity().skip_norm_wip();1519                if !ct_ty.has_param() && !param_ty.has_param() {1520                    let cause = traits::ObligationCause::new(1521                        tcx.def_span(param.def_id),1522                        wfcx.body_def_id,1523                        ObligationCauseCode::WellFormed(None),1524                    );1525                    wfcx.register_obligation(Obligation::new(1526                        tcx,1527                        cause,1528                        wfcx.param_env,1529                        ty::ClauseKind::ConstArgHasType(ct, param_ty),1530                    ));1531                }1532            }1533        }1534    }15351536    // Check that trait predicates are WF when params are instantiated with their defaults.1537    // We don't want to overly constrain the predicates that may be written but we want to1538    // catch cases where a default my never be applied such as `struct Foo<T: Copy = String>`.1539    // Therefore we check if a predicate which contains a single type param1540    // with a concrete default is WF with that default instantiated.1541    // For more examples see tests `defaults-well-formedness.rs` and `type-check-defaults.rs`.1542    //1543    // First we build the defaulted generic parameters.1544    let args = GenericArgs::for_item(tcx, def_id.to_def_id(), |param, _| {1545        if param.index >= generics.parent_count as u321546            // If the param has a default, ...1547            && let Some(default) = param.default_value(tcx).map(ty::EarlyBinder::instantiate_identity).map(Unnormalized::skip_norm_wip)1548            // ... and it's not a dependent default, ...1549            && !default.has_param()1550        {1551            // ... then instantiate it with the default.1552            return default;1553        }1554        tcx.mk_param_from_def(param)1555    });15561557    // Now we build the instantiated predicates.1558    let default_obligations = predicates1559        .predicates1560        .iter()1561        .flat_map(|&(pred, sp)| {1562            #[derive(Default)]1563            struct CountParams {1564                params: FxHashSet<u32>,1565            }1566            impl<'tcx> ty::TypeVisitor<TyCtxt<'tcx>> for CountParams {1567                type Result = ControlFlow<()>;1568                fn visit_ty(&mut self, t: Ty<'tcx>) -> Self::Result {1569                    if let ty::Param(param) = t.kind() {1570                        self.params.insert(param.index);1571                    }1572                    t.super_visit_with(self)1573                }15741575                fn visit_region(&mut self, _: ty::Region<'tcx>) -> Self::Result {1576                    ControlFlow::Break(())1577                }15781579                fn visit_const(&mut self, c: ty::Const<'tcx>) -> Self::Result {1580                    if let ty::ConstKind::Param(param) = c.kind() {1581                        self.params.insert(param.index);1582                    }1583                    c.super_visit_with(self)1584                }1585            }1586            let mut param_count = CountParams::default();1587            let has_region = pred.visit_with(&mut param_count).is_break();1588            let instantiated_pred = ty::EarlyBinder::bind(pred).instantiate(tcx, args);1589            // Don't check non-defaulted params, dependent defaults (including lifetimes)1590            // or preds with multiple params.1591            if instantiated_pred.skip_normalization().has_non_region_param()1592                || param_count.params.len() > 11593                || has_region1594            {1595                None1596            } else if predicates1597                .predicates1598                .iter()1599                .any(|&(p, _)| Unnormalized::new_wip(p) == instantiated_pred)1600            {1601                // Avoid duplication of predicates that contain no parameters, for example.1602                None1603            } else {1604                Some((instantiated_pred, sp))1605            }1606        })1607        .map(|(pred, sp)| {1608            // Convert each of those into an obligation. So if you have1609            // something like `struct Foo<T: Copy = String>`, we would1610            // take that predicate `T: Copy`, instantiated with `String: Copy`1611            // (actually that happens in the previous `flat_map` call),1612            // and then try to prove it (in this case, we'll fail).1613            //1614            // Note the subtle difference from how we handle `predicates`1615            // below: there, we are not trying to prove those predicates1616            // to be *true* but merely *well-formed*.1617            let pred = wfcx.normalize(sp, None, pred);1618            let cause = traits::ObligationCause::new(1619                sp,1620                wfcx.body_def_id,1621                ObligationCauseCode::WhereClause(def_id.to_def_id(), sp),1622            );1623            Obligation::new(tcx, cause, wfcx.param_env, pred)1624        });16251626    let predicates = predicates.instantiate_identity(tcx);16271628    let assoc_const_obligations: Vec<_> = predicates1629        .predicates1630        .iter()1631        .copied()1632        .zip(predicates.spans.iter().copied())1633        .filter_map(|(clause, sp)| {1634            let clause = clause.skip_norm_wip();1635            let proj = clause.as_projection_clause()?;1636            let pred_binder = proj1637                .map_bound(|pred| {1638                    pred.term.as_const().map(|ct| {1639                        let assoc_const_ty =1640                            pred.projection_term.expect_ct().type_of(tcx).skip_norm_wip();1641                        ty::ClauseKind::ConstArgHasType(ct, assoc_const_ty)1642                    })1643                })1644                .transpose();1645            pred_binder.map(|pred_binder| {1646                let cause = traits::ObligationCause::new(1647                    sp,1648                    wfcx.body_def_id,1649                    ObligationCauseCode::WhereClause(def_id.to_def_id(), sp),1650                );1651                Obligation::new(tcx, cause, wfcx.param_env, pred_binder)1652            })1653        })1654        .collect();16551656    assert_eq!(predicates.predicates.len(), predicates.spans.len());1657    let wf_obligations = predicates.into_iter().flat_map(|(p, sp)| {1658        traits::wf::clause_obligations(1659            infcx,1660            wfcx.param_env,1661            wfcx.body_def_id,1662            p.skip_norm_wip(),1663            sp,1664        )1665    });1666    let obligations: Vec<_> =1667        wf_obligations.chain(default_obligations).chain(assoc_const_obligations).collect();1668    wfcx.register_obligations(obligations);1669}16701671#[instrument(level = "debug", skip(wfcx, hir_decl))]1672fn check_fn_or_method<'tcx>(1673    wfcx: &WfCheckingCtxt<'_, 'tcx>,1674    sig: ty::PolyFnSig<'tcx>,1675    hir_decl: &hir::FnDecl<'_>,1676    def_id: LocalDefId,1677) {1678    let tcx = wfcx.tcx();1679    let mut sig = tcx.liberate_late_bound_regions(def_id.to_def_id(), sig);16801681    // Normalize the input and output types one at a time, using a different1682    // `WellFormedLoc` for each. We cannot call `normalize_associated_types`1683    // on the entire `FnSig`, since this would use the same `WellFormedLoc`1684    // for each type, preventing the HIR wf check from generating1685    // a nice error message.1686    let arg_span =1687        |idx| hir_decl.inputs.get(idx).map_or(hir_decl.output.span(), |arg: &hir::Ty<'_>| arg.span);16881689    sig.inputs_and_output =1690        tcx.mk_type_list_from_iter(sig.inputs_and_output.iter().enumerate().map(|(idx, ty)| {1691            wfcx.deeply_normalize(1692                arg_span(idx),1693                Some(WellFormedLoc::Param {1694                    function: def_id,1695                    // Note that the `param_idx` of the output type is1696                    // one greater than the index of the last input type.1697                    param_idx: idx,1698                }),1699                Unnormalized::new_wip(ty),1700            )1701        }));17021703    for (idx, ty) in sig.inputs_and_output.iter().enumerate() {1704        wfcx.register_wf_obligation(1705            arg_span(idx),1706            Some(WellFormedLoc::Param { function: def_id, param_idx: idx }),1707            ty.into(),1708        );1709    }17101711    check_where_clauses(wfcx, def_id);17121713    if sig.abi() == ExternAbi::RustCall {1714        let span = tcx.def_span(def_id);1715        let has_implicit_self = hir_decl.implicit_self().has_implicit_self();1716        let mut inputs = sig.inputs().iter().skip(if has_implicit_self { 1 } else { 0 });1717        // FIXME(splat): use `sig.splatted()` once FnSig has it1718        // Check that the argument is a tuple and is sized1719        if let Some(ty) = inputs.next() {1720            wfcx.register_bound(1721                ObligationCause::new(span, wfcx.body_def_id, ObligationCauseCode::RustCall),1722                wfcx.param_env,1723                *ty,1724                tcx.require_lang_item(hir::LangItem::Tuple, span),1725            );1726            wfcx.register_bound(1727                ObligationCause::new(span, wfcx.body_def_id, ObligationCauseCode::RustCall),1728                wfcx.param_env,1729                *ty,1730                tcx.require_lang_item(hir::LangItem::Sized, span),1731            );1732        } else {1733            tcx.dcx().span_err(1734                hir_decl.inputs.last().map_or(span, |input| input.span),1735                "functions with the \"rust-call\" ABI must take a single non-self tuple argument",1736            );1737        }1738        // No more inputs other than the `self` type and the tuple type1739        if inputs.next().is_some() {1740            tcx.dcx().span_err(1741                hir_decl.inputs.last().map_or(span, |input| input.span),1742                "functions with the \"rust-call\" ABI must take a single non-self tuple argument",1743            );1744        }1745    }17461747    // If the function has a body, additionally require that the return type is sized.1748    if let Some(body) = tcx.hir_maybe_body_owned_by(def_id) {1749        let span = match hir_decl.output {1750            hir::FnRetTy::Return(ty) => ty.span,1751            hir::FnRetTy::DefaultReturn(_) => body.value.span,1752        };17531754        wfcx.register_bound(1755            ObligationCause::new(span, def_id, ObligationCauseCode::SizedReturnType),1756            wfcx.param_env,1757            sig.output(),1758            tcx.require_lang_item(LangItem::Sized, span),1759        );1760    }1761}17621763/// The `arbitrary_self_types_pointers` feature implies `arbitrary_self_types`.1764#[derive(Clone, Copy, PartialEq)]1765enum ArbitrarySelfTypesLevel {1766    Basic,        // just arbitrary_self_types1767    WithPointers, // both arbitrary_self_types and arbitrary_self_types_pointers1768}17691770#[instrument(level = "debug", skip(wfcx))]1771fn check_method_receiver<'tcx>(1772    wfcx: &WfCheckingCtxt<'_, 'tcx>,1773    fn_sig: &hir::FnSig<'_>,1774    method: ty::AssocItem,1775    self_ty: Ty<'tcx>,1776) -> Result<(), ErrorGuaranteed> {1777    let tcx = wfcx.tcx();17781779    if !method.is_method() {1780        return Ok(());1781    }17821783    let span = fn_sig.decl.inputs[0].span;1784    let loc = Some(WellFormedLoc::Param { function: method.def_id.expect_local(), param_idx: 0 });17851786    let sig = tcx.fn_sig(method.def_id).instantiate_identity().skip_norm_wip();1787    let sig = tcx.liberate_late_bound_regions(method.def_id, sig);1788    let sig = wfcx.normalize(DUMMY_SP, loc, Unnormalized::new_wip(sig));17891790    debug!("check_method_receiver: sig={:?}", sig);17911792    let self_ty = wfcx.normalize(DUMMY_SP, loc, Unnormalized::new_wip(self_ty));17931794    let receiver_ty = sig.inputs()[0];1795    let receiver_ty = wfcx.normalize(DUMMY_SP, loc, Unnormalized::new_wip(receiver_ty));17961797    // If the receiver already has errors reported, consider it valid to avoid1798    // unnecessary errors (#58712).1799    receiver_ty.error_reported()?;18001801    let arbitrary_self_types_level = if tcx.features().arbitrary_self_types_pointers() {1802        Some(ArbitrarySelfTypesLevel::WithPointers)1803    } else if tcx.features().arbitrary_self_types() {1804        Some(ArbitrarySelfTypesLevel::Basic)1805    } else {1806        None1807    };1808    let generics = tcx.generics_of(method.def_id);18091810    let receiver_validity =1811        receiver_is_valid(wfcx, span, receiver_ty, self_ty, arbitrary_self_types_level, generics);1812    if let Err(receiver_validity_err) = receiver_validity {1813        return Err(match arbitrary_self_types_level {1814            // Wherever possible, emit a message advising folks that the features1815            // `arbitrary_self_types` or `arbitrary_self_types_pointers` might1816            // have helped.1817            None if receiver_is_valid(1818                wfcx,1819                span,1820                receiver_ty,1821                self_ty,1822                Some(ArbitrarySelfTypesLevel::Basic),1823                generics,1824            )1825            .is_ok() =>1826            {1827                // Report error; would have worked with `arbitrary_self_types`.1828                feature_err(1829                    &tcx.sess,1830                    sym::arbitrary_self_types,1831                    span,1832                    format!(1833                        "`{receiver_ty}` cannot be used as the type of `self` without \1834                            the `arbitrary_self_types` feature",1835                    ),1836                )1837                .with_help(msg!("consider changing to `self`, `&self`, `&mut self`, or a type implementing `Receiver` such as `self: Box<Self>`, `self: Rc<Self>`, or `self: Arc<Self>`"))1838                .emit()1839            }1840            None | Some(ArbitrarySelfTypesLevel::Basic)1841                if receiver_is_valid(1842                    wfcx,1843                    span,1844                    receiver_ty,1845                    self_ty,1846                    Some(ArbitrarySelfTypesLevel::WithPointers),1847                    generics,1848                )1849                .is_ok() =>1850            {1851                // Report error; would have worked with `arbitrary_self_types_pointers`.1852                feature_err(1853                    &tcx.sess,1854                    sym::arbitrary_self_types_pointers,1855                    span,1856                    format!(1857                        "`{receiver_ty}` cannot be used as the type of `self` without \1858                            the `arbitrary_self_types_pointers` feature",1859                    ),1860                )1861                .with_help(msg!("consider changing to `self`, `&self`, `&mut self`, or a type implementing `Receiver` such as `self: Box<Self>`, `self: Rc<Self>`, or `self: Arc<Self>`"))1862                .emit()1863            }1864            _ =>1865            // Report error; would not have worked with `arbitrary_self_types[_pointers]`.1866            {1867                match receiver_validity_err {1868                    ReceiverValidityError::DoesNotDeref if arbitrary_self_types_level.is_some() => {1869                        let hint = match receiver_ty1870                            .builtin_deref(false)1871                            .unwrap_or(receiver_ty)1872                            .ty_adt_def()1873                            .and_then(|adt_def| tcx.get_diagnostic_name(adt_def.did()))1874                        {1875                            Some(sym::RcWeak | sym::ArcWeak) => Some(InvalidReceiverTyHint::Weak),1876                            Some(sym::NonNull) => Some(InvalidReceiverTyHint::NonNull),1877                            _ => None,1878                        };18791880                        tcx.dcx().emit_err(diagnostics::InvalidReceiverTy {1881                            span,1882                            receiver_ty,1883                            hint,1884                        })1885                    }1886                    ReceiverValidityError::DoesNotDeref => {1887                        tcx.dcx().emit_err(diagnostics::InvalidReceiverTyNoArbitrarySelfTypes {1888                            span,1889                            receiver_ty,1890                        })1891                    }1892                    ReceiverValidityError::MethodGenericParamUsed => tcx1893                        .dcx()1894                        .emit_err(diagnostics::InvalidGenericReceiverTy { span, receiver_ty }),1895                }1896            }1897        });1898    }1899    Ok(())1900}19011902/// Error cases which may be returned from `receiver_is_valid`. These error1903/// cases are generated in this function as they may be unearthed as we explore1904/// the `autoderef` chain, but they're converted to diagnostics in the caller.1905enum ReceiverValidityError {1906    /// The self type does not get to the receiver type by following the1907    /// autoderef chain.1908    DoesNotDeref,1909    /// A type was found which is a method type parameter, and that's not allowed.1910    MethodGenericParamUsed,1911}19121913/// Confirms that a type is not a type parameter referring to one of the1914/// method's type params.1915fn confirm_type_is_not_a_method_generic_param(1916    ty: Ty<'_>,1917    method_generics: &ty::Generics,1918) -> Result<(), ReceiverValidityError> {1919    if let ty::Param(param) = ty.kind() {1920        if (param.index as usize) >= method_generics.parent_count {1921            return Err(ReceiverValidityError::MethodGenericParamUsed);1922        }1923    }1924    Ok(())1925}19261927/// Returns whether `receiver_ty` would be considered a valid receiver type for `self_ty`. If1928/// `arbitrary_self_types` is enabled, `receiver_ty` must transitively deref to `self_ty`, possibly1929/// through a `*const/mut T` raw pointer if  `arbitrary_self_types_pointers` is also enabled.1930/// If neither feature is enabled, the requirements are more strict: `receiver_ty` must implement1931/// `Receiver` and directly implement `Deref<Target = self_ty>`.1932///1933/// N.B., there are cases this function returns `true` but causes an error to be emitted,1934/// particularly when `receiver_ty` derefs to a type that is the same as `self_ty` but has the1935/// wrong lifetime. Be careful of this if you are calling this function speculatively.1936fn receiver_is_valid<'tcx>(1937    wfcx: &WfCheckingCtxt<'_, 'tcx>,1938    span: Span,1939    receiver_ty: Ty<'tcx>,1940    self_ty: Ty<'tcx>,1941    arbitrary_self_types_enabled: Option<ArbitrarySelfTypesLevel>,1942    method_generics: &ty::Generics,1943) -> Result<(), ReceiverValidityError> {1944    let infcx = wfcx.infcx;1945    let tcx = wfcx.tcx();1946    let cause =1947        ObligationCause::new(span, wfcx.body_def_id, traits::ObligationCauseCode::MethodReceiver);19481949    // Special case `receiver == self_ty`, which doesn't necessarily require the `Receiver` lang item.1950    if let Ok(()) = wfcx.infcx.commit_if_ok(|_| {1951        let ocx = ObligationCtxt::new(wfcx.infcx);1952        ocx.eq(&cause, wfcx.param_env, self_ty, receiver_ty)?;1953        if ocx.evaluate_obligations_error_on_ambiguity().is_empty() {1954            Ok(())1955        } else {1956            Err(NoSolution)1957        }1958    }) {1959        return Ok(());1960    }19611962    confirm_type_is_not_a_method_generic_param(receiver_ty, method_generics)?;19631964    let mut autoderef = Autoderef::new(infcx, wfcx.param_env, wfcx.body_def_id, span, receiver_ty);19651966    // The `arbitrary_self_types` feature allows custom smart pointer1967    // types to be method receivers, as identified by following the Receiver<Target=T>1968    // chain.1969    if arbitrary_self_types_enabled.is_some() {1970        autoderef = autoderef.use_receiver_trait();1971    }19721973    // The `arbitrary_self_types_pointers` feature allows raw pointer receivers like `self: *const Self`.1974    if arbitrary_self_types_enabled == Some(ArbitrarySelfTypesLevel::WithPointers) {1975        autoderef = autoderef.include_raw_pointers();1976    }19771978    // Keep dereferencing `receiver_ty` until we get to `self_ty`.1979    while let Some((potential_self_ty, _)) = autoderef.next() {1980        debug!(1981            "receiver_is_valid: potential self type `{:?}` to match `{:?}`",1982            potential_self_ty, self_ty1983        );19841985        confirm_type_is_not_a_method_generic_param(potential_self_ty, method_generics)?;19861987        // Check if the self type unifies. If it does, then commit the result1988        // since it may have region side-effects.1989        if let Ok(()) = wfcx.infcx.commit_if_ok(|_| {1990            let ocx = ObligationCtxt::new(wfcx.infcx);1991            ocx.eq(&cause, wfcx.param_env, self_ty, potential_self_ty)?;1992            if ocx.evaluate_obligations_error_on_ambiguity().is_empty() {1993                Ok(())1994            } else {1995                Err(NoSolution)1996            }1997        }) {1998            wfcx.register_obligations(autoderef.into_obligations());1999            return Ok(());2000        }

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.