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