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 ®ions {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 ®ions {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.