compiler/rustc_hir_analysis/src/check/wfcheck.rs RUST 2,597 lines View on github.com → Search inside
File is large — showing lines 1–2,000 of 2,597.
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, AdtKind, GenericArgKind, GenericArgs, GenericParamDefKind, Ty, TyCtxt, TypeFlags,26    TypeFoldable, TypeSuperVisitable, TypeVisitable, TypeVisitableExt, TypeVisitor, TypingMode,27    Unnormalized, 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::errors;48use crate::errors::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);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 = infcx_compat.resolve_regions_with_outlives_env(&outlives_env);215    if errors_compat.is_empty() {216        // FIXME: Once we fix bevy, this would be the place to insert a warning217        // to upgrade bevy.218        Ok(())219    } else {220        Err(infcx_compat.err_ctxt().report_region_errors(body_def_id, &errors_compat))221    }222}223224pub(super) fn check_well_formed(225    tcx: TyCtxt<'_>,226    def_id: LocalDefId,227) -> Result<(), ErrorGuaranteed> {228    let mut res = crate::check::check::check_item_type(tcx, def_id);229230    for param in &tcx.generics_of(def_id).own_params {231        res = res.and(check_param_wf(tcx, param));232    }233234    res235}236237/// Checks that the field types (in a struct def'n) or argument types (in an enum def'n) are238/// well-formed, meaning that they do not require any constraints not declared in the struct239/// definition itself. For example, this definition would be illegal:240///241/// ```rust242/// struct StaticRef<T> { x: &'static T }243/// ```244///245/// because the type did not declare that `T: 'static`.246///247/// We do this check as a pre-pass before checking fn bodies because if these constraints are248/// not included it frequently leads to confusing errors in fn bodies. So it's better to check249/// the types first.250#[instrument(skip(tcx), level = "debug")]251pub(super) fn check_item<'tcx>(252    tcx: TyCtxt<'tcx>,253    item: &'tcx hir::Item<'tcx>,254) -> Result<(), ErrorGuaranteed> {255    let def_id = item.owner_id.def_id;256257    debug!(258        ?item.owner_id,259        item.name = ? tcx.def_path_str(def_id)260    );261262    match item.kind {263        // Right now we check that every default trait implementation264        // has an implementation of itself. Basically, a case like:265        //266        //     impl Trait for T {}267        //268        // has a requirement of `T: Trait` which was required for default269        // method implementations. Although this could be improved now that270        // there's a better infrastructure in place for this, it's being left271        // for a follow-up work.272        //273        // Since there's such a requirement, we need to check *just* positive274        // implementations, otherwise things like:275        //276        //     impl !Send for T {}277        //278        // won't be allowed unless there's an *explicit* implementation of `Send`279        // for `T`280        hir::ItemKind::Impl(ref impl_) => {281            crate::impl_wf_check::check_impl_wf(tcx, def_id, impl_.of_trait.is_some())?;282            let mut res = Ok(());283            if let Some(of_trait) = impl_.of_trait {284                let header = tcx.impl_trait_header(def_id);285                let is_auto = tcx.trait_is_auto(header.trait_ref.skip_binder().def_id);286                if let (hir::Defaultness::Default { .. }, true) = (of_trait.defaultness, is_auto) {287                    let sp = of_trait.trait_ref.path.span;288                    res = Err(tcx289                        .dcx()290                        .struct_span_err(sp, "impls of auto traits cannot be default")291                        .with_span_labels(of_trait.defaultness_span, "default because of this")292                        .with_span_label(sp, "auto trait")293                        .emit());294                }295                match header.polarity {296                    ty::ImplPolarity::Positive => {297                        res = res.and(check_impl(tcx, item, impl_));298                    }299                    ty::ImplPolarity::Negative => {300                        let ast::ImplPolarity::Negative(span) = of_trait.polarity else {301                            bug!("impl_polarity query disagrees with impl's polarity in HIR");302                        };303                        // FIXME(#27579): what amount of WF checking do we need for neg impls?304                        if let hir::Defaultness::Default { .. } = of_trait.defaultness {305                            let mut spans = vec![span];306                            spans.extend(of_trait.defaultness_span);307                            res = Err(struct_span_code_err!(308                                tcx.dcx(),309                                spans,310                                E0750,311                                "negative impls cannot be default impls"312                            )313                            .emit());314                        }315                    }316                    ty::ImplPolarity::Reservation => {317                        // FIXME: what amount of WF checking do we need for reservation impls?318                    }319                }320            } else {321                res = res.and(check_impl(tcx, item, impl_));322            }323            res324        }325        hir::ItemKind::Fn { sig, .. } => check_item_fn(tcx, def_id, sig.decl),326        hir::ItemKind::Struct(..) => check_type_defn(tcx, item, false),327        hir::ItemKind::Union(..) => check_type_defn(tcx, item, true),328        hir::ItemKind::Enum(..) => check_type_defn(tcx, item, true),329        hir::ItemKind::Trait { .. } => check_trait(tcx, item),330        hir::ItemKind::TraitAlias(..) => check_trait(tcx, item),331        _ => Ok(()),332    }333}334335pub(super) fn check_foreign_item<'tcx>(336    tcx: TyCtxt<'tcx>,337    item: &'tcx hir::ForeignItem<'tcx>,338) -> Result<(), ErrorGuaranteed> {339    let def_id = item.owner_id.def_id;340341    debug!(342        ?item.owner_id,343        item.name = ? tcx.def_path_str(def_id)344    );345346    match item.kind {347        hir::ForeignItemKind::Fn(sig, ..) => check_item_fn(tcx, def_id, sig.decl),348        hir::ForeignItemKind::Static(..) | hir::ForeignItemKind::Type => Ok(()),349    }350}351352pub(crate) fn check_trait_item<'tcx>(353    tcx: TyCtxt<'tcx>,354    def_id: LocalDefId,355) -> Result<(), ErrorGuaranteed> {356    // Check that an item definition in a subtrait is shadowing a supertrait item.357    lint_item_shadowing_supertrait_item(tcx, def_id);358359    let mut res = Ok(());360361    if tcx.def_kind(def_id) == DefKind::AssocFn {362        for &assoc_ty_def_id in363            tcx.associated_types_for_impl_traits_in_associated_fn(def_id.to_def_id())364        {365            res = res.and(check_associated_item(tcx, assoc_ty_def_id.expect_local()));366        }367    }368    res369}370371/// Require that the user writes where clauses on GATs for the implicit372/// outlives bounds involving trait parameters in trait functions and373/// lifetimes passed as GAT args. See `self-outlives-lint` test.374///375/// We use the following trait as an example throughout this function:376/// ```rust,ignore (this code fails due to this lint)377/// trait IntoIter {378///     type Iter<'a>: Iterator<Item = Self::Item<'a>>;379///     type Item<'a>;380///     fn into_iter<'a>(&'a self) -> Self::Iter<'a>;381/// }382/// ```383fn check_gat_where_clauses(tcx: TyCtxt<'_>, trait_def_id: LocalDefId) {384    // Associates every GAT's def_id to a list of possibly missing bounds detected by this lint.385    let mut required_bounds_by_item = FxIndexMap::default();386    let associated_items = tcx.associated_items(trait_def_id);387388    // Loop over all GATs together, because if this lint suggests adding a where-clause bound389    // to one GAT, it might then require us to an additional bound on another GAT.390    // In our `IntoIter` example, we discover a missing `Self: 'a` bound on `Iter<'a>`, which391    // then in a second loop adds a `Self: 'a` bound to `Item` due to the relationship between392    // those GATs.393    loop {394        let mut should_continue = false;395        for gat_item in associated_items.in_definition_order() {396            let gat_def_id = gat_item.def_id.expect_local();397            let gat_item = tcx.associated_item(gat_def_id);398            // If this item is not an assoc ty, or has no args, then it's not a GAT399            if !gat_item.is_type() {400                continue;401            }402            let gat_generics = tcx.generics_of(gat_def_id);403            // FIXME(jackh726): we can also warn in the more general case404            if gat_generics.is_own_empty() {405                continue;406            }407408            // Gather the bounds with which all other items inside of this trait constrain the GAT.409            // This is calculated by taking the intersection of the bounds that each item410            // constrains the GAT with individually.411            let mut new_required_bounds: Option<FxIndexSet<ty::Clause<'_>>> = None;412            for item in associated_items.in_definition_order() {413                let item_def_id = item.def_id.expect_local();414                // Skip our own GAT, since it does not constrain itself at all.415                if item_def_id == gat_def_id {416                    continue;417                }418419                let param_env = tcx.param_env(item_def_id);420421                let item_required_bounds = match tcx.associated_item(item_def_id).kind {422                    // In our example, this corresponds to `into_iter` method423                    ty::AssocKind::Fn { .. } => {424                        // For methods, we check the function signature's return type for any GATs425                        // to constrain. In the `into_iter` case, we see that the return type426                        // `Self::Iter<'a>` is a GAT we want to gather any potential missing bounds from.427                        let sig: ty::FnSig<'_> = tcx.liberate_late_bound_regions(428                            item_def_id.to_def_id(),429                            tcx.fn_sig(item_def_id).instantiate_identity().skip_norm_wip(),430                        );431                        gather_gat_bounds(432                            tcx,433                            param_env,434                            item_def_id,435                            sig.inputs_and_output,436                            // We also assume that all of the function signature's parameter types437                            // are well formed.438                            &sig.inputs().iter().copied().collect(),439                            gat_def_id,440                            gat_generics,441                        )442                    }443                    // In our example, this corresponds to the `Iter` and `Item` associated types444                    ty::AssocKind::Type { .. } => {445                        // If our associated item is a GAT with missing bounds, add them to446                        // the param-env here. This allows this GAT to propagate missing bounds447                        // to other GATs.448                        let param_env = augment_param_env(449                            tcx,450                            param_env,451                            required_bounds_by_item.get(&item_def_id),452                        );453                        gather_gat_bounds(454                            tcx,455                            param_env,456                            item_def_id,457                            tcx.explicit_item_bounds(item_def_id)458                                .iter_identity_copied()459                                .map(Unnormalized::skip_norm_wip)460                                .collect::<Vec<_>>(),461                            &FxIndexSet::default(),462                            gat_def_id,463                            gat_generics,464                        )465                    }466                    ty::AssocKind::Const { .. } => None,467                };468469                if let Some(item_required_bounds) = item_required_bounds {470                    // Take the intersection of the required bounds for this GAT, and471                    // the item_required_bounds which are the ones implied by just472                    // this item alone.473                    // This is why we use an Option<_>, since we need to distinguish474                    // the empty set of bounds from the _uninitialized_ set of bounds.475                    if let Some(new_required_bounds) = &mut new_required_bounds {476                        new_required_bounds.retain(|b| item_required_bounds.contains(b));477                    } else {478                        new_required_bounds = Some(item_required_bounds);479                    }480                }481            }482483            if let Some(new_required_bounds) = new_required_bounds {484                let required_bounds = required_bounds_by_item.entry(gat_def_id).or_default();485                if new_required_bounds.into_iter().any(|p| required_bounds.insert(p)) {486                    // Iterate until our required_bounds no longer change487                    // Since they changed here, we should continue the loop488                    should_continue = true;489                }490            }491        }492        // We know that this loop will eventually halt, since we only set `should_continue` if the493        // `required_bounds` for this item grows. Since we are not creating any new region or type494        // variables, the set of all region and type bounds that we could ever insert are limited495        // by the number of unique types and regions we observe in a given item.496        if !should_continue {497            break;498        }499    }500501    for (gat_def_id, required_bounds) in required_bounds_by_item {502        // Don't suggest adding `Self: 'a` to a GAT that can't be named503        if tcx.is_impl_trait_in_trait(gat_def_id.to_def_id()) {504            continue;505        }506507        let gat_item_hir = tcx.hir_expect_trait_item(gat_def_id);508        debug!(?required_bounds);509        let param_env = tcx.param_env(gat_def_id);510511        let unsatisfied_bounds: Vec<_> = required_bounds512            .into_iter()513            .filter(|clause| match clause.kind().skip_binder() {514                ty::ClauseKind::RegionOutlives(ty::OutlivesPredicate(a, b)) => {515                    !region_known_to_outlive(516                        tcx,517                        gat_def_id,518                        param_env,519                        &FxIndexSet::default(),520                        a,521                        b,522                    )523                }524                ty::ClauseKind::TypeOutlives(ty::OutlivesPredicate(a, b)) => {525                    !ty_known_to_outlive(tcx, gat_def_id, param_env, &FxIndexSet::default(), a, b)526                }527                _ => bug!("Unexpected ClauseKind"),528            })529            .map(|clause| clause.to_string())530            .collect();531532        if !unsatisfied_bounds.is_empty() {533            let plural = pluralize!(unsatisfied_bounds.len());534            let suggestion = format!(535                "{} {}",536                gat_item_hir.generics.add_where_or_trailing_comma(),537                unsatisfied_bounds.join(", "),538            );539            let bound =540                if unsatisfied_bounds.len() > 1 { "these bounds are" } else { "this bound is" };541            tcx.dcx()542                .struct_span_err(543                    gat_item_hir.span,544                    format!("missing required bound{} on `{}`", plural, gat_item_hir.ident),545                )546                .with_span_suggestion(547                    gat_item_hir.generics.tail_span_for_predicate_suggestion(),548                    format!("add the required where clause{plural}"),549                    suggestion,550                    Applicability::MachineApplicable,551                )552                .with_note(format!(553                    "{bound} currently required to ensure that impls have maximum flexibility"554                ))555                .with_note(556                    "we are soliciting feedback, see issue #87479 \557                     <https://github.com/rust-lang/rust/issues/87479> for more information",558                )559                .emit();560        }561    }562}563564/// Add a new set of predicates to the caller_bounds of an existing param_env.565fn augment_param_env<'tcx>(566    tcx: TyCtxt<'tcx>,567    param_env: ty::ParamEnv<'tcx>,568    new_predicates: Option<&FxIndexSet<ty::Clause<'tcx>>>,569) -> ty::ParamEnv<'tcx> {570    let Some(new_predicates) = new_predicates else {571        return param_env;572    };573574    if new_predicates.is_empty() {575        return param_env;576    }577578    let bounds = tcx.mk_clauses_from_iter(579        param_env.caller_bounds().iter().chain(new_predicates.iter().cloned()),580    );581    // FIXME(compiler-errors): Perhaps there is a case where we need to normalize this582    // i.e. traits::normalize_param_env_or_error583    ty::ParamEnv::new(bounds)584}585586/// We use the following trait as an example throughout this function.587/// Specifically, let's assume that `to_check` here is the return type588/// of `into_iter`, and the GAT we are checking this for is `Iter`.589/// ```rust,ignore (this code fails due to this lint)590/// trait IntoIter {591///     type Iter<'a>: Iterator<Item = Self::Item<'a>>;592///     type Item<'a>;593///     fn into_iter<'a>(&'a self) -> Self::Iter<'a>;594/// }595/// ```596fn gather_gat_bounds<'tcx, T: TypeFoldable<TyCtxt<'tcx>>>(597    tcx: TyCtxt<'tcx>,598    param_env: ty::ParamEnv<'tcx>,599    item_def_id: LocalDefId,600    to_check: T,601    wf_tys: &FxIndexSet<Ty<'tcx>>,602    gat_def_id: LocalDefId,603    gat_generics: &'tcx ty::Generics,604) -> Option<FxIndexSet<ty::Clause<'tcx>>> {605    // The bounds we that we would require from `to_check`606    let mut bounds = FxIndexSet::default();607608    let (regions, types) = GATArgsCollector::visit(gat_def_id.to_def_id(), to_check);609610    // If both regions and types are empty, then this GAT isn't in the611    // set of types we are checking, and we shouldn't try to do clause analysis612    // (particularly, doing so would end up with an empty set of clauses,613    // since the current method would require none, and we take the614    // intersection of requirements of all methods)615    if types.is_empty() && regions.is_empty() {616        return None;617    }618619    for (region_a, region_a_idx) in &regions {620        // Ignore `'static` lifetimes for the purpose of this lint: it's621        // because we know it outlives everything and so doesn't give meaningful622        // clues. Also ignore `ReError`, to avoid knock-down errors.623        if let ty::ReStatic | ty::ReError(_) = region_a.kind() {624            continue;625        }626        // For each region argument (e.g., `'a` in our example), check for a627        // relationship to the type arguments (e.g., `Self`). If there is an628        // outlives relationship (`Self: 'a`), then we want to ensure that is629        // reflected in a where clause on the GAT itself.630        for (ty, ty_idx) in &types {631            // In our example, requires that `Self: 'a`632            if ty_known_to_outlive(tcx, item_def_id, param_env, wf_tys, *ty, *region_a) {633                debug!(?ty_idx, ?region_a_idx);634                debug!("required clause: {ty} must outlive {region_a}");635                // Translate into the generic parameters of the GAT. In636                // our example, the type was `Self`, which will also be637                // `Self` in the GAT.638                let ty_param = gat_generics.param_at(*ty_idx, tcx);639                let ty_param = Ty::new_param(tcx, ty_param.index, ty_param.name);640                // Same for the region. In our example, 'a corresponds641                // to the 'me parameter.642                let region_param = gat_generics.param_at(*region_a_idx, tcx);643                let region_param = ty::Region::new_early_param(644                    tcx,645                    ty::EarlyParamRegion { index: region_param.index, name: region_param.name },646                );647                // The predicate we expect to see. (In our example,648                // `Self: 'me`.)649                bounds.insert(650                    ty::ClauseKind::TypeOutlives(ty::OutlivesPredicate(ty_param, region_param))651                        .upcast(tcx),652                );653            }654        }655656        // For each region argument (e.g., `'a` in our example), also check for a657        // relationship to the other region arguments. If there is an outlives658        // relationship, then we want to ensure that is reflected in the where clause659        // on the GAT itself.660        for (region_b, region_b_idx) in &regions {661            // Again, skip `'static` because it outlives everything. Also, we trivially662            // know that a region outlives itself. Also ignore `ReError`, to avoid663            // knock-down errors.664            if matches!(region_b.kind(), ty::ReStatic | ty::ReError(_)) || region_a == region_b {665                continue;666            }667            if region_known_to_outlive(tcx, item_def_id, param_env, wf_tys, *region_a, *region_b) {668                debug!(?region_a_idx, ?region_b_idx);669                debug!("required clause: {region_a} must outlive {region_b}");670                // Translate into the generic parameters of the GAT.671                let region_a_param = gat_generics.param_at(*region_a_idx, tcx);672                let region_a_param = ty::Region::new_early_param(673                    tcx,674                    ty::EarlyParamRegion { index: region_a_param.index, name: region_a_param.name },675                );676                // Same for the region.677                let region_b_param = gat_generics.param_at(*region_b_idx, tcx);678                let region_b_param = ty::Region::new_early_param(679                    tcx,680                    ty::EarlyParamRegion { index: region_b_param.index, name: region_b_param.name },681                );682                // The predicate we expect to see.683                bounds.insert(684                    ty::ClauseKind::RegionOutlives(ty::OutlivesPredicate(685                        region_a_param,686                        region_b_param,687                    ))688                    .upcast(tcx),689                );690            }691        }692    }693694    Some(bounds)695}696697/// Given a known `param_env` and a set of well formed types, can we prove that698/// `ty` outlives `region`.699fn ty_known_to_outlive<'tcx>(700    tcx: TyCtxt<'tcx>,701    id: LocalDefId,702    param_env: ty::ParamEnv<'tcx>,703    wf_tys: &FxIndexSet<Ty<'tcx>>,704    ty: Ty<'tcx>,705    region: ty::Region<'tcx>,706) -> bool {707    test_region_obligations(tcx, id, param_env, wf_tys, |infcx| {708        infcx.register_type_outlives_constraint_inner(infer::TypeOutlivesConstraint {709            sub_region: region,710            sup_type: ty,711            origin: SubregionOrigin::RelateParamBound(DUMMY_SP, ty, None),712        });713    })714}715716/// Given a known `param_env` and a set of well formed types, can we prove that717/// `region_a` outlives `region_b`718fn region_known_to_outlive<'tcx>(719    tcx: TyCtxt<'tcx>,720    id: LocalDefId,721    param_env: ty::ParamEnv<'tcx>,722    wf_tys: &FxIndexSet<Ty<'tcx>>,723    region_a: ty::Region<'tcx>,724    region_b: ty::Region<'tcx>,725) -> bool {726    test_region_obligations(tcx, id, param_env, wf_tys, |infcx| {727        infcx.sub_regions(728            SubregionOrigin::RelateRegionParamBound(DUMMY_SP, None),729            region_b,730            region_a,731            ty::VisibleForLeakCheck::Unreachable,732        );733    })734}735736/// Given a known `param_env` and a set of well formed types, set up an737/// `InferCtxt`, call the passed function (to e.g. set up region constraints738/// to be tested), then resolve region and return errors739fn test_region_obligations<'tcx>(740    tcx: TyCtxt<'tcx>,741    id: LocalDefId,742    param_env: ty::ParamEnv<'tcx>,743    wf_tys: &FxIndexSet<Ty<'tcx>>,744    add_constraints: impl FnOnce(&InferCtxt<'tcx>),745) -> bool {746    // Unfortunately, we have to use a new `InferCtxt` each call, because747    // region constraints get added and solved there and we need to test each748    // call individually.749    let infcx = tcx.infer_ctxt().build(TypingMode::non_body_analysis());750751    add_constraints(&infcx);752753    let errors = infcx.resolve_regions(id, param_env, wf_tys.iter().copied());754    debug!(?errors, "errors");755756    // If we were able to prove that the type outlives the region without757    // an error, it must be because of the implied or explicit bounds...758    errors.is_empty()759}760761/// TypeVisitor that looks for uses of GATs like762/// `<P0 as Trait<P1..Pn>>::GAT<Pn..Pm>` and adds the arguments `P0..Pm` into763/// the two vectors, `regions` and `types` (depending on their kind). For each764/// parameter `Pi` also track the index `i`.765struct GATArgsCollector<'tcx> {766    gat: DefId,767    // Which region appears and which parameter index its instantiated with768    regions: FxIndexSet<(ty::Region<'tcx>, usize)>,769    // Which params appears and which parameter index its instantiated with770    types: FxIndexSet<(Ty<'tcx>, usize)>,771}772773impl<'tcx> GATArgsCollector<'tcx> {774    fn visit<T: TypeFoldable<TyCtxt<'tcx>>>(775        gat: DefId,776        t: T,777    ) -> (FxIndexSet<(ty::Region<'tcx>, usize)>, FxIndexSet<(Ty<'tcx>, usize)>) {778        let mut visitor =779            GATArgsCollector { gat, regions: FxIndexSet::default(), types: FxIndexSet::default() };780        t.visit_with(&mut visitor);781        (visitor.regions, visitor.types)782    }783}784785impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for GATArgsCollector<'tcx> {786    fn visit_ty(&mut self, t: Ty<'tcx>) {787        match t.kind() {788            &ty::Alias(ty::AliasTy { kind: ty::Projection { def_id }, args, .. })789                if def_id == self.gat =>790            {791                for (idx, arg) in args.iter().enumerate() {792                    match arg.kind() {793                        GenericArgKind::Lifetime(lt) if !lt.is_bound() => {794                            self.regions.insert((lt, idx));795                        }796                        GenericArgKind::Type(t) => {797                            self.types.insert((t, idx));798                        }799                        _ => {}800                    }801                }802            }803            _ => {}804        }805        t.super_visit_with(self)806    }807}808809fn lint_item_shadowing_supertrait_item<'tcx>(tcx: TyCtxt<'tcx>, trait_item_def_id: LocalDefId) {810    let item_name = tcx.item_name(trait_item_def_id.to_def_id());811    let trait_def_id = tcx.local_parent(trait_item_def_id);812813    let shadowed: Vec<_> = traits::supertrait_def_ids(tcx, trait_def_id.to_def_id())814        .skip(1)815        .flat_map(|supertrait_def_id| {816            tcx.associated_items(supertrait_def_id).filter_by_name_unhygienic(item_name)817        })818        .collect();819    if !shadowed.is_empty() {820        let shadowee = if let [shadowed] = shadowed[..] {821            errors::SupertraitItemShadowee::Labeled {822                span: tcx.def_span(shadowed.def_id),823                supertrait: tcx.item_name(shadowed.trait_container(tcx).unwrap()),824            }825        } else {826            let (traits, spans): (Vec<_>, Vec<_>) = shadowed827                .iter()828                .map(|item| {829                    (tcx.item_name(item.trait_container(tcx).unwrap()), tcx.def_span(item.def_id))830                })831                .unzip();832            errors::SupertraitItemShadowee::Several { traits: traits.into(), spans: spans.into() }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            errors::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.1038fn check_type_defn<'tcx>(1039    tcx: TyCtxt<'tcx>,1040    item: &hir::Item<'tcx>,1041    all_sized: bool,1042) -> Result<(), ErrorGuaranteed> {1043    tcx.ensure_ok().check_representability(item.owner_id.def_id);1044    let adt_def = tcx.adt_def(item.owner_id);10451046    enter_wf_checking_ctxt(tcx, item.owner_id.def_id, |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 hir::Node::AnonConst(anon) = tcx.hir_node_by_def_id(def_id)1060                        && let expr = &tcx.hir_body(anon.body).value1061                        && let hir::ExprKind::Path(hir::QPath::Resolved(None, path)) = expr.kind1062                        && let Res::Def(DefKind::ConstParam, _def_id) = path.res1063                    {1064                        // Do not evaluate bare `const` params, as those would ICE and are only1065                        // usable if `#![feature(generic_const_exprs)]` is enabled.1066                    } else {1067                        // Evaluate the constant proactively, to emit an error if the constant has1068                        // an unconditional error. We only do so if the const has no type params.1069                        let _ = tcx.const_eval_poly(def_id);1070                    }1071                }1072                let field_id = field.did.expect_local();1073                let hir::FieldDef { ty: hir_ty, .. } =1074                    tcx.hir_node_by_def_id(field_id).expect_field();1075                let ty = wfcx.deeply_normalize(1076                    hir_ty.span,1077                    None,1078                    tcx.type_of(field.did).instantiate_identity(),1079                );1080                wfcx.register_wf_obligation(1081                    hir_ty.span,1082                    Some(WellFormedLoc::Ty(field_id)),1083                    ty.into(),1084                );10851086                if matches!(ty.kind(), ty::Adt(def, _) if def.repr().scalable())1087                    && !matches!(adt_def.repr().scalable, Some(ScalableElt::Container))1088                {1089                    // Scalable vectors can only be fields of structs if the type has a1090                    // `rustc_scalable_vector` attribute w/out specifying an element count1091                    tcx.dcx().span_err(1092                        hir_ty.span,1093                        format!(1094                            "scalable vectors cannot be fields of a {}",1095                            adt_def.variant_descr()1096                        ),1097                    );1098                }1099            }11001101            // For DST, or when drop needs to copy things around, all1102            // intermediate types must be sized.1103            let needs_drop_copy = || {1104                packed && {1105                    let ty = tcx.type_of(variant.tail().did).instantiate_identity().skip_norm_wip();1106                    let ty = tcx.erase_and_anonymize_regions(ty);1107                    assert!(!ty.has_infer());1108                    ty.needs_drop(tcx, wfcx.infcx.typing_env(wfcx.param_env))1109                }1110            };1111            // All fields (except for possibly the last) should be sized.1112            let all_sized = all_sized || variant.fields.is_empty() || needs_drop_copy();1113            let unsized_len = if all_sized { 0 } else { 1 };1114            for (idx, field) in1115                variant.fields.raw[..variant.fields.len() - unsized_len].iter().enumerate()1116            {1117                let last = idx == variant.fields.len() - 1;1118                let field_id = field.did.expect_local();1119                let hir::FieldDef { ty: hir_ty, .. } =1120                    tcx.hir_node_by_def_id(field_id).expect_field();1121                let ty = wfcx.normalize(1122                    hir_ty.span,1123                    None,1124                    tcx.type_of(field.did).instantiate_identity(),1125                );1126                wfcx.register_bound(1127                    traits::ObligationCause::new(1128                        hir_ty.span,1129                        wfcx.body_def_id,1130                        ObligationCauseCode::FieldSized {1131                            adt_kind: match &item.kind {1132                                ItemKind::Struct(..) => AdtKind::Struct,1133                                ItemKind::Union(..) => AdtKind::Union,1134                                ItemKind::Enum(..) => AdtKind::Enum,1135                                kind => span_bug!(1136                                    item.span,1137                                    "should be wfchecking an ADT, got {kind:?}"1138                                ),1139                            },1140                            span: hir_ty.span,1141                            last,1142                        },1143                    ),1144                    wfcx.param_env,1145                    ty,1146                    tcx.require_lang_item(LangItem::Sized, hir_ty.span),1147                );1148            }11491150            // Explicit `enum` discriminant values must const-evaluate successfully.1151            if let ty::VariantDiscr::Explicit(discr_def_id) = variant.discr {1152                match tcx.const_eval_poly(discr_def_id) {1153                    Ok(_) => {}1154                    Err(ErrorHandled::Reported(..)) => {}1155                    Err(ErrorHandled::TooGeneric(sp)) => {1156                        span_bug!(sp, "enum variant discr was too generic to eval")1157                    }1158                }1159            }1160        }11611162        check_where_clauses(wfcx, item.owner_id.def_id);1163        Ok(())1164    })1165}11661167#[instrument(skip(tcx, item))]1168fn check_trait(tcx: TyCtxt<'_>, item: &hir::Item<'_>) -> Result<(), ErrorGuaranteed> {1169    debug!(?item.owner_id);11701171    let def_id = item.owner_id.def_id;1172    if tcx.is_lang_item(def_id.into(), LangItem::PointeeSized) {1173        // `PointeeSized` is removed during lowering.1174        return Ok(());1175    }11761177    let trait_def = tcx.trait_def(def_id);1178    if trait_def.is_marker1179        || matches!(trait_def.specialization_kind, TraitSpecializationKind::Marker)1180    {1181        for associated_def_id in &*tcx.associated_item_def_ids(def_id) {1182            struct_span_code_err!(1183                tcx.dcx(),1184                tcx.def_span(*associated_def_id),1185                E0714,1186                "marker traits cannot have associated items",1187            )1188            .emit();1189        }1190    }11911192    let res = enter_wf_checking_ctxt(tcx, def_id, |wfcx| {1193        check_where_clauses(wfcx, def_id);1194        Ok(())1195    });11961197    // Only check traits, don't check trait aliases1198    if let hir::ItemKind::Trait { .. } = item.kind {1199        check_gat_where_clauses(tcx, item.owner_id.def_id);1200    }1201    res1202}12031204/// Checks all associated type defaults of trait `trait_def_id`.1205///1206/// Assuming the defaults are used, check that all predicates (bounds on the1207/// assoc type and where clauses on the trait) hold.1208fn check_associated_type_bounds(wfcx: &WfCheckingCtxt<'_, '_>, item: ty::AssocItem, _span: Span) {1209    let bounds = wfcx.tcx().explicit_item_bounds(item.def_id);12101211    debug!("check_associated_type_bounds: bounds={:?}", bounds);1212    let wf_obligations = bounds.iter_identity_copied().map(Unnormalized::skip_norm_wip).flat_map(1213        |(bound, bound_span)| {1214            traits::wf::clause_obligations(1215                wfcx.infcx,1216                wfcx.param_env,1217                wfcx.body_def_id,1218                bound,1219                bound_span,1220            )1221        },1222    );12231224    wfcx.register_obligations(wf_obligations);1225}12261227fn check_item_fn(1228    tcx: TyCtxt<'_>,1229    def_id: LocalDefId,1230    decl: &hir::FnDecl<'_>,1231) -> Result<(), ErrorGuaranteed> {1232    enter_wf_checking_ctxt(tcx, def_id, |wfcx| {1233        check_eiis_fn(tcx, def_id);12341235        let sig = tcx.fn_sig(def_id).instantiate_identity().skip_norm_wip();1236        check_fn_or_method(wfcx, sig, decl, def_id);1237        Ok(())1238    })1239}12401241fn check_eiis_fn(tcx: TyCtxt<'_>, def_id: LocalDefId) {1242    // does the function have an EiiImpl attribute? that contains the defid of a *macro*1243    // that was used to mark the implementation. This is a two step process.1244    for EiiImpl { resolution, span, .. } in1245        find_attr!(tcx, def_id, EiiImpls(impls) => impls).into_iter().flatten()1246    {1247        let (foreign_item, name) = match resolution {1248            EiiImplResolution::Macro(def_id) => {1249                // we expect this macro to have the `EiiMacroFor` attribute, that points to a function1250                // signature that we'd like to compare the function we're currently checking with1251                if let Some(foreign_item) =1252                    find_attr!(tcx, *def_id, EiiDeclaration(EiiDecl {foreign_item: t, ..}) => *t)1253                {1254                    (foreign_item, tcx.item_name(*def_id))1255                } else {1256                    tcx.dcx().span_delayed_bug(*span, "resolved to something that's not an EII");1257                    continue;1258                }1259            }1260            EiiImplResolution::Known(decl) => (decl.foreign_item, decl.name.name),1261            EiiImplResolution::Error(_eg) => continue,1262        };12631264        let _ = compare_eii_function_types(tcx, def_id, foreign_item, name, *span);1265    }1266}12671268fn check_eiis_static<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId, ty: Ty<'tcx>) {1269    // does the function have an EiiImpl attribute? that contains the defid of a *macro*1270    // that was used to mark the implementation. This is a two step process.1271    for EiiImpl { resolution, span, .. } in1272        find_attr!(tcx, def_id, EiiImpls(impls) => impls).into_iter().flatten()1273    {1274        let (foreign_item, name) = match resolution {1275            EiiImplResolution::Macro(def_id) => {1276                // we expect this macro to have the `EiiMacroFor` attribute, that points to a function1277                // signature that we'd like to compare the function we're currently checking with1278                if let Some(foreign_item) =1279                    find_attr!(tcx, *def_id, EiiDeclaration(EiiDecl {foreign_item: t, ..}) => *t)1280                {1281                    (foreign_item, tcx.item_name(*def_id))1282                } else {1283                    tcx.dcx().span_delayed_bug(*span, "resolved to something that's not an EII");1284                    continue;1285                }1286            }1287            EiiImplResolution::Known(decl) => (decl.foreign_item, decl.name.name),1288            EiiImplResolution::Error(_eg) => continue,1289        };12901291        let _ = compare_eii_statics(tcx, def_id, ty, foreign_item, name, *span);1292    }1293}12941295#[instrument(level = "debug", skip(tcx))]1296pub(crate) fn check_static_item<'tcx>(1297    tcx: TyCtxt<'tcx>,1298    item_id: LocalDefId,1299    ty: Ty<'tcx>,1300    should_check_for_sync: bool,1301) -> Result<(), ErrorGuaranteed> {1302    enter_wf_checking_ctxt(tcx, item_id, |wfcx| {1303        if should_check_for_sync {1304            check_eiis_static(tcx, item_id, ty);1305        }13061307        let span = tcx.ty_span(item_id);1308        let loc = Some(WellFormedLoc::Ty(item_id));1309        let item_ty = wfcx.deeply_normalize(span, loc, Unnormalized::new_wip(ty));13101311        let is_foreign_item = tcx.is_foreign_item(item_id);1312        let is_structurally_foreign_item = || {1313            let tail = tcx.struct_tail_raw(1314                item_ty,1315                &ObligationCause::dummy(),1316                |ty| wfcx.deeply_normalize(span, loc, Unnormalized::new_wip(ty)),1317                || {},1318            );13191320            matches!(tail.kind(), ty::Foreign(_))1321        };1322        let forbid_unsized = !(is_foreign_item && is_structurally_foreign_item());13231324        wfcx.register_wf_obligation(span, Some(WellFormedLoc::Ty(item_id)), item_ty.into());1325        if forbid_unsized {1326            let span = tcx.def_span(item_id);1327            wfcx.register_bound(1328                traits::ObligationCause::new(1329                    span,1330                    wfcx.body_def_id,1331                    ObligationCauseCode::SizedConstOrStatic,1332                ),1333                wfcx.param_env,1334                item_ty,1335                tcx.require_lang_item(LangItem::Sized, span),1336            );1337        }13381339        // Ensure that the end result is `Sync` in a non-thread local `static`.1340        let should_check_for_sync = should_check_for_sync1341            && !is_foreign_item1342            && tcx.static_mutability(item_id.to_def_id()) == Some(hir::Mutability::Not)1343            && !tcx.is_thread_local_static(item_id.to_def_id());13441345        if should_check_for_sync {1346            wfcx.register_bound(1347                traits::ObligationCause::new(1348                    span,1349                    wfcx.body_def_id,1350                    ObligationCauseCode::SharedStatic,1351                ),1352                wfcx.param_env,1353                item_ty,1354                tcx.require_lang_item(LangItem::Sync, span),1355            );1356        }1357        Ok(())1358    })1359}13601361#[instrument(level = "debug", skip(wfcx))]1362pub(super) fn check_type_const<'tcx>(1363    wfcx: &WfCheckingCtxt<'_, 'tcx>,1364    def_id: LocalDefId,1365    item_ty: Ty<'tcx>,1366    has_value: bool,1367) -> Result<(), ErrorGuaranteed> {1368    let tcx = wfcx.tcx();1369    let span = tcx.def_span(def_id);13701371    if !tcx.features().const_param_ty_unchecked() {1372        wfcx.register_bound(1373            ObligationCause::new(span, def_id, ObligationCauseCode::ConstParam(item_ty)),1374            wfcx.param_env,1375            item_ty,1376            tcx.require_lang_item(LangItem::ConstParamTy, span),1377        );1378    }13791380    if has_value {1381        let raw_ct = tcx.const_of_item(def_id).instantiate_identity();1382        let norm_ct = wfcx.deeply_normalize(span, Some(WellFormedLoc::Ty(def_id)), raw_ct);1383        wfcx.register_wf_obligation(span, Some(WellFormedLoc::Ty(def_id)), norm_ct.into());13841385        wfcx.register_obligation(Obligation::new(1386            tcx,1387            ObligationCause::new(span, def_id, ObligationCauseCode::WellFormed(None)),1388            wfcx.param_env,1389            ty::PredicateKind::Clause(ty::ClauseKind::ConstArgHasType(norm_ct, item_ty)),1390        ));1391    }1392    Ok(())1393}13941395#[instrument(level = "debug", skip(tcx, impl_))]1396fn check_impl<'tcx>(1397    tcx: TyCtxt<'tcx>,1398    item: &'tcx hir::Item<'tcx>,1399    impl_: &hir::Impl<'_>,1400) -> Result<(), ErrorGuaranteed> {1401    enter_wf_checking_ctxt(tcx, item.owner_id.def_id, |wfcx| {1402        match impl_.of_trait {1403            Some(of_trait) => {1404                // `#[rustc_reservation_impl]` impls are not real impls and1405                // therefore don't need to be WF (the trait's `Self: Trait` predicate1406                // won't hold).1407                let trait_ref = tcx.impl_trait_ref(item.owner_id).instantiate_identity();1408                // Avoid bogus "type annotations needed `Foo: Bar`" errors on `impl Bar for Foo` in1409                // case other `Foo` impls are incoherent.1410                tcx.ensure_result().coherent_trait(trait_ref.skip_normalization().def_id)?;1411                let trait_span = of_trait.trait_ref.path.span;1412                let trait_ref = wfcx.deeply_normalize(1413                    trait_span,1414                    Some(WellFormedLoc::Ty(item.hir_id().expect_owner().def_id)),1415                    trait_ref,1416                );1417                let trait_pred =1418                    ty::TraitPredicate { trait_ref, polarity: ty::PredicatePolarity::Positive };1419                let mut obligations = traits::wf::trait_obligations(1420                    wfcx.infcx,1421                    wfcx.param_env,1422                    wfcx.body_def_id,1423                    trait_pred,1424                    trait_span,1425                    item,1426                );1427                for obligation in &mut obligations {1428                    if obligation.cause.span != trait_span {1429                        // We already have a better span.1430                        continue;1431                    }1432                    if let Some(pred) = obligation.predicate.as_trait_clause()1433                        && pred.skip_binder().self_ty() == trait_ref.self_ty()1434                    {1435                        obligation.cause.span = impl_.self_ty.span;1436                    }1437                    if let Some(pred) = obligation.predicate.as_projection_clause()1438                        && pred.skip_binder().self_ty() == trait_ref.self_ty()1439                    {1440                        obligation.cause.span = impl_.self_ty.span;1441                    }1442                }14431444                // Ensure that the `[const]` where clauses of the trait hold for the impl.1445                if tcx.is_conditionally_const(item.owner_id.def_id) {1446                    for (bound, _) in1447                        tcx.const_conditions(trait_ref.def_id).instantiate(tcx, trait_ref.args)1448                    {1449                        let bound = wfcx.normalize(1450                            item.span,1451                            Some(WellFormedLoc::Ty(item.hir_id().expect_owner().def_id)),1452                            bound,1453                        );1454                        wfcx.register_obligation(Obligation::new(1455                            tcx,1456                            ObligationCause::new(1457                                impl_.self_ty.span,1458                                wfcx.body_def_id,1459                                ObligationCauseCode::WellFormed(None),1460                            ),1461                            wfcx.param_env,1462                            bound.to_host_effect_clause(tcx, ty::BoundConstness::Maybe),1463                        ))1464                    }1465                }14661467                debug!(?obligations);1468                wfcx.register_obligations(obligations);1469            }1470            None => {1471                let self_ty = tcx.type_of(item.owner_id).instantiate_identity().skip_norm_wip();1472                let self_ty = wfcx.deeply_normalize(1473                    item.span,1474                    Some(WellFormedLoc::Ty(item.hir_id().expect_owner().def_id)),1475                    Unnormalized::new_wip(self_ty),1476                );1477                wfcx.register_wf_obligation(1478                    impl_.self_ty.span,1479                    Some(WellFormedLoc::Ty(item.hir_id().expect_owner().def_id)),1480                    self_ty.into(),1481                );1482            }1483        }14841485        check_where_clauses(wfcx, item.owner_id.def_id);1486        Ok(())1487    })1488}14891490/// Checks where-clauses and inline bounds that are declared on `def_id`.1491#[instrument(level = "debug", skip(wfcx))]1492pub(super) fn check_where_clauses<'tcx>(wfcx: &WfCheckingCtxt<'_, 'tcx>, def_id: LocalDefId) {1493    let infcx = wfcx.infcx;1494    let tcx = wfcx.tcx();14951496    let predicates = tcx.predicates_of(def_id.to_def_id());1497    let generics = tcx.generics_of(def_id);14981499    // Check that concrete defaults are well-formed. See test `type-check-defaults.rs`.1500    // For example, this forbids the declaration:1501    //1502    //     struct Foo<T = Vec<[u32]>> { .. }1503    //1504    // Here, the default `Vec<[u32]>` is not WF because `[u32]: Sized` does not hold.1505    for param in &generics.own_params {1506        if let Some(default) = param1507            .default_value(tcx)1508            .map(ty::EarlyBinder::instantiate_identity)1509            .map(Unnormalized::skip_norm_wip)1510        {1511            // Ignore dependent defaults -- that is, where the default of one type1512            // parameter includes another (e.g., `<T, U = T>`). In those cases, we can't1513            // be sure if it will error or not as user might always specify the other.1514            // FIXME(generic_const_exprs): This is incorrect when dealing with unused const params.1515            // E.g: `struct Foo<const N: usize, const M: usize = { 1 - 2 }>;`. Here, we should1516            // eagerly error but we don't as we have `ConstKind::Unevaluated(.., [N, M])`.1517            if !default.has_param() {1518                wfcx.register_wf_obligation(1519                    tcx.def_span(param.def_id),1520                    matches!(param.kind, GenericParamDefKind::Type { .. })1521                        .then(|| WellFormedLoc::Ty(param.def_id.expect_local())),1522                    default.as_term().unwrap(),1523                );1524            } else {1525                // If we've got a generic const parameter we still want to check its1526                // type is correct in case both it and the param type are fully concrete.1527                let GenericArgKind::Const(ct) = default.kind() else {1528                    continue;1529                };15301531                let ct_ty = match ct.kind() {1532                    ty::ConstKind::Infer(_)1533                    | ty::ConstKind::Placeholder(_)1534                    | ty::ConstKind::Bound(_, _) => unreachable!(),1535                    ty::ConstKind::Error(_) | ty::ConstKind::Expr(_) => continue,1536                    ty::ConstKind::Value(cv) => cv.ty,1537                    ty::ConstKind::Unevaluated(uv) => {1538                        infcx.tcx.type_of(uv.def).instantiate(infcx.tcx, uv.args).skip_norm_wip()1539                    }1540                    ty::ConstKind::Param(param_ct) => {1541                        param_ct.find_const_ty_from_env(wfcx.param_env)1542                    }1543                };15441545                let param_ty = tcx.type_of(param.def_id).instantiate_identity().skip_norm_wip();1546                if !ct_ty.has_param() && !param_ty.has_param() {1547                    let cause = traits::ObligationCause::new(1548                        tcx.def_span(param.def_id),1549                        wfcx.body_def_id,1550                        ObligationCauseCode::WellFormed(None),1551                    );1552                    wfcx.register_obligation(Obligation::new(1553                        tcx,1554                        cause,1555                        wfcx.param_env,1556                        ty::ClauseKind::ConstArgHasType(ct, param_ty),1557                    ));1558                }1559            }1560        }1561    }15621563    // Check that trait predicates are WF when params are instantiated with their defaults.1564    // We don't want to overly constrain the predicates that may be written but we want to1565    // catch cases where a default my never be applied such as `struct Foo<T: Copy = String>`.1566    // Therefore we check if a predicate which contains a single type param1567    // with a concrete default is WF with that default instantiated.1568    // For more examples see tests `defaults-well-formedness.rs` and `type-check-defaults.rs`.1569    //1570    // First we build the defaulted generic parameters.1571    let args = GenericArgs::for_item(tcx, def_id.to_def_id(), |param, _| {1572        if param.index >= generics.parent_count as u321573            // If the param has a default, ...1574            && let Some(default) = param.default_value(tcx).map(ty::EarlyBinder::instantiate_identity).map(Unnormalized::skip_norm_wip)1575            // ... and it's not a dependent default, ...1576            && !default.has_param()1577        {1578            // ... then instantiate it with the default.1579            return default;1580        }1581        tcx.mk_param_from_def(param)1582    });15831584    // Now we build the instantiated predicates.1585    let default_obligations = predicates1586        .predicates1587        .iter()1588        .flat_map(|&(pred, sp)| {1589            #[derive(Default)]1590            struct CountParams {1591                params: FxHashSet<u32>,1592            }1593            impl<'tcx> ty::TypeVisitor<TyCtxt<'tcx>> for CountParams {1594                type Result = ControlFlow<()>;1595                fn visit_ty(&mut self, t: Ty<'tcx>) -> Self::Result {1596                    if let ty::Param(param) = t.kind() {1597                        self.params.insert(param.index);1598                    }1599                    t.super_visit_with(self)1600                }16011602                fn visit_region(&mut self, _: ty::Region<'tcx>) -> Self::Result {1603                    ControlFlow::Break(())1604                }16051606                fn visit_const(&mut self, c: ty::Const<'tcx>) -> Self::Result {1607                    if let ty::ConstKind::Param(param) = c.kind() {1608                        self.params.insert(param.index);1609                    }1610                    c.super_visit_with(self)1611                }1612            }1613            let mut param_count = CountParams::default();1614            let has_region = pred.visit_with(&mut param_count).is_break();1615            let instantiated_pred = ty::EarlyBinder::bind(pred).instantiate(tcx, args);1616            // Don't check non-defaulted params, dependent defaults (including lifetimes)1617            // or preds with multiple params.1618            if instantiated_pred.skip_normalization().has_non_region_param()1619                || param_count.params.len() > 11620                || has_region1621            {1622                None1623            } else if predicates1624                .predicates1625                .iter()1626                .any(|&(p, _)| Unnormalized::new_wip(p) == instantiated_pred)1627            {1628                // Avoid duplication of predicates that contain no parameters, for example.1629                None1630            } else {1631                Some((instantiated_pred, sp))1632            }1633        })1634        .map(|(pred, sp)| {1635            // Convert each of those into an obligation. So if you have1636            // something like `struct Foo<T: Copy = String>`, we would1637            // take that predicate `T: Copy`, instantiated with `String: Copy`1638            // (actually that happens in the previous `flat_map` call),1639            // and then try to prove it (in this case, we'll fail).1640            //1641            // Note the subtle difference from how we handle `predicates`1642            // below: there, we are not trying to prove those predicates1643            // to be *true* but merely *well-formed*.1644            let pred = wfcx.normalize(sp, None, pred);1645            let cause = traits::ObligationCause::new(1646                sp,1647                wfcx.body_def_id,1648                ObligationCauseCode::WhereClause(def_id.to_def_id(), sp),1649            );1650            Obligation::new(tcx, cause, wfcx.param_env, pred)1651        });16521653    let predicates = predicates.instantiate_identity(tcx);16541655    let assoc_const_obligations: Vec<_> = predicates1656        .predicates1657        .iter()1658        .copied()1659        .zip(predicates.spans.iter().copied())1660        .filter_map(|(clause, sp)| {1661            let clause = clause.skip_norm_wip();1662            let proj = clause.as_projection_clause()?;1663            let pred_binder = proj1664                .map_bound(|pred| {1665                    pred.term.as_const().map(|ct| {1666                        let assoc_const_ty = tcx1667                            .type_of(pred.projection_term.def_id())1668                            .instantiate(tcx, pred.projection_term.args)1669                            .skip_norm_wip();1670                        ty::ClauseKind::ConstArgHasType(ct, assoc_const_ty)1671                    })1672                })1673                .transpose();1674            pred_binder.map(|pred_binder| {1675                let cause = traits::ObligationCause::new(1676                    sp,1677                    wfcx.body_def_id,1678                    ObligationCauseCode::WhereClause(def_id.to_def_id(), sp),1679                );1680                Obligation::new(tcx, cause, wfcx.param_env, pred_binder)1681            })1682        })1683        .collect();16841685    assert_eq!(predicates.predicates.len(), predicates.spans.len());1686    let wf_obligations = predicates.into_iter().flat_map(|(p, sp)| {1687        traits::wf::clause_obligations(1688            infcx,1689            wfcx.param_env,1690            wfcx.body_def_id,1691            p.skip_norm_wip(),1692            sp,1693        )1694    });1695    let obligations: Vec<_> =1696        wf_obligations.chain(default_obligations).chain(assoc_const_obligations).collect();1697    wfcx.register_obligations(obligations);1698}16991700#[instrument(level = "debug", skip(wfcx, hir_decl))]1701fn check_fn_or_method<'tcx>(1702    wfcx: &WfCheckingCtxt<'_, 'tcx>,1703    sig: ty::PolyFnSig<'tcx>,1704    hir_decl: &hir::FnDecl<'_>,1705    def_id: LocalDefId,1706) {1707    let tcx = wfcx.tcx();1708    let mut sig = tcx.liberate_late_bound_regions(def_id.to_def_id(), sig);17091710    // Normalize the input and output types one at a time, using a different1711    // `WellFormedLoc` for each. We cannot call `normalize_associated_types`1712    // on the entire `FnSig`, since this would use the same `WellFormedLoc`1713    // for each type, preventing the HIR wf check from generating1714    // a nice error message.1715    let arg_span =1716        |idx| hir_decl.inputs.get(idx).map_or(hir_decl.output.span(), |arg: &hir::Ty<'_>| arg.span);17171718    sig.inputs_and_output =1719        tcx.mk_type_list_from_iter(sig.inputs_and_output.iter().enumerate().map(|(idx, ty)| {1720            wfcx.deeply_normalize(1721                arg_span(idx),1722                Some(WellFormedLoc::Param {1723                    function: def_id,1724                    // Note that the `param_idx` of the output type is1725                    // one greater than the index of the last input type.1726                    param_idx: idx,1727                }),1728                Unnormalized::new_wip(ty),1729            )1730        }));17311732    for (idx, ty) in sig.inputs_and_output.iter().enumerate() {1733        wfcx.register_wf_obligation(1734            arg_span(idx),1735            Some(WellFormedLoc::Param { function: def_id, param_idx: idx }),1736            ty.into(),1737        );1738    }17391740    check_where_clauses(wfcx, def_id);17411742    if sig.abi() == ExternAbi::RustCall {1743        let span = tcx.def_span(def_id);1744        let has_implicit_self = hir_decl.implicit_self() != hir::ImplicitSelfKind::None;1745        let mut inputs = sig.inputs().iter().skip(if has_implicit_self { 1 } else { 0 });1746        // Check that the argument is a tuple and is sized1747        if let Some(ty) = inputs.next() {1748            wfcx.register_bound(1749                ObligationCause::new(span, wfcx.body_def_id, ObligationCauseCode::RustCall),1750                wfcx.param_env,1751                *ty,1752                tcx.require_lang_item(hir::LangItem::Tuple, span),1753            );1754            wfcx.register_bound(1755                ObligationCause::new(span, wfcx.body_def_id, ObligationCauseCode::RustCall),1756                wfcx.param_env,1757                *ty,1758                tcx.require_lang_item(hir::LangItem::Sized, span),1759            );1760        } else {1761            tcx.dcx().span_err(1762                hir_decl.inputs.last().map_or(span, |input| input.span),1763                "functions with the \"rust-call\" ABI must take a single non-self tuple argument",1764            );1765        }1766        // No more inputs other than the `self` type and the tuple type1767        if inputs.next().is_some() {1768            tcx.dcx().span_err(1769                hir_decl.inputs.last().map_or(span, |input| input.span),1770                "functions with the \"rust-call\" ABI must take a single non-self tuple argument",1771            );1772        }1773    }17741775    // If the function has a body, additionally require that the return type is sized.1776    if let Some(body) = tcx.hir_maybe_body_owned_by(def_id) {1777        let span = match hir_decl.output {1778            hir::FnRetTy::Return(ty) => ty.span,1779            hir::FnRetTy::DefaultReturn(_) => body.value.span,1780        };17811782        wfcx.register_bound(1783            ObligationCause::new(span, def_id, ObligationCauseCode::SizedReturnType),1784            wfcx.param_env,1785            sig.output(),1786            tcx.require_lang_item(LangItem::Sized, span),1787        );1788    }1789}17901791/// The `arbitrary_self_types_pointers` feature implies `arbitrary_self_types`.1792#[derive(Clone, Copy, PartialEq)]1793enum ArbitrarySelfTypesLevel {1794    Basic,        // just arbitrary_self_types1795    WithPointers, // both arbitrary_self_types and arbitrary_self_types_pointers1796}17971798#[instrument(level = "debug", skip(wfcx))]1799fn check_method_receiver<'tcx>(1800    wfcx: &WfCheckingCtxt<'_, 'tcx>,1801    fn_sig: &hir::FnSig<'_>,1802    method: ty::AssocItem,1803    self_ty: Ty<'tcx>,1804) -> Result<(), ErrorGuaranteed> {1805    let tcx = wfcx.tcx();18061807    if !method.is_method() {1808        return Ok(());1809    }18101811    let span = fn_sig.decl.inputs[0].span;1812    let loc = Some(WellFormedLoc::Param { function: method.def_id.expect_local(), param_idx: 0 });18131814    let sig = tcx.fn_sig(method.def_id).instantiate_identity().skip_norm_wip();1815    let sig = tcx.liberate_late_bound_regions(method.def_id, sig);1816    let sig = wfcx.normalize(DUMMY_SP, loc, Unnormalized::new_wip(sig));18171818    debug!("check_method_receiver: sig={:?}", sig);18191820    let self_ty = wfcx.normalize(DUMMY_SP, loc, Unnormalized::new_wip(self_ty));18211822    let receiver_ty = sig.inputs()[0];1823    let receiver_ty = wfcx.normalize(DUMMY_SP, loc, Unnormalized::new_wip(receiver_ty));18241825    // If the receiver already has errors reported, consider it valid to avoid1826    // unnecessary errors (#58712).1827    receiver_ty.error_reported()?;18281829    let arbitrary_self_types_level = if tcx.features().arbitrary_self_types_pointers() {1830        Some(ArbitrarySelfTypesLevel::WithPointers)1831    } else if tcx.features().arbitrary_self_types() {1832        Some(ArbitrarySelfTypesLevel::Basic)1833    } else {1834        None1835    };1836    let generics = tcx.generics_of(method.def_id);18371838    let receiver_validity =1839        receiver_is_valid(wfcx, span, receiver_ty, self_ty, arbitrary_self_types_level, generics);1840    if let Err(receiver_validity_err) = receiver_validity {1841        return Err(match arbitrary_self_types_level {1842            // Wherever possible, emit a message advising folks that the features1843            // `arbitrary_self_types` or `arbitrary_self_types_pointers` might1844            // have helped.1845            None if receiver_is_valid(1846                wfcx,1847                span,1848                receiver_ty,1849                self_ty,1850                Some(ArbitrarySelfTypesLevel::Basic),1851                generics,1852            )1853            .is_ok() =>1854            {1855                // Report error; would have worked with `arbitrary_self_types`.1856                feature_err(1857                    &tcx.sess,1858                    sym::arbitrary_self_types,1859                    span,1860                    format!(1861                        "`{receiver_ty}` cannot be used as the type of `self` without \1862                            the `arbitrary_self_types` feature",1863                    ),1864                )1865                .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>`"))1866                .emit()1867            }1868            None | Some(ArbitrarySelfTypesLevel::Basic)1869                if receiver_is_valid(1870                    wfcx,1871                    span,1872                    receiver_ty,1873                    self_ty,1874                    Some(ArbitrarySelfTypesLevel::WithPointers),1875                    generics,1876                )1877                .is_ok() =>1878            {1879                // Report error; would have worked with `arbitrary_self_types_pointers`.1880                feature_err(1881                    &tcx.sess,1882                    sym::arbitrary_self_types_pointers,1883                    span,1884                    format!(1885                        "`{receiver_ty}` cannot be used as the type of `self` without \1886                            the `arbitrary_self_types_pointers` feature",1887                    ),1888                )1889                .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>`"))1890                .emit()1891            }1892            _ =>1893            // Report error; would not have worked with `arbitrary_self_types[_pointers]`.1894            {1895                match receiver_validity_err {1896                    ReceiverValidityError::DoesNotDeref if arbitrary_self_types_level.is_some() => {1897                        let hint = match receiver_ty1898                            .builtin_deref(false)1899                            .unwrap_or(receiver_ty)1900                            .ty_adt_def()1901                            .and_then(|adt_def| tcx.get_diagnostic_name(adt_def.did()))1902                        {1903                            Some(sym::RcWeak | sym::ArcWeak) => Some(InvalidReceiverTyHint::Weak),1904                            Some(sym::NonNull) => Some(InvalidReceiverTyHint::NonNull),1905                            _ => None,1906                        };19071908                        tcx.dcx().emit_err(errors::InvalidReceiverTy { span, receiver_ty, hint })1909                    }1910                    ReceiverValidityError::DoesNotDeref => {1911                        tcx.dcx().emit_err(errors::InvalidReceiverTyNoArbitrarySelfTypes {1912                            span,1913                            receiver_ty,1914                        })1915                    }1916                    ReceiverValidityError::MethodGenericParamUsed => {1917                        tcx.dcx().emit_err(errors::InvalidGenericReceiverTy { span, receiver_ty })1918                    }1919                }1920            }1921        });1922    }1923    Ok(())1924}19251926/// Error cases which may be returned from `receiver_is_valid`. These error1927/// cases are generated in this function as they may be unearthed as we explore1928/// the `autoderef` chain, but they're converted to diagnostics in the caller.1929enum ReceiverValidityError {1930    /// The self type does not get to the receiver type by following the1931    /// autoderef chain.1932    DoesNotDeref,1933    /// A type was found which is a method type parameter, and that's not allowed.1934    MethodGenericParamUsed,1935}19361937/// Confirms that a type is not a type parameter referring to one of the1938/// method's type params.1939fn confirm_type_is_not_a_method_generic_param(1940    ty: Ty<'_>,1941    method_generics: &ty::Generics,1942) -> Result<(), ReceiverValidityError> {1943    if let ty::Param(param) = ty.kind() {1944        if (param.index as usize) >= method_generics.parent_count {1945            return Err(ReceiverValidityError::MethodGenericParamUsed);1946        }1947    }1948    Ok(())1949}19501951/// Returns whether `receiver_ty` would be considered a valid receiver type for `self_ty`. If1952/// `arbitrary_self_types` is enabled, `receiver_ty` must transitively deref to `self_ty`, possibly1953/// through a `*const/mut T` raw pointer if  `arbitrary_self_types_pointers` is also enabled.1954/// If neither feature is enabled, the requirements are more strict: `receiver_ty` must implement1955/// `Receiver` and directly implement `Deref<Target = self_ty>`.1956///1957/// N.B., there are cases this function returns `true` but causes an error to be emitted,1958/// particularly when `receiver_ty` derefs to a type that is the same as `self_ty` but has the1959/// wrong lifetime. Be careful of this if you are calling this function speculatively.1960fn receiver_is_valid<'tcx>(1961    wfcx: &WfCheckingCtxt<'_, 'tcx>,1962    span: Span,1963    receiver_ty: Ty<'tcx>,1964    self_ty: Ty<'tcx>,1965    arbitrary_self_types_enabled: Option<ArbitrarySelfTypesLevel>,1966    method_generics: &ty::Generics,1967) -> Result<(), ReceiverValidityError> {1968    let infcx = wfcx.infcx;1969    let tcx = wfcx.tcx();1970    let cause =1971        ObligationCause::new(span, wfcx.body_def_id, traits::ObligationCauseCode::MethodReceiver);19721973    // Special case `receiver == self_ty`, which doesn't necessarily require the `Receiver` lang item.1974    if let Ok(()) = wfcx.infcx.commit_if_ok(|_| {1975        let ocx = ObligationCtxt::new(wfcx.infcx);1976        ocx.eq(&cause, wfcx.param_env, self_ty, receiver_ty)?;1977        if ocx.evaluate_obligations_error_on_ambiguity().is_empty() {1978            Ok(())1979        } else {1980            Err(NoSolution)1981        }1982    }) {1983        return Ok(());1984    }19851986    confirm_type_is_not_a_method_generic_param(receiver_ty, method_generics)?;19871988    let mut autoderef = Autoderef::new(infcx, wfcx.param_env, wfcx.body_def_id, span, receiver_ty);19891990    // The `arbitrary_self_types` feature allows custom smart pointer1991    // types to be method receivers, as identified by following the Receiver<Target=T>1992    // chain.1993    if arbitrary_self_types_enabled.is_some() {1994        autoderef = autoderef.use_receiver_trait();1995    }19961997    // The `arbitrary_self_types_pointers` feature allows raw pointer receivers like `self: *const Self`.1998    if arbitrary_self_types_enabled == Some(ArbitrarySelfTypesLevel::WithPointers) {1999        autoderef = autoderef.include_raw_pointers();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.