compiler/rustc_hir_analysis/src/check/wfcheck.rs RUST 2,499 lines View on github.com → Search inside
File is large — showing lines 1–2,000 of 2,499.
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::lang_items::LangItem;12use rustc_hir::attrs::{EiiDecl, EiiImpl, EiiImplResolution};13use rustc_hir::def::{DefKind, Res};14use rustc_hir::def_id::{DefId, LocalDefId};15use rustc_hir::{AmbigArg, ItemKind, find_attr};16use rustc_infer::infer::TyCtxtInferExt;17use rustc_infer::infer::outlives::env::OutlivesEnvironment;18use rustc_infer::traits::{PredicateObligations, TraitErrors};19use rustc_lint_defs::builtin::{REDUNDANT_LIFETIMES, 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, RegionExt, Ty, TyCtxt, TypeFlags,26    TypeFoldable, TypeSuperVisitable, TypeVisitable, TypeVisitableExt, TypeVisitor, TypingMode,27    Unnormalized, Upcast,28};29use rustc_middle::{bug, span_bug};30use rustc_session::diagnostics::feature_err;31use rustc_span::{DUMMY_SP, Span, sym};32use rustc_trait_selection::error_reporting::InferCtxtErrorExt;33use rustc_trait_selection::regions::{34    OutlivesEnvironmentBuildExt, region_known_to_outlive, ty_known_to_outlive,35};36use rustc_trait_selection::traits::misc::{37    ConstParamTyImplementationError, type_allowed_to_implement_const_param_ty,38};39use rustc_trait_selection::traits::query::evaluate_obligation::InferCtxtExt as _;40use rustc_trait_selection::traits::{41    self, FulfillmentError, Obligation, ObligationCause, ObligationCauseCode, ObligationCtxt,42    WellFormedLoc,43};44use tracing::{debug, instrument};4546use super::compare_eii::{compare_eii_function_types, compare_eii_statics};47use crate::autoderef::Autoderef;48use crate::constrained_generic_params::{Parameter, identify_constrained_generic_params};49use crate::diagnostics;50use crate::diagnostics::InvalidReceiverTyHint;5152pub(super) struct WfCheckingCtxt<'a, 'tcx> {53    pub(super) ocx: ObligationCtxt<'a, 'tcx, FulfillmentError<'tcx>>,54    body_def_id: LocalDefId,55    param_env: ty::ParamEnv<'tcx>,56}57impl<'a, 'tcx> Deref for WfCheckingCtxt<'a, 'tcx> {58    type Target = ObligationCtxt<'a, 'tcx, FulfillmentError<'tcx>>;59    fn deref(&self) -> &Self::Target {60        &self.ocx61    }62}6364impl<'tcx> WfCheckingCtxt<'_, 'tcx> {65    fn tcx(&self) -> TyCtxt<'tcx> {66        self.ocx.infcx.tcx67    }6869    // Convenience function to normalize during wfcheck. This performs70    // `ObligationCtxt::normalize`, but provides a nice `ObligationCauseCode`.71    fn normalize<T>(72        &self,73        span: Span,74        loc: Option<WellFormedLoc>,75        value: Unnormalized<'tcx, T>,76    ) -> T77    where78        T: TypeFoldable<TyCtxt<'tcx>>,79    {80        self.ocx.normalize(81            &ObligationCause::new(span, self.body_def_id, ObligationCauseCode::WellFormed(loc)),82            self.param_env,83            value,84        )85    }8687    /// Convenience function to *deeply* normalize during wfcheck. In the old solver,88    /// this just dispatches to [`WfCheckingCtxt::normalize`], but in the new solver89    /// this calls `deeply_normalize` and reports errors if they are encountered.90    ///91    /// This function should be called in favor of `normalize` in cases where we will92    /// then check the well-formedness of the type, since we only use the normalized93    /// signature types for implied bounds when checking regions.94    // FIXME(-Znext-solver): This should be removed when we compute implied outlives95    // bounds using the unnormalized signature of the function we're checking.96    pub(super) fn deeply_normalize<T>(97        &self,98        span: Span,99        loc: Option<WellFormedLoc>,100        value: Unnormalized<'tcx, T>,101    ) -> T102    where103        T: TypeFoldable<TyCtxt<'tcx>>,104    {105        if self.infcx.next_trait_solver() {106            match self.ocx.deeply_normalize(107                &ObligationCause::new(span, self.body_def_id, ObligationCauseCode::WellFormed(loc)),108                self.param_env,109                value.clone(),110            ) {111                Ok(value) => value,112                Err(errors) => {113                    self.infcx.err_ctxt().report_fulfillment_errors(errors);114                    value.skip_norm_wip()115                }116            }117        } else {118            self.normalize(span, loc, value)119        }120    }121122    pub(super) fn register_wf_obligation(123        &self,124        span: Span,125        loc: Option<WellFormedLoc>,126        term: ty::Term<'tcx>,127    ) {128        let cause = traits::ObligationCause::new(129            span,130            self.body_def_id,131            ObligationCauseCode::WellFormed(loc),132        );133        self.ocx.register_obligation(Obligation::new(134            self.tcx(),135            cause,136            self.param_env,137            ty::ClauseKind::WellFormed(term),138        ));139    }140141    pub(super) fn unnormalized_obligations(142        &self,143        span: Span,144        ty: Ty<'tcx>,145    ) -> Option<PredicateObligations<'tcx>> {146        traits::wf::unnormalized_obligations(147            self.ocx.infcx,148            self.param_env,149            ty.into(),150            span,151            self.body_def_id,152        )153    }154}155156pub(super) fn enter_wf_checking_ctxt<'tcx, F>(157    tcx: TyCtxt<'tcx>,158    body_def_id: LocalDefId,159    f: F,160) -> Result<(), ErrorGuaranteed>161where162    F: for<'a> FnOnce(&WfCheckingCtxt<'a, 'tcx>) -> Result<(), ErrorGuaranteed>,163{164    let param_env = tcx.param_env(body_def_id);165    let infcx = &tcx.infer_ctxt().build(TypingMode::non_body_analysis());166    let ocx = ObligationCtxt::new_with_diagnostics(infcx);167168    let mut wfcx = WfCheckingCtxt { ocx, body_def_id, param_env };169170    // As of now, bounds are only enforced on checked type aliases, they're ignored for most type171    // aliases. So, only check for false global bounds if we're not ignoring bounds altogether.172    let ignore_bounds =173        tcx.def_kind(body_def_id) == DefKind::TyAlias && !tcx.type_alias_is_checked(body_def_id);174175    if !ignore_bounds && !tcx.features().trivial_bounds() {176        wfcx.check_false_global_bounds()177    }178    f(&mut wfcx)?;179180    let errors = wfcx.evaluate_obligations_error_on_ambiguity();181    if let TraitErrors::HasErrors(errors) = errors {182        return Err(infcx.err_ctxt().report_fulfillment_errors(errors));183    }184185    let assumed_wf_types = wfcx.ocx.assumed_wf_types_and_report_errors(param_env, body_def_id)?;186    debug!(?assumed_wf_types);187188    let infcx_compat = infcx.fork();189190    // We specifically want to *disable* the implied bounds hack, first,191    // so we can detect when failures are due to bevy's implied bounds.192    let outlives_env = OutlivesEnvironment::new_with_implied_bounds_compat(193        &infcx,194        body_def_id,195        param_env,196        assumed_wf_types.iter().copied(),197        true,198    );199200    lint_redundant_lifetimes(tcx, body_def_id, &outlives_env);201202    let errors = infcx.resolve_regions_with_outlives_env(&outlives_env, tcx.def_span(body_def_id));203    if errors.is_empty() {204        return Ok(());205    }206207    let outlives_env = OutlivesEnvironment::new_with_implied_bounds_compat(208        &infcx_compat,209        body_def_id,210        param_env,211        assumed_wf_types,212        // Don't *disable* the implied bounds hack; though this will only apply213        // the implied bounds hack if this contains `bevy_ecs`'s `ParamSet` type.214        false,215    );216    let errors_compat =217        infcx_compat.resolve_regions_with_outlives_env(&outlives_env, tcx.def_span(body_def_id));218    if errors_compat.is_empty() {219        // FIXME: Once we fix bevy, this would be the place to insert a warning220        // to upgrade bevy.221        Ok(())222    } else {223        Err(infcx_compat.err_ctxt().report_region_errors(body_def_id, &errors_compat))224    }225}226227pub(super) fn check_well_formed(228    tcx: TyCtxt<'_>,229    def_id: LocalDefId,230) -> Result<(), ErrorGuaranteed> {231    let mut res = crate::check::check::check_item_type(tcx, def_id);232233    for param in &tcx.generics_of(def_id).own_params {234        res = res.and(check_param_wf(tcx, param));235    }236237    res238}239240/// Checks that the field types (in a struct def'n) or argument types (in an enum def'n) are241/// well-formed, meaning that they do not require any constraints not declared in the struct242/// definition itself. For example, this definition would be illegal:243///244/// ```rust245/// struct StaticRef<T> { x: &'static T }246/// ```247///248/// because the type did not declare that `T: 'static`.249///250/// We do this check as a pre-pass before checking fn bodies because if these constraints are251/// not included it frequently leads to confusing errors in fn bodies. So it's better to check252/// the types first.253#[instrument(skip(tcx), level = "debug")]254pub(super) fn check_item<'tcx>(255    tcx: TyCtxt<'tcx>,256    item: &'tcx hir::Item<'tcx>,257) -> Result<(), ErrorGuaranteed> {258    let def_id = item.owner_id.def_id;259260    debug!(261        ?item.owner_id,262        item.name = ? tcx.def_path_str(def_id)263    );264265    match item.kind {266        // Right now we check that every default trait implementation267        // has an implementation of itself. Basically, a case like:268        //269        //     impl Trait for T {}270        //271        // has a requirement of `T: Trait` which was required for default272        // method implementations. Although this could be improved now that273        // there's a better infrastructure in place for this, it's being left274        // for a follow-up work.275        //276        // Since there's such a requirement, we need to check *just* positive277        // implementations, otherwise things like:278        //279        //     impl !Send for T {}280        //281        // won't be allowed unless there's an *explicit* implementation of `Send`282        // for `T`283        hir::ItemKind::Impl(ref impl_) => {284            crate::impl_wf_check::check_impl_wf(tcx, def_id, impl_.of_trait.is_some())?;285            let mut res = Ok(());286            if let Some(of_trait) = impl_.of_trait {287                let header = tcx.impl_trait_header(def_id);288                let is_auto = tcx.trait_is_auto(header.trait_ref.skip_binder().def_id);289                if let (hir::Defaultness::Default { .. }, true) = (of_trait.defaultness, is_auto) {290                    let sp = of_trait.trait_ref.path.span;291                    res = Err(tcx292                        .dcx()293                        .struct_span_err(sp, "impls of auto traits cannot be default")294                        .with_span_labels(of_trait.defaultness_span, "default because of this")295                        .with_span_label(sp, "auto trait")296                        .emit());297                }298                match header.polarity {299                    ty::ImplPolarity::Positive => {300                        res = res.and(check_impl(tcx, item, impl_));301                    }302                    ty::ImplPolarity::Negative => {303                        let ast::ImplPolarity::Negative(span) = of_trait.polarity else {304                            bug!("impl_polarity query disagrees with impl's polarity in HIR");305                        };306                        // FIXME(#27579): what amount of WF checking do we need for neg impls?307                        if let hir::Defaultness::Default { .. } = of_trait.defaultness {308                            let mut spans = vec![span];309                            spans.extend(of_trait.defaultness_span);310                            res = Err(struct_span_code_err!(311                                tcx.dcx(),312                                spans,313                                E0750,314                                "negative impls cannot be default impls"315                            )316                            .emit());317                        }318                    }319                    ty::ImplPolarity::Reservation => {320                        // FIXME: what amount of WF checking do we need for reservation impls?321                    }322                }323            } else {324                res = res.and(check_impl(tcx, item, impl_));325            }326            res327        }328        hir::ItemKind::Fn { sig, .. } => check_item_fn(tcx, def_id, sig.decl),329        // Note: do not add new entries to this match. Instead add all new logic in `check_item_type`330        _ => span_bug!(item.span, "should have been handled by the type based wf check: {item:?}"),331    }332}333334pub(super) fn check_foreign_item<'tcx>(335    tcx: TyCtxt<'tcx>,336    item: &'tcx hir::ForeignItem<'tcx>,337) -> Result<(), ErrorGuaranteed> {338    let def_id = item.owner_id.def_id;339340    debug!(341        ?item.owner_id,342        item.name = ? tcx.def_path_str(def_id)343    );344345    match item.kind {346        hir::ForeignItemKind::Fn(sig, ..) => check_item_fn(tcx, def_id, sig.decl),347        hir::ForeignItemKind::Static(..) | hir::ForeignItemKind::Type => Ok(()),348    }349}350351pub(crate) fn check_trait_item<'tcx>(352    tcx: TyCtxt<'tcx>,353    def_id: LocalDefId,354) -> Result<(), ErrorGuaranteed> {355    // Check that an item definition in a subtrait is shadowing a supertrait item.356    lint_item_shadowing_supertrait_item(tcx, def_id);357358    let mut res = Ok(());359360    if tcx.def_kind(def_id) == DefKind::AssocFn {361        for &assoc_ty_def_id in362            tcx.associated_types_for_impl_traits_in_associated_fn(def_id.to_def_id())363        {364            res = res.and(check_associated_item(tcx, assoc_ty_def_id.expect_local()));365        }366    }367    res368}369370/// Require that the user writes where clauses on GATs for the implicit371/// outlives bounds involving trait parameters in trait functions and372/// lifetimes passed as GAT args. See `self-outlives-lint` test.373///374/// We use the following trait as an example throughout this function:375/// ```rust,ignore (this code fails due to this lint)376/// trait IntoIter {377///     type Iter<'a>: Iterator<Item = Self::Item<'a>>;378///     type Item<'a>;379///     fn into_iter<'a>(&'a self) -> Self::Iter<'a>;380/// }381/// ```382pub(crate) fn check_gat_where_clauses(tcx: TyCtxt<'_>, trait_def_id: LocalDefId) {383    // Associates every GAT's def_id to a list of possibly missing bounds detected by this lint.384    let mut required_bounds_by_item = FxIndexMap::default();385    let associated_items = tcx.associated_items(trait_def_id);386387    // Loop over all GATs together, because if this lint suggests adding a where-clause bound388    // to one GAT, it might then require us to an additional bound on another GAT.389    // In our `IntoIter` example, we discover a missing `Self: 'a` bound on `Iter<'a>`, which390    // then in a second loop adds a `Self: 'a` bound to `Item` due to the relationship between391    // those GATs.392    loop {393        let mut should_continue = false;394        for gat_item in associated_items.in_definition_order() {395            let gat_def_id = gat_item.def_id.expect_local();396            let gat_item = tcx.associated_item(gat_def_id);397            // If this item is not an assoc ty, or has no args, then it's not a GAT398            if !gat_item.is_type() {399                continue;400            }401            let gat_generics = tcx.generics_of(gat_def_id);402            // FIXME(jackh726): we can also warn in the more general case403            if gat_generics.is_own_empty() {404                continue;405            }406407            // Gather the bounds with which all other items inside of this trait constrain the GAT.408            // This is calculated by taking the intersection of the bounds that each item409            // constrains the GAT with individually.410            let mut new_required_bounds: Option<FxIndexSet<ty::Clause<'_>>> = None;411            for item in associated_items.in_definition_order() {412                let item_def_id = item.def_id.expect_local();413                // Skip our own GAT, since it does not constrain itself at all.414                if item_def_id == gat_def_id {415                    continue;416                }417418                let param_env = tcx.param_env(item_def_id);419420                let item_required_bounds = match tcx.associated_item(item_def_id).kind {421                    // In our example, this corresponds to `into_iter` method422                    ty::AssocKind::Fn { .. } => {423                        // For methods, we check the function signature's return type for any GATs424                        // to constrain. In the `into_iter` case, we see that the return type425                        // `Self::Iter<'a>` is a GAT we want to gather any potential missing bounds from.426                        let sig: ty::FnSig<'_> = tcx.liberate_late_bound_regions(427                            item_def_id.to_def_id(),428                            tcx.fn_sig(item_def_id).instantiate_identity().skip_norm_wip(),429                        );430                        gather_gat_bounds(431                            tcx,432                            param_env,433                            item_def_id,434                            sig.inputs_and_output,435                            // We also assume that all of the function signature's parameter types436                            // are well formed.437                            &sig.inputs().iter().copied().collect(),438                            gat_def_id,439                            gat_generics,440                        )441                    }442                    // In our example, this corresponds to the `Iter` and `Item` associated types443                    ty::AssocKind::Type { .. } => {444                        // If our associated item is a GAT with missing bounds, add them to445                        // the param-env here. This allows this GAT to propagate missing bounds446                        // to other GATs.447                        let param_env = augment_param_env(448                            tcx,449                            param_env,450                            required_bounds_by_item.get(&item_def_id),451                        );452                        gather_gat_bounds(453                            tcx,454                            param_env,455                            item_def_id,456                            tcx.explicit_item_bounds(item_def_id)457                                .iter_identity_copied()458                                .map(Unnormalized::skip_norm_wip)459                                .collect::<Vec<_>>(),460                            &FxIndexSet::default(),461                            gat_def_id,462                            gat_generics,463                        )464                    }465                    ty::AssocKind::Const { .. } => None,466                };467468                if let Some(item_required_bounds) = item_required_bounds {469                    // Take the intersection of the required bounds for this GAT, and470                    // the item_required_bounds which are the ones implied by just471                    // this item alone.472                    // This is why we use an Option<_>, since we need to distinguish473                    // the empty set of bounds from the _uninitialized_ set of bounds.474                    if let Some(new_required_bounds) = &mut new_required_bounds {475                        new_required_bounds.retain(|b| item_required_bounds.contains(b));476                    } else {477                        new_required_bounds = Some(item_required_bounds);478                    }479                }480            }481482            if let Some(new_required_bounds) = new_required_bounds {483                let required_bounds = required_bounds_by_item.entry(gat_def_id).or_default();484                if new_required_bounds.into_iter().any(|p| required_bounds.insert(p)) {485                    // Iterate until our required_bounds no longer change486                    // Since they changed here, we should continue the loop487                    should_continue = true;488                }489            }490        }491        // We know that this loop will eventually halt, since we only set `should_continue` if the492        // `required_bounds` for this item grows. Since we are not creating any new region or type493        // variables, the set of all region and type bounds that we could ever insert are limited494        // by the number of unique types and regions we observe in a given item.495        if !should_continue {496            break;497        }498    }499500    for (gat_def_id, required_bounds) in required_bounds_by_item {501        // Don't suggest adding `Self: 'a` to a GAT that can't be named502        if tcx.is_impl_trait_in_trait(gat_def_id.to_def_id()) {503            continue;504        }505506        let gat_item_hir = tcx.hir_expect_trait_item(gat_def_id);507        debug!(?required_bounds);508        let param_env = tcx.param_env(gat_def_id);509510        let unsatisfied_bounds: Vec<_> = required_bounds511            .into_iter()512            .filter(|clause| match clause.kind().skip_binder() {513                ty::ClauseKind::RegionOutlives(ty::OutlivesClause(a, b)) => {514                    !region_known_to_outlive(515                        tcx,516                        gat_def_id,517                        param_env,518                        &FxIndexSet::default(),519                        a,520                        b,521                    )522                }523                ty::ClauseKind::TypeOutlives(ty::OutlivesClause(a, b)) => {524                    !ty_known_to_outlive(tcx, gat_def_id, param_env, &FxIndexSet::default(), a, b)525                }526                _ => bug!("Unexpected ClauseKind"),527            })528            .map(|clause| clause.to_string())529            .collect();530531        if !unsatisfied_bounds.is_empty() {532            let plural = pluralize!(unsatisfied_bounds.len());533            let suggestion = format!(534                "{} {}",535                gat_item_hir.generics.add_where_or_trailing_comma(),536                unsatisfied_bounds.join(", "),537            );538            let bound =539                if unsatisfied_bounds.len() > 1 { "these bounds are" } else { "this bound is" };540            tcx.dcx()541                .struct_span_err(542                    gat_item_hir.span,543                    format!("missing required bound{} on `{}`", plural, gat_item_hir.ident),544                )545                .with_span_suggestion(546                    gat_item_hir.generics.tail_span_for_predicate_suggestion(),547                    format!("add the required where clause{plural}"),548                    suggestion,549                    Applicability::MachineApplicable,550                )551                .with_note(format!(552                    "{bound} currently required to ensure that impls have maximum flexibility"553                ))554                .with_note(555                    "we are soliciting feedback, see issue #87479 \556                     <https://github.com/rust-lang/rust/issues/87479> for more information",557                )558                .emit();559        }560    }561}562563/// Add a new set of predicates to the caller_bounds of an existing param_env.564fn augment_param_env<'tcx>(565    tcx: TyCtxt<'tcx>,566    param_env: ty::ParamEnv<'tcx>,567    new_clauses: Option<&FxIndexSet<ty::Clause<'tcx>>>,568) -> ty::ParamEnv<'tcx> {569    let Some(new_clauses) = new_clauses else {570        return param_env;571    };572573    if new_clauses.is_empty() {574        return param_env;575    }576577    let bounds = tcx578        .mk_clauses_from_iter(param_env.caller_bounds().iter().chain(new_clauses.iter().copied()));579    // FIXME(compiler-errors): Perhaps there is a case where we need to normalize this580    // i.e. traits::normalize_param_env_or_error581    ty::ParamEnv::new(bounds)582}583584/// We use the following trait as an example throughout this function.585/// Specifically, let's assume that `to_check` here is the return type586/// of `into_iter`, and the GAT we are checking this for is `Iter`.587/// ```rust,ignore (this code fails due to this lint)588/// trait IntoIter {589///     type Iter<'a>: Iterator<Item = Self::Item<'a>>;590///     type Item<'a>;591///     fn into_iter<'a>(&'a self) -> Self::Iter<'a>;592/// }593/// ```594fn gather_gat_bounds<'tcx, T: TypeFoldable<TyCtxt<'tcx>>>(595    tcx: TyCtxt<'tcx>,596    param_env: ty::ParamEnv<'tcx>,597    item_def_id: LocalDefId,598    to_check: T,599    wf_tys: &FxIndexSet<Ty<'tcx>>,600    gat_def_id: LocalDefId,601    gat_generics: &'tcx ty::Generics,602) -> Option<FxIndexSet<ty::Clause<'tcx>>> {603    // The bounds we that we would require from `to_check`604    let mut bounds = FxIndexSet::default();605606    let (regions, types) = GATArgsCollector::visit(gat_def_id.to_def_id(), to_check);607608    // If both regions and types are empty, then this GAT isn't in the609    // set of types we are checking, and we shouldn't try to do clause analysis610    // (particularly, doing so would end up with an empty set of clauses,611    // since the current method would require none, and we take the612    // intersection of requirements of all methods)613    if types.is_empty() && regions.is_empty() {614        return None;615    }616617    for (region_a, region_a_idx) in &regions {618        // Ignore `'static` lifetimes for the purpose of this lint: it's619        // because we know it outlives everything and so doesn't give meaningful620        // clues. Also ignore `ReError`, to avoid knock-down errors.621        if let ty::ReStatic | ty::ReError(_) = region_a.kind() {622            continue;623        }624        // For each region argument (e.g., `'a` in our example), check for a625        // relationship to the type arguments (e.g., `Self`). If there is an626        // outlives relationship (`Self: 'a`), then we want to ensure that is627        // reflected in a where clause on the GAT itself.628        for (ty, ty_idx) in &types {629            // In our example, requires that `Self: 'a`630            if ty_known_to_outlive(tcx, item_def_id, param_env, wf_tys, *ty, *region_a) {631                debug!(?ty_idx, ?region_a_idx);632                debug!("required clause: {ty} must outlive {region_a}");633                // Translate into the generic parameters of the GAT. In634                // our example, the type was `Self`, which will also be635                // `Self` in the GAT.636                let ty_param = gat_generics.param_at(*ty_idx, tcx);637                let ty_param = Ty::new_param(tcx, ty_param.index, ty_param.name);638                // Same for the region. In our example, 'a corresponds639                // to the 'me parameter.640                let region_param = gat_generics.param_at(*region_a_idx, tcx);641                let region_param = ty::Region::new_early_param(642                    tcx,643                    ty::EarlyParamRegion { index: region_param.index, name: region_param.name },644                );645                // The clause we expect to see. (In our example,646                // `Self: 'me`.)647                bounds.insert(648                    ty::ClauseKind::TypeOutlives(ty::OutlivesClause(ty_param, region_param))649                        .upcast(tcx),650                );651            }652        }653654        // For each region argument (e.g., `'a` in our example), also check for a655        // relationship to the other region arguments. If there is an outlives656        // relationship, then we want to ensure that is reflected in the where clause657        // on the GAT itself.658        for (region_b, region_b_idx) in &regions {659            // Again, skip `'static` because it outlives everything. Also, we trivially660            // know that a region outlives itself. Also ignore `ReError`, to avoid661            // knock-down errors.662            if matches!(region_b.kind(), ty::ReStatic | ty::ReError(_)) || region_a == region_b {663                continue;664            }665            if region_known_to_outlive(tcx, item_def_id, param_env, wf_tys, *region_a, *region_b) {666                debug!(?region_a_idx, ?region_b_idx);667                debug!("required clause: {region_a} must outlive {region_b}");668                // Translate into the generic parameters of the GAT.669                let region_a_param = gat_generics.param_at(*region_a_idx, tcx);670                let region_a_param = ty::Region::new_early_param(671                    tcx,672                    ty::EarlyParamRegion { index: region_a_param.index, name: region_a_param.name },673                );674                // Same for the region.675                let region_b_param = gat_generics.param_at(*region_b_idx, tcx);676                let region_b_param = ty::Region::new_early_param(677                    tcx,678                    ty::EarlyParamRegion { index: region_b_param.index, name: region_b_param.name },679                );680                // The clause we expect to see.681                bounds.insert(682                    ty::ClauseKind::RegionOutlives(ty::OutlivesClause(683                        region_a_param,684                        region_b_param,685                    ))686                    .upcast(tcx),687                );688            }689        }690    }691692    Some(bounds)693}694695/// TypeVisitor that looks for uses of GATs like696/// `<P0 as Trait<P1..Pn>>::GAT<Pn..Pm>` and adds the arguments `P0..Pm` into697/// the two vectors, `regions` and `types` (depending on their kind). For each698/// parameter `Pi` also track the index `i`.699struct GATArgsCollector<'tcx> {700    gat: DefId,701    // Which region appears and which parameter index its instantiated with702    regions: FxIndexSet<(ty::Region<'tcx>, usize)>,703    // Which params appears and which parameter index its instantiated with704    types: FxIndexSet<(Ty<'tcx>, usize)>,705}706707impl<'tcx> GATArgsCollector<'tcx> {708    fn visit<T: TypeFoldable<TyCtxt<'tcx>>>(709        gat: DefId,710        t: T,711    ) -> (FxIndexSet<(ty::Region<'tcx>, usize)>, FxIndexSet<(Ty<'tcx>, usize)>) {712        let mut visitor =713            GATArgsCollector { gat, regions: FxIndexSet::default(), types: FxIndexSet::default() };714        t.visit_with(&mut visitor);715        (visitor.regions, visitor.types)716    }717}718719impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for GATArgsCollector<'tcx> {720    fn visit_ty(&mut self, t: Ty<'tcx>) {721        match t.kind() {722            &ty::Alias(_, ty::AliasTy { kind: ty::Projection { def_id }, args, .. })723                if def_id == self.gat =>724            {725                for (idx, arg) in args.iter().enumerate() {726                    match arg.kind() {727                        GenericArgKind::Lifetime(lt) if !lt.is_bound() => {728                            self.regions.insert((lt, idx));729                        }730                        GenericArgKind::Type(t) => {731                            self.types.insert((t, idx));732                        }733                        _ => {}734                    }735                }736            }737            _ => {}738        }739        t.super_visit_with(self)740    }741}742743fn lint_item_shadowing_supertrait_item<'tcx>(tcx: TyCtxt<'tcx>, trait_item_def_id: LocalDefId) {744    let item_name = tcx.item_name(trait_item_def_id.to_def_id());745    let trait_def_id = tcx.local_parent(trait_item_def_id);746747    let shadowed: Vec<_> = traits::supertrait_def_ids(tcx, trait_def_id.to_def_id())748        .skip(1)749        .flat_map(|supertrait_def_id| {750            tcx.associated_items(supertrait_def_id).filter_by_name_unhygienic(item_name)751        })752        .collect();753    if !shadowed.is_empty() {754        let shadowee = if let [shadowed] = shadowed[..] {755            diagnostics::SupertraitItemShadowee::Labeled {756                span: tcx.def_span(shadowed.def_id),757                supertrait: tcx.item_name(shadowed.trait_container(tcx).unwrap()),758            }759        } else {760            let (traits, spans): (Vec<_>, Vec<_>) = shadowed761                .iter()762                .map(|item| {763                    (tcx.item_name(item.trait_container(tcx).unwrap()), tcx.def_span(item.def_id))764                })765                .unzip();766            diagnostics::SupertraitItemShadowee::Several {767                traits: traits.into(),768                spans: spans.into(),769            }770        };771772        tcx.emit_node_span_lint(773            SHADOWING_SUPERTRAIT_ITEMS,774            tcx.local_def_id_to_hir_id(trait_item_def_id),775            tcx.def_span(trait_item_def_id),776            diagnostics::SupertraitItemShadowing {777                item: item_name,778                subtrait: tcx.item_name(trait_def_id.to_def_id()),779                shadowee,780            },781        );782    }783}784785fn check_param_wf(tcx: TyCtxt<'_>, param: &ty::GenericParamDef) -> Result<(), ErrorGuaranteed> {786    match param.kind {787        // We currently only check wf of const params here.788        ty::GenericParamDefKind::Lifetime | ty::GenericParamDefKind::Type { .. } => Ok(()),789790        // Const parameters are well formed if their type is structural match.791        ty::GenericParamDefKind::Const { .. } => {792            let ty = tcx.type_of(param.def_id).instantiate_identity().skip_norm_wip();793            let span = tcx.def_span(param.def_id);794            let def_id = param.def_id.expect_local();795796            if tcx.features().const_param_ty_unchecked() {797                enter_wf_checking_ctxt(tcx, tcx.local_parent(def_id), |wfcx| {798                    wfcx.register_wf_obligation(span, None, ty.into());799                    Ok(())800                })801            } else if tcx.features().adt_const_params() || tcx.features().min_adt_const_params() {802                enter_wf_checking_ctxt(tcx, tcx.local_parent(def_id), |wfcx| {803                    wfcx.register_bound(804                        ObligationCause::new(span, def_id, ObligationCauseCode::ConstParam(ty)),805                        wfcx.param_env,806                        ty,807                        tcx.require_lang_item(LangItem::ConstParamTy, span),808                    );809                    Ok(())810                })811            } else {812                let span = || {813                    let hir::GenericParamKind::Const { ty: &hir::Ty { span, .. }, .. } =814                        tcx.hir_node_by_def_id(def_id).expect_generic_param().kind815                    else {816                        bug!()817                    };818                    span819                };820                let mut diag = match ty.kind() {821                    ty::Bool | ty::Char | ty::Int(_) | ty::Uint(_) | ty::Error(_) => return Ok(()),822                    ty::FnPtr(..) => tcx.dcx().struct_span_err(823                        span(),824                        "using function pointers as const generic parameters is forbidden",825                    ),826                    ty::RawPtr(_, _) => tcx.dcx().struct_span_err(827                        span(),828                        "using raw pointers as const generic parameters is forbidden",829                    ),830                    _ => {831                        // Avoid showing "{type error}" to users. See #118179.832                        ty.error_reported()?;833834                        tcx.dcx().struct_span_err(835                            span(),836                            format!(837                                "`{ty}` is forbidden as the type of a const generic parameter",838                            ),839                        )840                    }841                };842843                diag.note("the only supported types are integers, `bool`, and `char`");844845                let cause = ObligationCause::misc(span(), def_id);846                let adt_const_params_feature_string =847                    " more complex and user defined types".to_string();848                let may_suggest_feature = match type_allowed_to_implement_const_param_ty(849                    tcx,850                    tcx.param_env(param.def_id),851                    ty,852                    cause,853                ) {854                    // Can never implement `ConstParamTy`, don't suggest anything.855                    Err(856                        ConstParamTyImplementationError::NotAnAdtOrBuiltinAllowed857                        | ConstParamTyImplementationError::NonExhaustive(..)858                        | ConstParamTyImplementationError::InvalidInnerTyOfBuiltinTy(..),859                    ) => None,860                    Err(ConstParamTyImplementationError::UnsizedConstParamsFeatureRequired) => {861                        Some(vec![862                            (adt_const_params_feature_string, sym::min_adt_const_params),863                            (864                                " references to implement the `ConstParamTy` trait".into(),865                                sym::unsized_const_params,866                            ),867                        ])868                    }869                    // May be able to implement `ConstParamTy`. Only emit the feature help870                    // if the type is local, since the user may be able to fix the local type.871                    Err(ConstParamTyImplementationError::InfrigingFields(..)) => {872                        fn ty_is_local(ty: Ty<'_>) -> bool {873                            match ty.kind() {874                                ty::Adt(adt_def, ..) => adt_def.did().is_local(),875                                // Arrays and slices use the inner type's `ConstParamTy`.876                                ty::Array(ty, ..) | ty::Slice(ty) => ty_is_local(*ty),877                                // `&` references use the inner type's `ConstParamTy`.878                                // `&mut` are not supported.879                                ty::Ref(_, ty, ast::Mutability::Not) => ty_is_local(*ty),880                                // Say that a tuple is local if any of its components are local.881                                // This is not strictly correct, but it's likely that the user can fix the local component.882                                ty::Tuple(tys) => tys.iter().any(|ty| ty_is_local(ty)),883                                _ => false,884                            }885                        }886887                        ty_is_local(ty).then_some(vec![(888                            adt_const_params_feature_string,889                            sym::min_adt_const_params,890                        )])891                    }892                    // Implements `ConstParamTy`, suggest adding the feature to enable.893                    Ok(..) => {894                        Some(vec![(adt_const_params_feature_string, sym::min_adt_const_params)])895                    }896                };897                if let Some(features) = may_suggest_feature {898                    tcx.disabled_nightly_features(&mut diag, features);899                }900901                Err(diag.emit())902            }903        }904    }905}906907#[instrument(level = "debug", skip(tcx))]908pub(crate) fn check_associated_item(909    tcx: TyCtxt<'_>,910    def_id: LocalDefId,911) -> Result<(), ErrorGuaranteed> {912    let loc = Some(WellFormedLoc::Ty(def_id));913    enter_wf_checking_ctxt(tcx, def_id, |wfcx| {914        let item = tcx.associated_item(def_id);915916        // Avoid bogus "type annotations needed `Foo: Bar`" errors on `impl Bar for Foo` in case917        // other `Foo` impls are incoherent.918        tcx.ensure_result().coherent_trait(tcx.parent(item.trait_item_or_self()?))?;919920        let self_ty = match item.container {921            ty::AssocContainer::Trait => tcx.types.self_param,922            ty::AssocContainer::InherentImpl | ty::AssocContainer::TraitImpl(_) => {923                tcx.type_of(item.container_id(tcx)).instantiate_identity().skip_norm_wip()924            }925        };926927        let span = tcx.def_span(def_id);928929        match item.kind {930            ty::AssocKind::Const { .. } => {931                let ty = tcx.type_of(def_id).instantiate_identity();932                let ty = wfcx.deeply_normalize(span, Some(WellFormedLoc::Ty(def_id)), ty);933                wfcx.register_wf_obligation(span, loc, ty.into());934935                let has_value = item.defaultness(tcx).has_value();936                if tcx.is_type_const(def_id) {937                    check_type_const(wfcx, def_id, ty, has_value)?;938                }939940                if has_value {941                    let code = ObligationCauseCode::SizedConstOrStatic;942                    wfcx.register_bound(943                        ObligationCause::new(span, def_id, code),944                        wfcx.param_env,945                        ty,946                        tcx.require_lang_item(LangItem::Sized, span),947                    );948                }949950                Ok(())951            }952            ty::AssocKind::Fn { .. } => {953                let sig = tcx.fn_sig(def_id).instantiate_identity().skip_norm_wip();954                let hir_sig =955                    tcx.hir_node_by_def_id(def_id).fn_sig().expect("bad signature for method");956                check_fn_or_method(wfcx, sig, hir_sig.decl, def_id);957                check_method_receiver(wfcx, hir_sig, item, self_ty)958            }959            ty::AssocKind::Type { .. } => {960                if let ty::AssocContainer::Trait = item.container {961                    check_associated_type_bounds(wfcx, item, span)962                }963                if item.defaultness(tcx).has_value() {964                    let ty = tcx.type_of(def_id).instantiate_identity();965                    let ty = wfcx.deeply_normalize(span, Some(WellFormedLoc::Ty(def_id)), ty);966                    wfcx.register_wf_obligation(span, loc, ty.into());967                }968                Ok(())969            }970        }971    })972}973974/// In a type definition, we check that to ensure that the types of the fields are well-formed.975pub(crate) fn check_type_defn<'tcx>(976    tcx: TyCtxt<'tcx>,977    item: LocalDefId,978    all_sized: bool,979) -> Result<(), ErrorGuaranteed> {980    tcx.ensure_ok().check_representability(item);981    let adt_def = tcx.adt_def(item);982983    enter_wf_checking_ctxt(tcx, item, |wfcx| {984        let variants = adt_def.variants();985        let packed = adt_def.repr().packed();986987        for variant in variants.iter() {988            // All field types must be well-formed.989            for field in &variant.fields {990                if let Some(def_id) = field.value991                    && let Some(_ty) = tcx.type_of(def_id).no_bound_vars()992                {993                    // FIXME(generic_const_exprs, default_field_values): this is a hack and needs to994                    // be refactored to check the instantiate-ability of the code better.995                    if let Some(def_id) = def_id.as_local()996                        && let DefKind::AnonConst = tcx.def_kind(def_id)997                        && let hir::Node::AnonConst(anon) = tcx.hir_node_by_def_id(def_id)998                        && let expr = &tcx.hir_body(anon.body).value999                        && let hir::ExprKind::Path(hir::QPath::Resolved(None, path)) = expr.kind1000                        && let Res::Def(DefKind::ConstParam, _def_id) = path.res1001                    {1002                        // Do not evaluate bare `const` params, as those would ICE and are only1003                        // usable if `#![feature(generic_const_exprs)]` is enabled.1004                    } else {1005                        // Evaluate the constant proactively, to emit an error if the constant has1006                        // an unconditional error. We only do so if the const has no type params.1007                        let _ = tcx.const_eval_poly(def_id);1008                    }1009                }1010                let field_id = field.did.expect_local();1011                let span = tcx.ty_span(field_id);1012                let ty = wfcx.deeply_normalize(1013                    span,1014                    None,1015                    tcx.type_of(field.did).instantiate_identity(),1016                );1017                wfcx.register_wf_obligation(span, Some(WellFormedLoc::Ty(field_id)), ty.into());10181019                if matches!(ty.kind(), ty::Adt(def, _) if def.repr().scalable())1020                    && !matches!(adt_def.repr().scalable, Some(ScalableElt::Container))1021                {1022                    // Scalable vectors can only be fields of structs if the type has a1023                    // `rustc_scalable_vector` attribute w/out specifying an element count1024                    tcx.dcx().span_err(1025                        span,1026                        format!(1027                            "scalable vectors cannot be fields of a {}",1028                            adt_def.variant_descr()1029                        ),1030                    );1031                }1032            }10331034            // For DST, or when drop needs to copy things around, all1035            // intermediate types must be sized.1036            let needs_drop_copy = || {1037                packed && {1038                    let ty = tcx.type_of(variant.tail().did).instantiate_identity().skip_norm_wip();1039                    let ty = tcx.erase_and_anonymize_regions(ty);1040                    assert!(!ty.has_infer());1041                    ty.needs_drop(tcx, wfcx.infcx.typing_env(wfcx.param_env))1042                }1043            };1044            // All fields (except for possibly the last) should be sized.1045            let all_sized = all_sized || variant.fields.is_empty() || needs_drop_copy();1046            let unsized_len = if all_sized { 0 } else { 1 };1047            for (idx, field) in1048                variant.fields.raw[..variant.fields.len() - unsized_len].iter().enumerate()1049            {1050                let last = idx == variant.fields.len() - 1;1051                let span = tcx.ty_span(field.did.expect_local());1052                let ty = wfcx.normalize(span, None, tcx.type_of(field.did).instantiate_identity());1053                wfcx.register_bound(1054                    traits::ObligationCause::new(1055                        span,1056                        wfcx.body_def_id,1057                        ObligationCauseCode::FieldSized {1058                            adt_kind: adt_def.adt_kind(),1059                            span,1060                            last,1061                        },1062                    ),1063                    wfcx.param_env,1064                    ty,1065                    tcx.require_lang_item(LangItem::Sized, span),1066                );1067            }10681069            // Explicit `enum` discriminant values must const-evaluate successfully.1070            if let ty::VariantDiscr::Explicit(discr_def_id) = variant.discr {1071                match tcx.const_eval_poly(discr_def_id) {1072                    Ok(_) => {}1073                    Err(ErrorHandled::Reported(..)) => {}1074                    Err(ErrorHandled::TooGeneric(sp)) => {1075                        span_bug!(sp, "enum variant discr was too generic to eval")1076                    }1077                }1078            }1079        }10801081        check_where_clauses(wfcx, item);1082        Ok(())1083    })1084}10851086#[instrument(skip(tcx))]1087pub(crate) fn check_trait(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Result<(), ErrorGuaranteed> {1088    if tcx.is_lang_item(def_id.into(), LangItem::PointeeSized) {1089        // `PointeeSized` is removed during lowering.1090        return Ok(());1091    }10921093    let trait_def = tcx.trait_def(def_id);1094    if trait_def.is_marker1095        || matches!(trait_def.specialization_kind, TraitSpecializationKind::Marker)1096    {1097        for associated_def_id in &*tcx.associated_item_def_ids(def_id) {1098            struct_span_code_err!(1099                tcx.dcx(),1100                tcx.def_span(*associated_def_id),1101                E0714,1102                "marker traits cannot have associated items",1103            )1104            .emit();1105        }1106    }11071108    let res = enter_wf_checking_ctxt(tcx, def_id, |wfcx| {1109        check_where_clauses(wfcx, def_id);1110        Ok(())1111    });11121113    res1114}11151116/// Checks all associated type defaults of trait `trait_def_id`.1117///1118/// Assuming the defaults are used, check that all predicates (bounds on the1119/// assoc type and where clauses on the trait) hold.1120fn check_associated_type_bounds(wfcx: &WfCheckingCtxt<'_, '_>, item: ty::AssocItem, _span: Span) {1121    let bounds = wfcx.tcx().explicit_item_bounds(item.def_id);11221123    debug!("check_associated_type_bounds: bounds={:?}", bounds);1124    let wf_obligations = bounds.iter_identity_copied().map(Unnormalized::skip_norm_wip).flat_map(1125        |(bound, bound_span)| {1126            traits::wf::clause_obligations(1127                wfcx.infcx,1128                wfcx.param_env,1129                wfcx.body_def_id,1130                bound,1131                bound_span,1132            )1133        },1134    );11351136    wfcx.register_obligations(wf_obligations);1137}11381139fn check_item_fn(1140    tcx: TyCtxt<'_>,1141    def_id: LocalDefId,1142    decl: &hir::FnDecl<'_>,1143) -> Result<(), ErrorGuaranteed> {1144    enter_wf_checking_ctxt(tcx, def_id, |wfcx| {1145        check_eiis_fn(tcx, def_id);11461147        let sig = tcx.fn_sig(def_id).instantiate_identity().skip_norm_wip();1148        check_fn_or_method(wfcx, sig, decl, def_id);1149        Ok(())1150    })1151}11521153fn check_eiis_fn(tcx: TyCtxt<'_>, def_id: LocalDefId) {1154    // does the function have an EiiImpl attribute? that contains the defid of a *macro*1155    // that was used to mark the implementation. This is a two step process.1156    if let Some(EiiImpl { resolution, span, .. }) = find_attr!(tcx, def_id, EiiImpl(i) => &**i) {1157        let (foreign_item, name) = match resolution {1158            EiiImplResolution::Macro(def_id) => {1159                // we expect this macro to have the `EiiMacroFor` attribute, that points to a function1160                // signature that we'd like to compare the function we're currently checking with1161                if let Some(foreign_item) =1162                    find_attr!(tcx, *def_id, EiiDeclaration(EiiDecl {foreign_item: t, ..}) => *t)1163                {1164                    (foreign_item, tcx.item_name(*def_id))1165                } else {1166                    tcx.dcx().span_delayed_bug(*span, "resolved to something that's not an EII");1167                    return;1168                }1169            }1170            EiiImplResolution::Known(def_id) => (*def_id, tcx.item_name(*def_id)),1171            EiiImplResolution::Error(_eg) => return,1172        };11731174        let _ = compare_eii_function_types(tcx, def_id, foreign_item, name, *span);1175    }1176}11771178fn check_eiis_static<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId, ty: Ty<'tcx>) {1179    // does the function have an EiiImpl attribute? that contains the defid of a *macro*1180    // that was used to mark the implementation. This is a two step process.1181    if let Some(EiiImpl { resolution, span, .. }) = find_attr!(tcx, def_id, EiiImpl(i) => &**i) {1182        let (foreign_item, name) = match resolution {1183            EiiImplResolution::Macro(def_id) => {1184                // we expect this macro to have the `EiiMacroFor` attribute, that points to a function1185                // signature that we'd like to compare the function we're currently checking with1186                if let Some(foreign_item) =1187                    find_attr!(tcx, *def_id, EiiDeclaration(EiiDecl {foreign_item: t, ..}) => *t)1188                {1189                    (foreign_item, tcx.item_name(*def_id))1190                } else {1191                    tcx.dcx().span_delayed_bug(*span, "resolved to something that's not an EII");1192                    return;1193                }1194            }1195            EiiImplResolution::Known(def_id) => (*def_id, tcx.item_name(*def_id)),1196            EiiImplResolution::Error(_eg) => return,1197        };11981199        let _ = compare_eii_statics(tcx, def_id, ty, foreign_item, name, *span);1200    }1201}12021203#[instrument(level = "debug", skip(tcx))]1204pub(crate) fn check_static_item<'tcx>(1205    tcx: TyCtxt<'tcx>,1206    item_id: LocalDefId,1207    ty: Ty<'tcx>,1208    should_check_for_sync: bool,1209) -> Result<(), ErrorGuaranteed> {1210    enter_wf_checking_ctxt(tcx, item_id, |wfcx| {1211        if should_check_for_sync {1212            check_eiis_static(tcx, item_id, ty);1213        }12141215        let span = tcx.ty_span(item_id);1216        let loc = Some(WellFormedLoc::Ty(item_id));1217        let item_ty = wfcx.deeply_normalize(span, loc, Unnormalized::new_wip(ty));12181219        let is_foreign_item = tcx.is_foreign_item(item_id);1220        let is_structurally_foreign_item = || {1221            let tail = tcx.struct_tail_raw(1222                item_ty,1223                &ObligationCause::dummy(),1224                |ty| wfcx.deeply_normalize(span, loc, ty),1225                || {},1226            );12271228            matches!(tail.kind(), ty::Foreign(_))1229        };1230        let forbid_unsized = !(is_foreign_item && is_structurally_foreign_item());12311232        wfcx.register_wf_obligation(span, Some(WellFormedLoc::Ty(item_id)), item_ty.into());1233        if forbid_unsized {1234            let span = tcx.def_span(item_id);1235            wfcx.register_bound(1236                traits::ObligationCause::new(1237                    span,1238                    wfcx.body_def_id,1239                    ObligationCauseCode::SizedConstOrStatic,1240                ),1241                wfcx.param_env,1242                item_ty,1243                tcx.require_lang_item(LangItem::Sized, span),1244            );1245        }12461247        // Ensure that the end result is `Sync` in a non-thread local `static`.1248        let should_check_for_sync = should_check_for_sync1249            && !is_foreign_item1250            && tcx.static_mutability(item_id.to_def_id()) == Some(hir::Mutability::Not)1251            && !tcx.is_thread_local_static(item_id.to_def_id());12521253        if should_check_for_sync {1254            wfcx.register_bound(1255                traits::ObligationCause::new(1256                    span,1257                    wfcx.body_def_id,1258                    ObligationCauseCode::SharedStatic,1259                ),1260                wfcx.param_env,1261                item_ty,1262                tcx.require_lang_item(LangItem::Sync, span),1263            );1264        }1265        Ok(())1266    })1267}12681269#[instrument(level = "debug", skip(wfcx))]1270pub(super) fn check_type_const<'tcx>(1271    wfcx: &WfCheckingCtxt<'_, 'tcx>,1272    def_id: LocalDefId,1273    item_ty: Ty<'tcx>,1274    has_value: bool,1275) -> Result<(), ErrorGuaranteed> {1276    let tcx = wfcx.tcx();1277    let span = tcx.def_span(def_id);12781279    if !tcx.features().const_param_ty_unchecked() {1280        wfcx.register_bound(1281            ObligationCause::new(span, def_id, ObligationCauseCode::ConstParam(item_ty)),1282            wfcx.param_env,1283            item_ty,1284            tcx.require_lang_item(LangItem::ConstParamTy, span),1285        );1286    }12871288    if has_value {1289        let raw_ct = tcx.const_of_item(def_id).instantiate_identity();1290        let norm_ct = wfcx.deeply_normalize(span, Some(WellFormedLoc::Ty(def_id)), raw_ct);1291        wfcx.register_wf_obligation(span, Some(WellFormedLoc::Ty(def_id)), norm_ct.into());12921293        wfcx.register_obligation(Obligation::new(1294            tcx,1295            ObligationCause::new(span, def_id, ObligationCauseCode::WellFormed(None)),1296            wfcx.param_env,1297            ty::PredicateKind::Clause(ty::ClauseKind::ConstArgHasType(norm_ct, item_ty)),1298        ));1299    }1300    Ok(())1301}13021303#[instrument(level = "debug", skip(tcx, impl_))]1304fn check_impl<'tcx>(1305    tcx: TyCtxt<'tcx>,1306    item: &'tcx hir::Item<'tcx>,1307    impl_: &hir::Impl<'_>,1308) -> Result<(), ErrorGuaranteed> {1309    enter_wf_checking_ctxt(tcx, item.owner_id.def_id, |wfcx| {1310        match impl_.of_trait {1311            Some(of_trait) => {1312                // `#[rustc_reservation_impl]` impls are not real impls and1313                // therefore don't need to be WF (the trait's `Self: Trait` predicate1314                // won't hold).1315                let trait_ref = tcx.impl_trait_ref(item.owner_id).instantiate_identity();1316                // Avoid bogus "type annotations needed `Foo: Bar`" errors on `impl Bar for Foo` in1317                // case other `Foo` impls are incoherent.1318                tcx.ensure_result().coherent_trait(trait_ref.skip_normalization().def_id)?;1319                let trait_span = of_trait.trait_ref.path.span;1320                let trait_ref = wfcx.deeply_normalize(1321                    trait_span,1322                    Some(WellFormedLoc::Ty(item.hir_id().expect_owner().def_id)),1323                    trait_ref,1324                );1325                let trait_pred =1326                    ty::TraitClause { trait_ref, polarity: ty::ClausePolarity::Positive };1327                let mut obligations = traits::wf::trait_obligations(1328                    wfcx.infcx,1329                    wfcx.param_env,1330                    wfcx.body_def_id,1331                    trait_pred,1332                    trait_span,1333                    item,1334                );1335                for obligation in &mut obligations {1336                    if obligation.cause.span != trait_span {1337                        // We already have a better span.1338                        continue;1339                    }1340                    if let Some(pred) = obligation.predicate.as_trait_clause()1341                        && pred.skip_binder().self_ty() == trait_ref.self_ty()1342                    {1343                        obligation.cause.span = impl_.self_ty.span;1344                    }1345                    if let Some(pred) = obligation.predicate.as_projection_clause()1346                        && pred.skip_binder().self_ty() == trait_ref.self_ty()1347                    {1348                        obligation.cause.span = impl_.self_ty.span;1349                    }1350                }13511352                // Ensure that the `[const]` where clauses of the trait hold for the impl.1353                if tcx.is_conditionally_const(item.owner_id.def_id) {1354                    for (bound, _) in1355                        tcx.const_conditions(trait_ref.def_id).instantiate(tcx, trait_ref.args)1356                    {1357                        let bound = wfcx.normalize(1358                            item.span,1359                            Some(WellFormedLoc::Ty(item.hir_id().expect_owner().def_id)),1360                            bound,1361                        );1362                        wfcx.register_obligation(Obligation::new(1363                            tcx,1364                            ObligationCause::new(1365                                impl_.self_ty.span,1366                                wfcx.body_def_id,1367                                ObligationCauseCode::WellFormed(None),1368                            ),1369                            wfcx.param_env,1370                            bound.to_host_effect_clause(tcx, ty::BoundConstness::Maybe),1371                        ))1372                    }1373                }13741375                debug!(?obligations);1376                wfcx.register_obligations(obligations);1377            }1378            None => {1379                let self_ty = tcx.type_of(item.owner_id).instantiate_identity().skip_norm_wip();1380                let self_ty = wfcx.deeply_normalize(1381                    item.span,1382                    Some(WellFormedLoc::Ty(item.hir_id().expect_owner().def_id)),1383                    Unnormalized::new_wip(self_ty),1384                );1385                wfcx.register_wf_obligation(1386                    impl_.self_ty.span,1387                    Some(WellFormedLoc::Ty(item.hir_id().expect_owner().def_id)),1388                    self_ty.into(),1389                );1390            }1391        }13921393        check_where_clauses(wfcx, item.owner_id.def_id);1394        Ok(())1395    })1396}13971398/// Checks where-clauses and inline bounds that are declared on `def_id`.1399#[instrument(level = "debug", skip(wfcx))]1400pub(super) fn check_where_clauses<'tcx>(wfcx: &WfCheckingCtxt<'_, 'tcx>, def_id: LocalDefId) {1401    let infcx = wfcx.infcx;1402    let tcx = wfcx.tcx();14031404    let gen_clauses = tcx.clauses_of(def_id.to_def_id());1405    let generics = tcx.generics_of(def_id);14061407    // Check that concrete defaults are well-formed. See test `type-check-defaults.rs`.1408    // For example, this forbids the declaration:1409    //1410    //     struct Foo<T = Vec<[u32]>> { .. }1411    //1412    // Here, the default `Vec<[u32]>` is not WF because `[u32]: Sized` does not hold.1413    for param in &generics.own_params {1414        if let Some(default) = param1415            .default_value(tcx)1416            .map(ty::EarlyBinder::instantiate_identity)1417            .map(Unnormalized::skip_norm_wip)1418        {1419            // Ignore dependent defaults -- that is, where the default of one type1420            // parameter includes another (e.g., `<T, U = T>`). In those cases, we can't1421            // be sure if it will error or not as user might always specify the other.1422            // FIXME(generic_const_exprs): This is incorrect when dealing with unused const params.1423            // E.g: `struct Foo<const N: usize, const M: usize = { 1 - 2 }>;`. Here, we should1424            // eagerly error but we don't as we have `ConstKind::Alias(.., [N, M])`.1425            if !default.has_param() {1426                wfcx.register_wf_obligation(1427                    tcx.def_span(param.def_id),1428                    matches!(param.kind, GenericParamDefKind::Type { .. })1429                        .then(|| WellFormedLoc::Ty(param.def_id.expect_local())),1430                    default.as_term().unwrap(),1431                );1432            } else {1433                // If we've got a generic const parameter we still want to check its1434                // type is correct in case both it and the param type are fully concrete.1435                let GenericArgKind::Const(ct) = default.kind() else {1436                    continue;1437                };14381439                let ct_ty = match ct.kind() {1440                    ty::ConstKind::Infer(_)1441                    | ty::ConstKind::Placeholder(_)1442                    | ty::ConstKind::Bound(_, _) => unreachable!(),1443                    ty::ConstKind::Error(_) | ty::ConstKind::Expr(_) => continue,1444                    ty::ConstKind::Value(cv) => cv.ty,1445                    ty::ConstKind::Alias(_, alias_const) => {1446                        alias_const.type_of(infcx.tcx).skip_norm_wip()1447                    }1448                    ty::ConstKind::Param(param_ct) => {1449                        param_ct.find_const_ty_from_env(wfcx.param_env)1450                    }1451                };14521453                let param_ty = tcx.type_of(param.def_id).instantiate_identity().skip_norm_wip();1454                if !ct_ty.has_param() && !param_ty.has_param() {1455                    let cause = traits::ObligationCause::new(1456                        tcx.def_span(param.def_id),1457                        wfcx.body_def_id,1458                        ObligationCauseCode::WellFormed(None),1459                    );1460                    wfcx.register_obligation(Obligation::new(1461                        tcx,1462                        cause,1463                        wfcx.param_env,1464                        ty::ClauseKind::ConstArgHasType(ct, param_ty),1465                    ));1466                }1467            }1468        }1469    }14701471    // Check that trait clauses are WF when params are instantiated with their defaults.1472    // We don't want to overly constrain the clauses that may be written but we want to1473    // catch cases where a default my never be applied such as `struct Foo<T: Copy = String>`.1474    // Therefore we check if a clause which contains a single type param1475    // with a concrete default is WF with that default instantiated.1476    // For more examples see tests `defaults-well-formedness.rs` and `type-check-defaults.rs`.1477    //1478    // First we build the defaulted generic parameters.1479    let args = GenericArgs::for_item(tcx, def_id.to_def_id(), |param, _| {1480        if param.index >= generics.parent_count as u321481            // If the param has a default, ...1482            && let Some(default) = param.default_value(tcx).map(ty::EarlyBinder::instantiate_identity).map(Unnormalized::skip_norm_wip)1483            // ... and it's not a dependent default, ...1484            && !default.has_param()1485        {1486            // ... then instantiate it with the default.1487            return default;1488        }1489        tcx.mk_param_from_def(param)1490    });14911492    // Now we build the instantiated clauses.1493    let default_obligations = gen_clauses1494        .clauses1495        .iter()1496        .flat_map(|&(clause, sp)| {1497            #[derive(Default)]1498            struct CountParams {1499                params: FxHashSet<u32>,1500            }1501            impl<'tcx> ty::TypeVisitor<TyCtxt<'tcx>> for CountParams {1502                type Result = ControlFlow<()>;1503                fn visit_ty(&mut self, t: Ty<'tcx>) -> Self::Result {1504                    if let ty::Param(param) = t.kind() {1505                        self.params.insert(param.index);1506                    }1507                    t.super_visit_with(self)1508                }15091510                fn visit_region(&mut self, _: ty::Region<'tcx>) -> Self::Result {1511                    ControlFlow::Break(())1512                }15131514                fn visit_const(&mut self, c: ty::Const<'tcx>) -> Self::Result {1515                    if let ty::ConstKind::Param(param) = c.kind() {1516                        self.params.insert(param.index);1517                    }1518                    c.super_visit_with(self)1519                }1520            }1521            let mut param_count = CountParams::default();1522            let has_region = clause.visit_with(&mut param_count).is_break();1523            let instantiated_clause = ty::EarlyBinder::bind(tcx, clause).instantiate(tcx, args);1524            // Don't check non-defaulted params, dependent defaults (including lifetimes)1525            // or clauses with multiple params.1526            if instantiated_clause.skip_normalization().has_non_region_param()1527                || param_count.params.len() > 11528                || has_region1529            {1530                None1531            } else if gen_clauses1532                .clauses1533                .iter()1534                .any(|&(p, _)| Unnormalized::new_wip(p) == instantiated_clause)1535            {1536                // Avoid duplication of clauses that contain no parameters, for example.1537                None1538            } else {1539                Some((instantiated_clause, sp))1540            }1541        })1542        .map(|(clause, sp)| {1543            // Convert each of those into an obligation. So if you have1544            // something like `struct Foo<T: Copy = String>`, we would1545            // take that clause `T: Copy`, instantiated with `String: Copy`1546            // (actually that happens in the previous `flat_map` call),1547            // and then try to prove it (in this case, we'll fail).1548            //1549            // Note the subtle difference from how we handle `gen_clauses`1550            // below: there, we are not trying to prove those clauses1551            // to be *true* but merely *well-formed*.1552            let clause = wfcx.normalize(sp, None, clause);1553            let cause = traits::ObligationCause::new(1554                sp,1555                wfcx.body_def_id,1556                ObligationCauseCode::WhereClause(def_id.to_def_id(), sp),1557            );1558            Obligation::new(tcx, cause, wfcx.param_env, clause)1559        });15601561    let gen_clauses = gen_clauses.instantiate_identity(tcx);15621563    let assoc_const_obligations: Vec<_> = gen_clauses1564        .clauses1565        .iter()1566        .copied()1567        .zip(gen_clauses.spans.iter().copied())1568        .filter_map(|(clause, sp)| {1569            let clause = clause.skip_norm_wip();1570            let proj = clause.as_projection_clause()?;1571            let pred_binder = proj1572                .map_bound(|pred| {1573                    pred.term.as_const().map(|ct| {1574                        let assoc_const_ty =1575                            pred.projection_term.expect_ct().type_of(tcx).skip_norm_wip();1576                        ty::ClauseKind::ConstArgHasType(ct, assoc_const_ty)1577                    })1578                })1579                .transpose();1580            pred_binder.map(|pred_binder| {1581                let cause = traits::ObligationCause::new(1582                    sp,1583                    wfcx.body_def_id,1584                    ObligationCauseCode::WhereClause(def_id.to_def_id(), sp),1585                );1586                Obligation::new(tcx, cause, wfcx.param_env, pred_binder)1587            })1588        })1589        .collect();15901591    assert_eq!(gen_clauses.clauses.len(), gen_clauses.spans.len());1592    let wf_obligations = gen_clauses.into_iter().flat_map(|(p, sp)| {1593        traits::wf::clause_obligations(1594            infcx,1595            wfcx.param_env,1596            wfcx.body_def_id,1597            p.skip_norm_wip(),1598            sp,1599        )1600    });1601    let obligations: Vec<_> =1602        wf_obligations.chain(default_obligations).chain(assoc_const_obligations).collect();1603    wfcx.register_obligations(obligations);1604}16051606#[instrument(level = "debug", skip(wfcx, hir_decl))]1607fn check_fn_or_method<'tcx>(1608    wfcx: &WfCheckingCtxt<'_, 'tcx>,1609    sig: ty::PolyFnSig<'tcx>,1610    hir_decl: &hir::FnDecl<'_>,1611    def_id: LocalDefId,1612) {1613    let tcx = wfcx.tcx();1614    let mut sig = tcx.liberate_late_bound_regions(def_id.to_def_id(), sig);16151616    // Normalize the input and output types one at a time, using a different1617    // `WellFormedLoc` for each. We cannot call `normalize_associated_types`1618    // on the entire `FnSig`, since this would use the same `WellFormedLoc`1619    // for each type, preventing the HIR wf check from generating1620    // a nice error message.1621    let arg_span =1622        |idx| hir_decl.inputs.get(idx).map_or(hir_decl.output.span(), |arg: &hir::Ty<'_>| arg.span);16231624    sig.inputs_and_output =1625        tcx.mk_type_list_from_iter(sig.inputs_and_output.iter().enumerate().map(|(idx, ty)| {1626            wfcx.deeply_normalize(1627                arg_span(idx),1628                Some(WellFormedLoc::Param {1629                    function: def_id,1630                    // Note that the `param_idx` of the output type is1631                    // one greater than the index of the last input type.1632                    param_idx: idx,1633                }),1634                Unnormalized::new_wip(ty),1635            )1636        }));16371638    for (idx, ty) in sig.inputs_and_output.iter().enumerate() {1639        wfcx.register_wf_obligation(1640            arg_span(idx),1641            Some(WellFormedLoc::Param { function: def_id, param_idx: idx }),1642            ty.into(),1643        );1644    }16451646    check_where_clauses(wfcx, def_id);16471648    if sig.abi() == ExternAbi::RustCall {1649        let span = tcx.def_span(def_id);1650        let has_implicit_self = hir_decl.implicit_self().has_implicit_self();1651        let mut inputs = sig.inputs().iter().skip(if has_implicit_self { 1 } else { 0 });1652        // Check that the argument is a tuple and is sized1653        if let Some(ty) = inputs.next() {1654            wfcx.register_bound(1655                ObligationCause::new(span, wfcx.body_def_id, ObligationCauseCode::RustCall),1656                wfcx.param_env,1657                *ty,1658                tcx.require_lang_item(LangItem::Tuple, span),1659            );1660            wfcx.register_bound(1661                ObligationCause::new(span, wfcx.body_def_id, ObligationCauseCode::RustCall),1662                wfcx.param_env,1663                *ty,1664                tcx.require_lang_item(LangItem::Sized, span),1665            );1666        } else {1667            tcx.dcx().span_err(1668                hir_decl.inputs.last().map_or(span, |input| input.span),1669                "functions with the \"rust-call\" ABI must take a single non-self tuple argument",1670            );1671        }1672        // No more inputs other than the `self` type and the tuple type1673        if inputs.next().is_some() {1674            tcx.dcx().span_err(1675                hir_decl.inputs.last().map_or(span, |input| input.span),1676                "functions with the \"rust-call\" ABI must take a single non-self tuple argument",1677            );1678        }1679    }16801681    // If the function has a body, additionally require that the return type is sized.1682    if let Some(body) = tcx.hir_maybe_body_owned_by(def_id) {1683        let span = match hir_decl.output {1684            hir::FnRetTy::Return(ty) => ty.span,1685            hir::FnRetTy::DefaultReturn(_) => body.value.span,1686        };16871688        wfcx.register_bound(1689            ObligationCause::new(span, def_id, ObligationCauseCode::SizedReturnType),1690            wfcx.param_env,1691            sig.output(),1692            tcx.require_lang_item(LangItem::Sized, span),1693        );1694    }1695}16961697/// The `arbitrary_self_types_pointers` feature implies `arbitrary_self_types`.1698#[derive(Clone, Copy, PartialEq)]1699enum ArbitrarySelfTypesLevel {1700    Basic,        // just arbitrary_self_types1701    WithPointers, // both arbitrary_self_types and arbitrary_self_types_pointers1702}17031704#[instrument(level = "debug", skip(wfcx))]1705fn check_method_receiver<'tcx>(1706    wfcx: &WfCheckingCtxt<'_, 'tcx>,1707    fn_sig: &hir::FnSig<'_>,1708    method: ty::AssocItem,1709    self_ty: Ty<'tcx>,1710) -> Result<(), ErrorGuaranteed> {1711    let tcx = wfcx.tcx();17121713    if !method.is_method() {1714        return Ok(());1715    }17161717    let span = fn_sig.decl.inputs[0].span;1718    let loc = Some(WellFormedLoc::Param { function: method.def_id.expect_local(), param_idx: 0 });17191720    let sig = tcx.fn_sig(method.def_id).instantiate_identity().skip_norm_wip();1721    let sig = tcx.liberate_late_bound_regions(method.def_id, sig);1722    let sig = wfcx.normalize(DUMMY_SP, loc, Unnormalized::new_wip(sig));17231724    debug!("check_method_receiver: sig={:?}", sig);17251726    let self_ty = wfcx.normalize(DUMMY_SP, loc, Unnormalized::new_wip(self_ty));17271728    let receiver_ty = sig.inputs()[0];1729    let receiver_ty = wfcx.normalize(DUMMY_SP, loc, Unnormalized::new_wip(receiver_ty));17301731    // If the receiver already has errors reported, consider it valid to avoid1732    // unnecessary errors (#58712).1733    receiver_ty.error_reported()?;17341735    let arbitrary_self_types_level = if tcx.features().arbitrary_self_types_pointers() {1736        Some(ArbitrarySelfTypesLevel::WithPointers)1737    } else if tcx.features().arbitrary_self_types() {1738        Some(ArbitrarySelfTypesLevel::Basic)1739    } else {1740        None1741    };1742    let generics = tcx.generics_of(method.def_id);17431744    let receiver_validity =1745        receiver_is_valid(wfcx, span, receiver_ty, self_ty, arbitrary_self_types_level, generics);1746    if let Err(receiver_validity_err) = receiver_validity {1747        return Err(match arbitrary_self_types_level {1748            // Wherever possible, emit a message advising folks that the features1749            // `arbitrary_self_types` or `arbitrary_self_types_pointers` might1750            // have helped.1751            None if receiver_is_valid(1752                wfcx,1753                span,1754                receiver_ty,1755                self_ty,1756                Some(ArbitrarySelfTypesLevel::Basic),1757                generics,1758            )1759            .is_ok() =>1760            {1761                // Report error; would have worked with `arbitrary_self_types`.1762                feature_err(1763                    &tcx.sess,1764                    sym::arbitrary_self_types,1765                    span,1766                    format!(1767                        "`{receiver_ty}` cannot be used as the type of `self` without \1768                            the `arbitrary_self_types` feature",1769                    ),1770                )1771                .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>`"))1772                .emit()1773            }1774            None | Some(ArbitrarySelfTypesLevel::Basic)1775                if receiver_is_valid(1776                    wfcx,1777                    span,1778                    receiver_ty,1779                    self_ty,1780                    Some(ArbitrarySelfTypesLevel::WithPointers),1781                    generics,1782                )1783                .is_ok() =>1784            {1785                // Report error; would have worked with `arbitrary_self_types_pointers`.1786                feature_err(1787                    &tcx.sess,1788                    sym::arbitrary_self_types_pointers,1789                    span,1790                    format!(1791                        "`{receiver_ty}` cannot be used as the type of `self` without \1792                            the `arbitrary_self_types_pointers` feature",1793                    ),1794                )1795                .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>`"))1796                .emit()1797            }1798            _ =>1799            // Report error; would not have worked with `arbitrary_self_types[_pointers]`.1800            {1801                match receiver_validity_err {1802                    ReceiverValidityError::DoesNotDeref if arbitrary_self_types_level.is_some() => {1803                        let adt_def =1804                            receiver_ty.builtin_deref(false).unwrap_or(receiver_ty).ty_adt_def();18051806                        let hint = match adt_def {1807                            Some(adt) => {1808                                if tcx.is_lang_item(adt.did(), LangItem::NonNull) {1809                                    Some(InvalidReceiverTyHint::NonNull)1810                                } else {1811                                    match tcx.get_diagnostic_name(adt.did()) {1812                                        Some(sym::RcWeak | sym::ArcWeak) => {1813                                            Some(InvalidReceiverTyHint::Weak)1814                                        }1815                                        _ => None,1816                                    }1817                                }1818                            }1819                            _ => None,1820                        };18211822                        tcx.dcx().emit_err(diagnostics::InvalidReceiverTy {1823                            span,1824                            receiver_ty,1825                            hint,1826                        })1827                    }1828                    ReceiverValidityError::DoesNotDeref => {1829                        tcx.dcx().emit_err(diagnostics::InvalidReceiverTyNoArbitrarySelfTypes {1830                            span,1831                            receiver_ty,1832                        })1833                    }1834                    ReceiverValidityError::MethodGenericParamUsed => tcx1835                        .dcx()1836                        .emit_err(diagnostics::InvalidGenericReceiverTy { span, receiver_ty }),1837                }1838            }1839        });1840    }1841    Ok(())1842}18431844/// Error cases which may be returned from `receiver_is_valid`. These error1845/// cases are generated in this function as they may be unearthed as we explore1846/// the `autoderef` chain, but they're converted to diagnostics in the caller.1847enum ReceiverValidityError {1848    /// The self type does not get to the receiver type by following the1849    /// autoderef chain.1850    DoesNotDeref,1851    /// A type was found which is a method type parameter, and that's not allowed.1852    MethodGenericParamUsed,1853}18541855/// Confirms that a type is not a type parameter referring to one of the1856/// method's type params.1857fn confirm_type_is_not_a_method_generic_param(1858    ty: Ty<'_>,1859    method_generics: &ty::Generics,1860) -> Result<(), ReceiverValidityError> {1861    if let ty::Param(param) = ty.kind() {1862        if (param.index as usize) >= method_generics.parent_count {1863            return Err(ReceiverValidityError::MethodGenericParamUsed);1864        }1865    }1866    Ok(())1867}18681869/// Returns whether `receiver_ty` would be considered a valid receiver type for `self_ty`. If1870/// `arbitrary_self_types` is enabled, `receiver_ty` must transitively deref to `self_ty`, possibly1871/// through a `*const/mut T` raw pointer if  `arbitrary_self_types_pointers` is also enabled.1872/// If neither feature is enabled, the requirements are more strict: `receiver_ty` must implement1873/// `Receiver` and directly implement `Deref<Target = self_ty>`.1874///1875/// N.B., there are cases this function returns `true` but causes an error to be emitted,1876/// particularly when `receiver_ty` derefs to a type that is the same as `self_ty` but has the1877/// wrong lifetime. Be careful of this if you are calling this function speculatively.1878fn receiver_is_valid<'tcx>(1879    wfcx: &WfCheckingCtxt<'_, 'tcx>,1880    span: Span,1881    receiver_ty: Ty<'tcx>,1882    self_ty: Ty<'tcx>,1883    arbitrary_self_types_enabled: Option<ArbitrarySelfTypesLevel>,1884    method_generics: &ty::Generics,1885) -> Result<(), ReceiverValidityError> {1886    let infcx = wfcx.infcx;1887    let tcx = wfcx.tcx();1888    let cause =1889        ObligationCause::new(span, wfcx.body_def_id, traits::ObligationCauseCode::MethodReceiver);18901891    // Special case `receiver == self_ty`, which doesn't necessarily require the `Receiver` lang item.1892    if let Ok(()) = wfcx.infcx.commit_if_ok(|_| {1893        let ocx = ObligationCtxt::new(wfcx.infcx);1894        ocx.eq(&cause, wfcx.param_env, self_ty, receiver_ty)?;1895        if ocx.evaluate_obligations_error_on_ambiguity().no_errors() {1896            Ok(())1897        } else {1898            Err(NoSolution)1899        }1900    }) {1901        return Ok(());1902    }19031904    confirm_type_is_not_a_method_generic_param(receiver_ty, method_generics)?;19051906    let mut autoderef = Autoderef::new(infcx, wfcx.param_env, wfcx.body_def_id, span, receiver_ty);19071908    // The `arbitrary_self_types` feature allows custom smart pointer1909    // types to be method receivers, as identified by following the Receiver<Target=T>1910    // chain.1911    if arbitrary_self_types_enabled.is_some() {1912        autoderef = autoderef.use_receiver_trait();1913    }19141915    // The `arbitrary_self_types_pointers` feature allows raw pointer receivers like `self: *const Self`.1916    if arbitrary_self_types_enabled == Some(ArbitrarySelfTypesLevel::WithPointers) {1917        autoderef = autoderef.include_raw_pointers();1918    }19191920    // Keep dereferencing `receiver_ty` until we get to `self_ty`.1921    while let Some((potential_self_ty, _)) = autoderef.next() {1922        debug!(1923            "receiver_is_valid: potential self type `{:?}` to match `{:?}`",1924            potential_self_ty, self_ty1925        );19261927        confirm_type_is_not_a_method_generic_param(potential_self_ty, method_generics)?;19281929        // Check if the self type unifies. If it does, then commit the result1930        // since it may have region side-effects.1931        if let Ok(()) = wfcx.infcx.commit_if_ok(|_| {1932            let ocx = ObligationCtxt::new(wfcx.infcx);1933            ocx.eq(&cause, wfcx.param_env, self_ty, potential_self_ty)?;1934            if ocx.evaluate_obligations_error_on_ambiguity().no_errors() {1935                Ok(())1936            } else {1937                Err(NoSolution)1938            }1939        }) {1940            wfcx.register_obligations(autoderef.into_obligations());1941            return Ok(());1942        }19431944        // Without `feature(arbitrary_self_types)`, we require that each step in the1945        // deref chain implement `LegacyReceiver`.1946        if arbitrary_self_types_enabled.is_none() {1947            let legacy_receiver_trait_def_id =1948                tcx.require_lang_item(LangItem::LegacyReceiver, span);1949            if !legacy_receiver_is_implemented(1950                wfcx,1951                legacy_receiver_trait_def_id,1952                cause.clone(),1953                potential_self_ty,1954            ) {1955                // We cannot proceed.1956                break;1957            }19581959            // Register the bound, in case it has any region side-effects.1960            wfcx.register_bound(1961                cause.clone(),1962                wfcx.param_env,1963                potential_self_ty,1964                legacy_receiver_trait_def_id,1965            );1966        }1967    }19681969    debug!("receiver_is_valid: type `{:?}` does not deref to `{:?}`", receiver_ty, self_ty);1970    Err(ReceiverValidityError::DoesNotDeref)1971}19721973fn legacy_receiver_is_implemented<'tcx>(1974    wfcx: &WfCheckingCtxt<'_, 'tcx>,1975    legacy_receiver_trait_def_id: DefId,1976    cause: ObligationCause<'tcx>,1977    receiver_ty: Ty<'tcx>,1978) -> bool {1979    let tcx = wfcx.tcx();1980    let trait_ref = ty::TraitRef::new(tcx, legacy_receiver_trait_def_id, [receiver_ty]);19811982    let obligation = Obligation::new(tcx, cause, wfcx.param_env, trait_ref);19831984    if wfcx.infcx.predicate_must_hold_modulo_regions(&obligation) {1985        true1986    } else {1987        debug!(1988            "receiver_is_implemented: type `{:?}` does not implement `LegacyReceiver` trait",1989            receiver_ty1990        );1991        false1992    }1993}19941995pub(super) fn check_variances_for_type_defn<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId) {1996    match tcx.def_kind(def_id) {1997        DefKind::Enum | DefKind::Struct | DefKind::Union => {1998            // Ok1999        }2000        kind => span_bug!(tcx.def_span(def_id), "cannot compute the variances of {kind:?}"),

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.