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