2024-07-29 08:13:50 +10:00
|
|
|
use std::cell::LazyCell;
|
|
|
|
|
use std::ops::{ControlFlow, Deref};
|
2022-12-27 00:39:36 +00:00
|
|
|
|
2024-07-17 15:56:16 -04:00
|
|
|
use hir::intravisit::{self, Visitor};
|
2024-11-02 19:32:56 -07:00
|
|
|
use rustc_abi::ExternAbi;
|
2024-10-02 08:25:55 +03:00
|
|
|
use rustc_data_structures::fx::{FxHashSet, FxIndexMap, FxIndexSet};
|
2024-07-29 08:13:50 +10:00
|
|
|
use rustc_errors::codes::*;
|
2024-09-22 19:05:04 -04:00
|
|
|
use rustc_errors::{Applicability, ErrorGuaranteed, pluralize, struct_span_code_err};
|
2024-10-24 16:25:02 +00:00
|
|
|
use rustc_hir::ItemKind;
|
2024-07-17 15:56:16 -04:00
|
|
|
use rustc_hir::def::{DefKind, Res};
|
2023-04-26 20:53:51 +02:00
|
|
|
use rustc_hir::def_id::{DefId, LocalDefId, LocalModDefId};
|
2020-08-18 11:47:27 +01:00
|
|
|
use rustc_hir::lang_items::LangItem;
|
2023-12-19 00:42:58 +00:00
|
|
|
use rustc_infer::infer::outlives::env::OutlivesEnvironment;
|
2022-06-13 01:11:16 -04:00
|
|
|
use rustc_infer::infer::{self, InferCtxt, TyCtxtInferExt};
|
2023-11-29 02:41:31 +00:00
|
|
|
use rustc_macros::LintDiagnostic;
|
2024-11-28 22:04:03 -08:00
|
|
|
use rustc_middle::mir::interpret::ErrorHandled;
|
2023-05-15 06:24:45 +02:00
|
|
|
use rustc_middle::query::Providers;
|
2023-12-10 20:13:21 -05:00
|
|
|
use rustc_middle::ty::print::with_no_trimmed_paths;
|
2020-03-29 17:19:48 +02:00
|
|
|
use rustc_middle::ty::trait_def::TraitSpecializationKind;
|
2021-10-08 12:09:34 -04:00
|
|
|
use rustc_middle::ty::{
|
2024-07-29 08:13:50 +10:00
|
|
|
self, AdtKind, GenericArgKind, GenericArgs, GenericParamDefKind, Ty, TyCtxt, TypeFoldable,
|
2024-10-18 00:28:43 +02:00
|
|
|
TypeSuperVisitable, TypeVisitable, TypeVisitableExt, TypeVisitor, TypingMode, Upcast,
|
2021-10-08 12:09:34 -04:00
|
|
|
};
|
2024-05-08 16:40:46 +10:00
|
|
|
use rustc_middle::{bug, span_bug};
|
2020-03-11 12:49:08 +01:00
|
|
|
use rustc_session::parse::feature_err;
|
2024-09-22 19:05:04 -04:00
|
|
|
use rustc_span::symbol::{Ident, sym};
|
|
|
|
|
use rustc_span::{DUMMY_SP, Span};
|
2024-07-21 15:20:41 -04:00
|
|
|
use rustc_trait_selection::error_reporting::InferCtxtErrorExt;
|
2023-12-18 22:45:34 +00:00
|
|
|
use rustc_trait_selection::regions::InferCtxtRegionExt;
|
2023-09-28 20:51:48 +00:00
|
|
|
use rustc_trait_selection::traits::misc::{
|
2024-09-22 19:05:04 -04:00
|
|
|
ConstParamTyImplementationError, type_allowed_to_implement_const_param_ty,
|
2023-09-28 20:51:48 +00:00
|
|
|
};
|
2022-08-22 16:53:34 -03:00
|
|
|
use rustc_trait_selection::traits::outlives_bounds::InferCtxtExt as _;
|
2021-10-08 12:09:34 -04:00
|
|
|
use rustc_trait_selection::traits::query::evaluate_obligation::InferCtxtExt as _;
|
2022-07-07 15:12:32 +02:00
|
|
|
use rustc_trait_selection::traits::{
|
2024-10-20 19:49:11 +00:00
|
|
|
self, FulfillmentError, Obligation, ObligationCause, ObligationCauseCode, ObligationCtxt,
|
|
|
|
|
WellFormedLoc,
|
2022-07-07 15:12:32 +02:00
|
|
|
};
|
2023-11-06 15:46:17 +00:00
|
|
|
use rustc_type_ir::TypeFlags;
|
2024-09-22 19:05:04 -04:00
|
|
|
use rustc_type_ir::solve::NoSolution;
|
2024-08-30 09:02:58 +10:00
|
|
|
use tracing::{debug, instrument};
|
2024-07-29 08:13:50 +10:00
|
|
|
use {rustc_ast as ast, rustc_hir as hir};
|
2016-06-21 18:08:13 -04:00
|
|
|
|
2024-07-29 08:13:50 +10:00
|
|
|
use crate::autoderef::Autoderef;
|
|
|
|
|
use crate::collect::CollectItemTypesVisitor;
|
2024-09-22 19:05:04 -04:00
|
|
|
use crate::constrained_generic_params::{Parameter, identify_constrained_generic_params};
|
2024-07-29 08:13:50 +10:00
|
|
|
use crate::{errors, fluent_generated as fluent};
|
2020-10-21 14:26:34 +02:00
|
|
|
|
2022-07-07 15:12:32 +02:00
|
|
|
pub(super) struct WfCheckingCtxt<'a, 'tcx> {
|
2024-06-01 14:51:31 -04:00
|
|
|
pub(super) ocx: ObligationCtxt<'a, 'tcx, FulfillmentError<'tcx>>,
|
2017-05-23 04:19:47 -04:00
|
|
|
span: Span,
|
2023-01-15 12:58:46 +01:00
|
|
|
body_def_id: LocalDefId,
|
2017-05-23 04:19:47 -04:00
|
|
|
param_env: ty::ParamEnv<'tcx>,
|
2016-05-11 04:14:41 +03:00
|
|
|
}
|
2022-07-07 15:12:32 +02:00
|
|
|
impl<'a, 'tcx> Deref for WfCheckingCtxt<'a, 'tcx> {
|
2024-06-01 14:51:31 -04:00
|
|
|
type Target = ObligationCtxt<'a, 'tcx, FulfillmentError<'tcx>>;
|
2022-07-07 15:12:32 +02:00
|
|
|
fn deref(&self) -> &Self::Target {
|
|
|
|
|
&self.ocx
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
impl<'tcx> WfCheckingCtxt<'_, 'tcx> {
|
|
|
|
|
fn tcx(&self) -> TyCtxt<'tcx> {
|
|
|
|
|
self.ocx.infcx.tcx
|
|
|
|
|
}
|
2016-05-11 04:14:41 +03:00
|
|
|
|
2022-11-25 17:28:50 +00:00
|
|
|
// Convenience function to normalize during wfcheck. This performs
|
|
|
|
|
// `ObligationCtxt::normalize`, but provides a nice `ObligationCauseCode`.
|
2022-07-07 15:12:32 +02:00
|
|
|
fn normalize<T>(&self, span: Span, loc: Option<WellFormedLoc>, value: T) -> T
|
2019-06-12 00:11:55 +03:00
|
|
|
where
|
2023-02-22 02:18:40 +00:00
|
|
|
T: TypeFoldable<TyCtxt<'tcx>>,
|
2016-05-11 04:14:41 +03:00
|
|
|
{
|
2022-07-07 15:12:32 +02:00
|
|
|
self.ocx.normalize(
|
2023-01-15 12:58:46 +01:00
|
|
|
&ObligationCause::new(span, self.body_def_id, ObligationCauseCode::WellFormed(loc)),
|
2022-07-07 15:12:32 +02:00
|
|
|
self.param_env,
|
|
|
|
|
value,
|
|
|
|
|
)
|
|
|
|
|
}
|
2022-06-27 18:46:16 +02:00
|
|
|
|
2022-07-07 15:12:32 +02:00
|
|
|
fn register_wf_obligation(
|
|
|
|
|
&self,
|
|
|
|
|
span: Span,
|
|
|
|
|
loc: Option<WellFormedLoc>,
|
|
|
|
|
arg: ty::GenericArg<'tcx>,
|
|
|
|
|
) {
|
2023-01-15 12:58:46 +01:00
|
|
|
let cause = traits::ObligationCause::new(
|
|
|
|
|
span,
|
|
|
|
|
self.body_def_id,
|
|
|
|
|
ObligationCauseCode::WellFormed(loc),
|
|
|
|
|
);
|
2024-10-20 19:49:11 +00:00
|
|
|
self.ocx.register_obligation(Obligation::new(
|
2022-11-09 10:49:28 +00:00
|
|
|
self.tcx(),
|
2022-07-07 15:12:32 +02:00
|
|
|
cause,
|
2023-07-27 15:50:42 +00:00
|
|
|
self.param_env,
|
2023-06-16 05:59:42 +00:00
|
|
|
ty::Binder::dummy(ty::PredicateKind::Clause(ty::ClauseKind::WellFormed(arg))),
|
2022-07-07 15:12:32 +02:00
|
|
|
));
|
2016-05-11 04:14:41 +03:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2022-07-07 15:12:32 +02:00
|
|
|
pub(super) fn enter_wf_checking_ctxt<'tcx, F>(
|
|
|
|
|
tcx: TyCtxt<'tcx>,
|
|
|
|
|
span: Span,
|
|
|
|
|
body_def_id: LocalDefId,
|
|
|
|
|
f: F,
|
2023-10-18 08:47:17 +00:00
|
|
|
) -> Result<(), ErrorGuaranteed>
|
|
|
|
|
where
|
2023-10-30 15:54:08 +00:00
|
|
|
F: for<'a> FnOnce(&WfCheckingCtxt<'a, 'tcx>) -> Result<(), ErrorGuaranteed>,
|
2022-07-07 15:12:32 +02:00
|
|
|
{
|
|
|
|
|
let param_env = tcx.param_env(body_def_id);
|
2024-10-18 00:28:43 +02:00
|
|
|
let infcx = &tcx.infer_ctxt().build(TypingMode::non_body_analysis());
|
2024-06-01 14:51:31 -04:00
|
|
|
let ocx = ObligationCtxt::new_with_diagnostics(infcx);
|
2022-08-17 12:22:32 +02:00
|
|
|
|
2023-01-15 12:58:46 +01:00
|
|
|
let mut wfcx = WfCheckingCtxt { ocx, span, body_def_id, param_env };
|
2022-07-07 15:12:32 +02:00
|
|
|
|
2024-10-09 09:01:57 +02:00
|
|
|
if !tcx.features().trivial_bounds() {
|
2022-09-19 22:03:59 -05:00
|
|
|
wfcx.check_false_global_bounds()
|
|
|
|
|
}
|
2023-10-30 15:54:08 +00:00
|
|
|
f(&mut wfcx)?;
|
2023-01-08 03:14:27 +00:00
|
|
|
|
2022-09-19 22:03:59 -05:00
|
|
|
let errors = wfcx.select_all_or_error();
|
|
|
|
|
if !errors.is_empty() {
|
2024-06-17 08:53:45 +00:00
|
|
|
return Err(infcx.err_ctxt().report_fulfillment_errors(errors));
|
2022-09-19 22:03:59 -05:00
|
|
|
}
|
2022-07-07 15:12:32 +02:00
|
|
|
|
2024-11-27 21:27:37 +00:00
|
|
|
let assumed_wf_types = wfcx.ocx.assumed_wf_types_and_report_errors(param_env, body_def_id)?;
|
2024-01-16 18:39:00 -05:00
|
|
|
debug!(?assumed_wf_types);
|
|
|
|
|
|
2023-12-10 20:13:21 -05:00
|
|
|
let infcx_compat = infcx.fork();
|
|
|
|
|
|
2024-01-16 18:39:00 -05:00
|
|
|
// We specifically want to call the non-compat version of `implied_bounds_tys`; we do this always.
|
|
|
|
|
let implied_bounds =
|
|
|
|
|
infcx.implied_bounds_tys_compat(param_env, body_def_id, &assumed_wf_types, false);
|
2023-04-12 10:24:36 +02:00
|
|
|
let outlives_env = OutlivesEnvironment::with_bounds(param_env, implied_bounds);
|
2022-07-29 15:08:50 +08:00
|
|
|
|
2023-11-29 02:41:31 +00:00
|
|
|
lint_redundant_lifetimes(tcx, body_def_id, &outlives_env);
|
|
|
|
|
|
2023-12-10 20:13:21 -05:00
|
|
|
let errors = infcx.resolve_regions(&outlives_env);
|
|
|
|
|
if errors.is_empty() {
|
|
|
|
|
return Ok(());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
let is_bevy = 'is_bevy: {
|
|
|
|
|
// We don't want to emit this for dependents of Bevy, for now.
|
|
|
|
|
// See #119956
|
|
|
|
|
let is_bevy_paramset = |def: ty::AdtDef<'_>| {
|
|
|
|
|
let adt_did = with_no_trimmed_paths!(infcx.tcx.def_path_str(def.0.did));
|
|
|
|
|
adt_did.contains("ParamSet")
|
|
|
|
|
};
|
|
|
|
|
for ty in assumed_wf_types.iter() {
|
|
|
|
|
match ty.kind() {
|
|
|
|
|
ty::Adt(def, _) => {
|
|
|
|
|
if is_bevy_paramset(*def) {
|
|
|
|
|
break 'is_bevy true;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
ty::Ref(_, ty, _) => match ty.kind() {
|
|
|
|
|
ty::Adt(def, _) => {
|
|
|
|
|
if is_bevy_paramset(*def) {
|
|
|
|
|
break 'is_bevy true;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
_ => {}
|
|
|
|
|
},
|
|
|
|
|
_ => {}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
false
|
|
|
|
|
};
|
|
|
|
|
|
2024-01-16 18:39:00 -05:00
|
|
|
// If we have set `no_implied_bounds_compat`, then do not attempt compatibility.
|
|
|
|
|
// We could also just always enter if `is_bevy`, and call `implied_bounds_tys`,
|
|
|
|
|
// but that does result in slightly more work when this option is set and
|
|
|
|
|
// just obscures what we mean here anyways. Let's just be explicit.
|
|
|
|
|
if is_bevy && !infcx.tcx.sess.opts.unstable_opts.no_implied_bounds_compat {
|
2023-12-10 20:13:21 -05:00
|
|
|
let implied_bounds =
|
2024-01-16 18:39:00 -05:00
|
|
|
infcx_compat.implied_bounds_tys_compat(param_env, body_def_id, &assumed_wf_types, true);
|
2023-12-10 20:13:21 -05:00
|
|
|
let outlives_env = OutlivesEnvironment::with_bounds(param_env, implied_bounds);
|
|
|
|
|
let errors_compat = infcx_compat.resolve_regions(&outlives_env);
|
|
|
|
|
if errors_compat.is_empty() {
|
|
|
|
|
Ok(())
|
|
|
|
|
} else {
|
|
|
|
|
Err(infcx_compat.err_ctxt().report_region_errors(body_def_id, &errors_compat))
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
Err(infcx.err_ctxt().report_region_errors(body_def_id, &errors))
|
|
|
|
|
}
|
2022-07-07 15:12:32 +02:00
|
|
|
}
|
|
|
|
|
|
2024-08-18 14:33:03 +00:00
|
|
|
fn check_well_formed(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Result<(), ErrorGuaranteed> {
|
|
|
|
|
let node = tcx.hir_node_by_def_id(def_id);
|
2023-10-18 08:47:17 +00:00
|
|
|
let mut res = match node {
|
2024-08-18 14:33:03 +00:00
|
|
|
hir::Node::Crate(_) => bug!("check_well_formed cannot be applied to the crate root"),
|
|
|
|
|
hir::Node::Item(item) => check_item(tcx, item),
|
|
|
|
|
hir::Node::TraitItem(item) => check_trait_item(tcx, item),
|
|
|
|
|
hir::Node::ImplItem(item) => check_impl_item(tcx, item),
|
|
|
|
|
hir::Node::ForeignItem(item) => check_foreign_item(tcx, item),
|
|
|
|
|
hir::Node::OpaqueTy(_) => Ok(crate::check::check::check_item_type(tcx, def_id)),
|
|
|
|
|
_ => unreachable!(),
|
2023-10-18 08:47:17 +00:00
|
|
|
};
|
2022-06-12 00:47:21 +02:00
|
|
|
|
|
|
|
|
if let Some(generics) = node.generics() {
|
|
|
|
|
for param in generics.params {
|
2023-10-18 08:47:17 +00:00
|
|
|
res = res.and(check_param_wf(tcx, param));
|
2022-06-12 00:47:21 +02:00
|
|
|
}
|
|
|
|
|
}
|
2024-08-18 14:33:03 +00:00
|
|
|
|
2023-10-18 08:47:17 +00:00
|
|
|
res
|
2022-06-12 00:47:21 +02:00
|
|
|
}
|
|
|
|
|
|
2018-03-12 22:18:51 -04:00
|
|
|
/// Checks that the field types (in a struct def'n) or argument types (in an enum def'n) are
|
|
|
|
|
/// well-formed, meaning that they do not require any constraints not declared in the struct
|
|
|
|
|
/// definition itself. For example, this definition would be illegal:
|
|
|
|
|
///
|
2019-02-28 22:43:53 +00:00
|
|
|
/// ```rust
|
|
|
|
|
/// struct Ref<'a, T> { x: &'a T }
|
|
|
|
|
/// ```
|
2018-03-12 22:18:51 -04:00
|
|
|
///
|
|
|
|
|
/// because the type did not declare that `T:'a`.
|
|
|
|
|
///
|
|
|
|
|
/// We do this check as a pre-pass before checking fn bodies because if these constraints are
|
|
|
|
|
/// not included it frequently leads to confusing errors in fn bodies. So it's better to check
|
|
|
|
|
/// the types first.
|
2021-09-16 19:08:25 +00:00
|
|
|
#[instrument(skip(tcx), level = "debug")]
|
2023-10-18 08:47:17 +00:00
|
|
|
fn check_item<'tcx>(tcx: TyCtxt<'tcx>, item: &'tcx hir::Item<'tcx>) -> Result<(), ErrorGuaranteed> {
|
2022-10-27 14:02:18 +11:00
|
|
|
let def_id = item.owner_id.def_id;
|
2018-03-12 22:18:51 -04:00
|
|
|
|
2019-12-24 17:38:22 -05:00
|
|
|
debug!(
|
2022-10-27 14:02:18 +11:00
|
|
|
?item.owner_id,
|
2023-02-16 09:25:11 +00:00
|
|
|
item.name = ? tcx.def_path_str(def_id)
|
2019-12-24 17:38:22 -05:00
|
|
|
);
|
2024-02-23 11:45:44 +00:00
|
|
|
CollectItemTypesVisitor { tcx }.visit_item(item);
|
2018-03-12 22:18:51 -04:00
|
|
|
|
2023-10-26 11:36:49 +00:00
|
|
|
let res = match item.kind {
|
2018-03-12 22:18:51 -04:00
|
|
|
// Right now we check that every default trait implementation
|
|
|
|
|
// has an implementation of itself. Basically, a case like:
|
|
|
|
|
//
|
2019-02-28 22:43:53 +00:00
|
|
|
// impl Trait for T {}
|
2018-03-12 22:18:51 -04:00
|
|
|
//
|
|
|
|
|
// has a requirement of `T: Trait` which was required for default
|
|
|
|
|
// method implementations. Although this could be improved now that
|
|
|
|
|
// there's a better infrastructure in place for this, it's being left
|
|
|
|
|
// for a follow-up work.
|
|
|
|
|
//
|
|
|
|
|
// Since there's such a requirement, we need to check *just* positive
|
|
|
|
|
// implementations, otherwise things like:
|
|
|
|
|
//
|
2019-02-28 22:43:53 +00:00
|
|
|
// impl !Send for T {}
|
2018-03-12 22:18:51 -04:00
|
|
|
//
|
|
|
|
|
// won't be allowed unless there's an *explicit* implementation of `Send`
|
|
|
|
|
// for `T`
|
2023-01-09 16:30:40 +00:00
|
|
|
hir::ItemKind::Impl(impl_) => {
|
2024-02-10 22:27:03 +00:00
|
|
|
let header = tcx.impl_trait_header(def_id);
|
|
|
|
|
let is_auto = header
|
2024-03-05 20:19:05 +01:00
|
|
|
.is_some_and(|header| tcx.trait_is_auto(header.trait_ref.skip_binder().def_id));
|
2024-02-15 17:12:05 +00:00
|
|
|
|
|
|
|
|
crate::impl_wf_check::check_impl_wf(tcx, def_id)?;
|
2023-10-18 08:47:17 +00:00
|
|
|
let mut res = Ok(());
|
2020-11-22 17:46:21 -05:00
|
|
|
if let (hir::Defaultness::Default { .. }, true) = (impl_.defaultness, is_auto) {
|
2021-01-11 20:45:33 +01:00
|
|
|
let sp = impl_.of_trait.as_ref().map_or(item.span, |t| t.path.span);
|
2024-01-03 17:03:10 +11:00
|
|
|
res = Err(tcx
|
|
|
|
|
.dcx()
|
|
|
|
|
.struct_span_err(sp, "impls of auto traits cannot be default")
|
2024-01-09 09:08:49 +11:00
|
|
|
.with_span_labels(impl_.defaultness_span, "default because of this")
|
|
|
|
|
.with_span_label(sp, "auto trait")
|
2024-01-03 17:03:10 +11:00
|
|
|
.emit());
|
2015-08-07 09:39:54 -04:00
|
|
|
}
|
2020-03-02 15:26:00 -08:00
|
|
|
// We match on both `ty::ImplPolarity` and `ast::ImplPolarity` just to get the `!` span.
|
2024-03-05 20:19:05 +01:00
|
|
|
match header.map(|h| h.polarity) {
|
2024-02-10 22:27:03 +00:00
|
|
|
// `None` means this is an inherent impl
|
|
|
|
|
Some(ty::ImplPolarity::Positive) | None => {
|
2023-10-18 08:47:17 +00:00
|
|
|
res = res.and(check_impl(tcx, item, impl_.self_ty, &impl_.of_trait));
|
2019-07-14 00:09:46 +03:00
|
|
|
}
|
2024-02-10 22:27:03 +00:00
|
|
|
Some(ty::ImplPolarity::Negative) => {
|
2023-12-15 03:19:46 +00:00
|
|
|
let ast::ImplPolarity::Negative(span) = impl_.polarity else {
|
2024-02-11 09:22:52 +01:00
|
|
|
bug!("impl_polarity query disagrees with impl's polarity in HIR");
|
2023-12-15 03:19:46 +00:00
|
|
|
};
|
2019-07-14 00:09:46 +03:00
|
|
|
// FIXME(#27579): what amount of WF checking do we need for neg impls?
|
2020-11-22 17:46:21 -05:00
|
|
|
if let hir::Defaultness::Default { .. } = impl_.defaultness {
|
2020-01-08 06:39:38 -05:00
|
|
|
let mut spans = vec![span];
|
2020-11-22 17:46:21 -05:00
|
|
|
spans.extend(impl_.defaultness_span);
|
2024-01-04 09:08:36 +11:00
|
|
|
res = Err(struct_span_code_err!(
|
2023-12-18 22:21:37 +11:00
|
|
|
tcx.dcx(),
|
2020-01-08 06:39:38 -05:00
|
|
|
spans,
|
|
|
|
|
E0750,
|
|
|
|
|
"negative impls cannot be default impls"
|
2020-03-02 15:26:00 -08:00
|
|
|
)
|
2023-10-18 08:47:17 +00:00
|
|
|
.emit());
|
2019-07-14 00:09:46 +03:00
|
|
|
}
|
|
|
|
|
}
|
2024-02-10 22:27:03 +00:00
|
|
|
Some(ty::ImplPolarity::Reservation) => {
|
2019-07-14 00:09:46 +03:00
|
|
|
// FIXME: what amount of WF checking do we need for reservation impls?
|
2018-03-12 22:18:51 -04:00
|
|
|
}
|
2015-08-07 09:39:54 -04:00
|
|
|
}
|
2023-10-18 08:47:17 +00:00
|
|
|
res
|
2018-03-12 22:18:51 -04:00
|
|
|
}
|
2020-06-13 19:37:25 +01:00
|
|
|
hir::ItemKind::Fn(ref sig, ..) => {
|
2023-10-18 08:47:17 +00:00
|
|
|
check_item_fn(tcx, def_id, item.ident, item.span, sig.decl)
|
2018-03-12 22:18:51 -04:00
|
|
|
}
|
2021-09-30 19:38:50 +02:00
|
|
|
hir::ItemKind::Static(ty, ..) => {
|
2023-10-18 08:47:17 +00:00
|
|
|
check_item_type(tcx, def_id, ty.span, UnsizedHandling::Forbid)
|
2018-03-12 22:18:51 -04:00
|
|
|
}
|
2021-09-30 19:38:50 +02:00
|
|
|
hir::ItemKind::Const(ty, ..) => {
|
2023-10-18 08:47:17 +00:00
|
|
|
check_item_type(tcx, def_id, ty.span, UnsizedHandling::Forbid)
|
2018-03-12 22:18:51 -04:00
|
|
|
}
|
2024-03-01 12:33:14 +01:00
|
|
|
hir::ItemKind::Struct(_, hir_generics) => {
|
2023-10-18 08:47:17 +00:00
|
|
|
let res = check_type_defn(tcx, item, false);
|
2024-03-01 12:33:14 +01:00
|
|
|
check_variances_for_type_defn(tcx, item, hir_generics);
|
2023-10-18 08:47:17 +00:00
|
|
|
res
|
2018-03-12 22:18:51 -04:00
|
|
|
}
|
2024-03-01 12:33:14 +01:00
|
|
|
hir::ItemKind::Union(_, hir_generics) => {
|
2023-10-18 08:47:17 +00:00
|
|
|
let res = check_type_defn(tcx, item, true);
|
2024-03-01 12:33:14 +01:00
|
|
|
check_variances_for_type_defn(tcx, item, hir_generics);
|
2023-10-18 08:47:17 +00:00
|
|
|
res
|
2018-03-12 22:18:51 -04:00
|
|
|
}
|
2024-03-01 12:33:14 +01:00
|
|
|
hir::ItemKind::Enum(_, hir_generics) => {
|
2023-10-18 08:47:17 +00:00
|
|
|
let res = check_type_defn(tcx, item, true);
|
2024-03-01 12:33:14 +01:00
|
|
|
check_variances_for_type_defn(tcx, item, hir_generics);
|
2023-10-18 08:47:17 +00:00
|
|
|
res
|
2015-08-07 09:39:54 -04:00
|
|
|
}
|
2023-10-18 08:47:17 +00:00
|
|
|
hir::ItemKind::Trait(..) => check_trait(tcx, item),
|
|
|
|
|
hir::ItemKind::TraitAlias(..) => check_trait(tcx, item),
|
2022-06-12 00:47:21 +02:00
|
|
|
// `ForeignItem`s are handled separately.
|
2023-10-18 08:47:17 +00:00
|
|
|
hir::ItemKind::ForeignMod { .. } => Ok(()),
|
2024-03-01 12:33:14 +01:00
|
|
|
hir::ItemKind::TyAlias(hir_ty, hir_generics) => {
|
2023-09-26 02:15:32 +00:00
|
|
|
if tcx.type_alias_is_lazy(item.owner_id) {
|
2023-07-30 01:46:20 +02:00
|
|
|
// Bounds of lazy type aliases and of eager ones that contain opaque types are respected.
|
|
|
|
|
// E.g: `type X = impl Trait;`, `type X = (impl Trait, Y);`.
|
2023-10-18 08:47:17 +00:00
|
|
|
let res = check_item_type(tcx, def_id, hir_ty.span, UnsizedHandling::Allow);
|
2024-03-01 12:33:14 +01:00
|
|
|
check_variances_for_type_defn(tcx, item, hir_generics);
|
2023-10-18 08:47:17 +00:00
|
|
|
res
|
|
|
|
|
} else {
|
|
|
|
|
Ok(())
|
2023-03-07 12:03:11 +00:00
|
|
|
}
|
|
|
|
|
}
|
2023-10-18 08:47:17 +00:00
|
|
|
_ => Ok(()),
|
2023-10-26 11:36:49 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
crate::check::check::check_item_type(tcx, def_id);
|
|
|
|
|
|
|
|
|
|
res
|
2018-03-12 22:18:51 -04:00
|
|
|
}
|
2015-08-07 09:39:54 -04:00
|
|
|
|
2024-02-23 11:45:44 +00:00
|
|
|
fn check_foreign_item<'tcx>(
|
|
|
|
|
tcx: TyCtxt<'tcx>,
|
|
|
|
|
item: &'tcx hir::ForeignItem<'tcx>,
|
|
|
|
|
) -> Result<(), ErrorGuaranteed> {
|
2022-10-27 14:02:18 +11:00
|
|
|
let def_id = item.owner_id.def_id;
|
2022-06-12 00:47:21 +02:00
|
|
|
|
2024-02-23 11:45:44 +00:00
|
|
|
CollectItemTypesVisitor { tcx }.visit_foreign_item(item);
|
|
|
|
|
|
2022-06-12 00:47:21 +02:00
|
|
|
debug!(
|
2022-10-27 14:02:18 +11:00
|
|
|
?item.owner_id,
|
2023-02-16 09:25:11 +00:00
|
|
|
item.name = ? tcx.def_path_str(def_id)
|
2022-06-12 00:47:21 +02:00
|
|
|
);
|
|
|
|
|
|
|
|
|
|
match item.kind {
|
2024-08-07 13:01:34 -04:00
|
|
|
hir::ForeignItemKind::Fn(sig, ..) => {
|
|
|
|
|
check_item_fn(tcx, def_id, item.ident, item.span, sig.decl)
|
2022-06-12 00:47:21 +02:00
|
|
|
}
|
2023-03-07 12:03:11 +00:00
|
|
|
hir::ForeignItemKind::Static(ty, ..) => {
|
|
|
|
|
check_item_type(tcx, def_id, ty.span, UnsizedHandling::AllowIfForeignTail)
|
|
|
|
|
}
|
2023-10-18 08:47:17 +00:00
|
|
|
hir::ForeignItemKind::Type => Ok(()),
|
2022-06-12 00:47:21 +02:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2024-02-23 11:45:44 +00:00
|
|
|
fn check_trait_item<'tcx>(
|
|
|
|
|
tcx: TyCtxt<'tcx>,
|
|
|
|
|
trait_item: &'tcx hir::TraitItem<'tcx>,
|
2023-10-18 08:47:17 +00:00
|
|
|
) -> Result<(), ErrorGuaranteed> {
|
2022-10-27 14:02:18 +11:00
|
|
|
let def_id = trait_item.owner_id.def_id;
|
2018-03-10 11:25:03 -05:00
|
|
|
|
2024-02-23 11:45:44 +00:00
|
|
|
CollectItemTypesVisitor { tcx }.visit_trait_item(trait_item);
|
|
|
|
|
|
2021-08-06 15:46:20 +00:00
|
|
|
let (method_sig, span) = match trait_item.kind {
|
|
|
|
|
hir::TraitItemKind::Fn(ref sig, _) => (Some(sig), trait_item.span),
|
|
|
|
|
hir::TraitItemKind::Type(_bounds, Some(ty)) => (None, ty.span),
|
|
|
|
|
_ => (None, trait_item.span),
|
2018-03-12 22:18:51 -04:00
|
|
|
};
|
2024-09-25 10:38:40 +02:00
|
|
|
check_dyn_incompatible_self_trait_by_name(tcx, trait_item);
|
2024-10-24 16:25:02 +00:00
|
|
|
let mut res = check_associated_item(tcx, def_id, span, method_sig);
|
2023-07-14 18:37:12 +00:00
|
|
|
|
|
|
|
|
if matches!(trait_item.kind, hir::TraitItemKind::Fn(..)) {
|
|
|
|
|
for &assoc_ty_def_id in tcx.associated_types_for_impl_traits_in_associated_fn(def_id) {
|
2023-10-18 08:47:17 +00:00
|
|
|
res = res.and(check_associated_item(
|
2023-07-14 18:37:12 +00:00
|
|
|
tcx,
|
|
|
|
|
assoc_ty_def_id.expect_local(),
|
|
|
|
|
tcx.def_span(assoc_ty_def_id),
|
|
|
|
|
None,
|
2023-10-18 08:47:17 +00:00
|
|
|
));
|
2023-07-14 18:37:12 +00:00
|
|
|
}
|
|
|
|
|
}
|
2023-10-18 08:47:17 +00:00
|
|
|
res
|
2021-10-08 12:09:34 -04:00
|
|
|
}
|
|
|
|
|
|
2021-11-05 21:33:14 -04:00
|
|
|
/// Require that the user writes where clauses on GATs for the implicit
|
2021-10-08 12:09:34 -04:00
|
|
|
/// outlives bounds involving trait parameters in trait functions and
|
2023-07-11 22:35:29 +01:00
|
|
|
/// lifetimes passed as GAT args. See `self-outlives-lint` test.
|
2022-02-12 14:55:53 -08:00
|
|
|
///
|
|
|
|
|
/// We use the following trait as an example throughout this function:
|
|
|
|
|
/// ```rust,ignore (this code fails due to this lint)
|
|
|
|
|
/// trait IntoIter {
|
|
|
|
|
/// type Iter<'a>: Iterator<Item = Self::Item<'a>>;
|
|
|
|
|
/// type Item<'a>;
|
|
|
|
|
/// fn into_iter<'a>(&'a self) -> Self::Iter<'a>;
|
|
|
|
|
/// }
|
2021-10-31 21:36:04 -04:00
|
|
|
/// ```
|
2023-10-16 15:39:07 +00:00
|
|
|
fn check_gat_where_clauses(tcx: TyCtxt<'_>, trait_def_id: LocalDefId) {
|
2022-02-12 14:55:53 -08:00
|
|
|
// Associates every GAT's def_id to a list of possibly missing bounds detected by this lint.
|
2024-10-02 08:25:55 +03:00
|
|
|
let mut required_bounds_by_item = FxIndexMap::default();
|
2023-10-16 15:39:07 +00:00
|
|
|
let associated_items = tcx.associated_items(trait_def_id);
|
2022-02-12 14:55:53 -08:00
|
|
|
|
|
|
|
|
// Loop over all GATs together, because if this lint suggests adding a where-clause bound
|
|
|
|
|
// to one GAT, it might then require us to an additional bound on another GAT.
|
|
|
|
|
// In our `IntoIter` example, we discover a missing `Self: 'a` bound on `Iter<'a>`, which
|
|
|
|
|
// then in a second loop adds a `Self: 'a` bound to `Item` due to the relationship between
|
|
|
|
|
// those GATs.
|
2022-02-11 00:17:22 -08:00
|
|
|
loop {
|
|
|
|
|
let mut should_continue = false;
|
2023-10-16 15:39:07 +00:00
|
|
|
for gat_item in associated_items.in_definition_order() {
|
|
|
|
|
let gat_def_id = gat_item.def_id.expect_local();
|
2022-02-11 00:17:22 -08:00
|
|
|
let gat_item = tcx.associated_item(gat_def_id);
|
2023-07-11 22:35:29 +01:00
|
|
|
// If this item is not an assoc ty, or has no args, then it's not a GAT
|
2022-02-11 00:17:22 -08:00
|
|
|
if gat_item.kind != ty::AssocKind::Type {
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
let gat_generics = tcx.generics_of(gat_def_id);
|
2022-02-12 14:55:53 -08:00
|
|
|
// FIXME(jackh726): we can also warn in the more general case
|
2024-05-11 11:46:25 +02:00
|
|
|
if gat_generics.is_own_empty() {
|
2022-02-11 00:08:17 -08:00
|
|
|
continue;
|
|
|
|
|
}
|
2021-10-16 02:29:59 -04:00
|
|
|
|
2022-02-12 14:55:53 -08:00
|
|
|
// Gather the bounds with which all other items inside of this trait constrain the GAT.
|
|
|
|
|
// This is calculated by taking the intersection of the bounds that each item
|
|
|
|
|
// constrains the GAT with individually.
|
2024-10-02 08:25:55 +03:00
|
|
|
let mut new_required_bounds: Option<FxIndexSet<ty::Clause<'_>>> = None;
|
2023-10-16 15:39:07 +00:00
|
|
|
for item in associated_items.in_definition_order() {
|
|
|
|
|
let item_def_id = item.def_id.expect_local();
|
2022-02-12 14:55:53 -08:00
|
|
|
// Skip our own GAT, since it does not constrain itself at all.
|
2022-02-11 00:17:22 -08:00
|
|
|
if item_def_id == gat_def_id {
|
|
|
|
|
continue;
|
2022-02-11 00:11:49 -08:00
|
|
|
}
|
2022-02-11 00:17:22 -08:00
|
|
|
|
|
|
|
|
let param_env = tcx.param_env(item_def_id);
|
|
|
|
|
|
2023-10-16 15:39:07 +00:00
|
|
|
let item_required_bounds = match tcx.associated_item(item_def_id).kind {
|
2022-02-12 14:55:53 -08:00
|
|
|
// In our example, this corresponds to `into_iter` method
|
2023-10-16 15:39:07 +00:00
|
|
|
ty::AssocKind::Fn => {
|
2022-02-12 14:55:53 -08:00
|
|
|
// For methods, we check the function signature's return type for any GATs
|
|
|
|
|
// to constrain. In the `into_iter` case, we see that the return type
|
|
|
|
|
// `Self::Iter<'a>` is a GAT we want to gather any potential missing bounds from.
|
2022-02-11 00:17:22 -08:00
|
|
|
let sig: ty::FnSig<'_> = tcx.liberate_late_bound_regions(
|
|
|
|
|
item_def_id.to_def_id(),
|
2023-07-11 22:35:29 +01:00
|
|
|
tcx.fn_sig(item_def_id).instantiate_identity(),
|
2022-02-11 00:17:22 -08:00
|
|
|
);
|
|
|
|
|
gather_gat_bounds(
|
|
|
|
|
tcx,
|
|
|
|
|
param_env,
|
2022-11-05 15:33:58 +00:00
|
|
|
item_def_id,
|
2022-08-09 20:23:40 -04:00
|
|
|
sig.inputs_and_output,
|
2022-02-12 14:55:53 -08:00
|
|
|
// We also assume that all of the function signature's parameter types
|
|
|
|
|
// are well formed.
|
2022-02-11 00:17:22 -08:00
|
|
|
&sig.inputs().iter().copied().collect(),
|
2023-10-16 15:39:07 +00:00
|
|
|
gat_def_id,
|
2022-02-11 00:17:22 -08:00
|
|
|
gat_generics,
|
|
|
|
|
)
|
|
|
|
|
}
|
2022-02-12 14:55:53 -08:00
|
|
|
// In our example, this corresponds to the `Iter` and `Item` associated types
|
2023-10-16 15:39:07 +00:00
|
|
|
ty::AssocKind::Type => {
|
2022-02-11 00:17:22 -08:00
|
|
|
// If our associated item is a GAT with missing bounds, add them to
|
|
|
|
|
// the param-env here. This allows this GAT to propagate missing bounds
|
|
|
|
|
// to other GATs.
|
|
|
|
|
let param_env = augment_param_env(
|
|
|
|
|
tcx,
|
|
|
|
|
param_env,
|
|
|
|
|
required_bounds_by_item.get(&item_def_id),
|
|
|
|
|
);
|
|
|
|
|
gather_gat_bounds(
|
|
|
|
|
tcx,
|
|
|
|
|
param_env,
|
2022-11-05 15:33:58 +00:00
|
|
|
item_def_id,
|
2023-04-17 16:43:46 -06:00
|
|
|
tcx.explicit_item_bounds(item_def_id)
|
2024-07-06 11:54:22 -04:00
|
|
|
.iter_identity_copied()
|
2023-04-17 15:57:29 -06:00
|
|
|
.collect::<Vec<_>>(),
|
2022-10-28 23:32:41 +02:00
|
|
|
&FxIndexSet::default(),
|
2023-10-16 15:39:07 +00:00
|
|
|
gat_def_id,
|
2022-02-11 00:17:22 -08:00
|
|
|
gat_generics,
|
|
|
|
|
)
|
|
|
|
|
}
|
2023-10-16 15:39:07 +00:00
|
|
|
ty::AssocKind::Const => None,
|
2022-02-11 00:17:22 -08:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
if let Some(item_required_bounds) = item_required_bounds {
|
2022-02-12 14:55:53 -08:00
|
|
|
// Take the intersection of the required bounds for this GAT, and
|
|
|
|
|
// the item_required_bounds which are the ones implied by just
|
|
|
|
|
// this item alone.
|
|
|
|
|
// This is why we use an Option<_>, since we need to distinguish
|
|
|
|
|
// the empty set of bounds from the _uninitialized_ set of bounds.
|
2022-02-11 00:17:22 -08:00
|
|
|
if let Some(new_required_bounds) = &mut new_required_bounds {
|
|
|
|
|
new_required_bounds.retain(|b| item_required_bounds.contains(b));
|
|
|
|
|
} else {
|
|
|
|
|
new_required_bounds = Some(item_required_bounds);
|
|
|
|
|
}
|
2021-10-31 23:04:42 -04:00
|
|
|
}
|
2021-10-08 12:09:34 -04:00
|
|
|
}
|
2022-02-11 00:08:17 -08:00
|
|
|
|
2022-02-11 00:17:22 -08:00
|
|
|
if let Some(new_required_bounds) = new_required_bounds {
|
|
|
|
|
let required_bounds = required_bounds_by_item.entry(gat_def_id).or_default();
|
2022-02-12 14:55:53 -08:00
|
|
|
if new_required_bounds.into_iter().any(|p| required_bounds.insert(p)) {
|
2022-02-11 00:17:22 -08:00
|
|
|
// Iterate until our required_bounds no longer change
|
|
|
|
|
// Since they changed here, we should continue the loop
|
|
|
|
|
should_continue = true;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
2022-02-12 14:55:53 -08:00
|
|
|
// We know that this loop will eventually halt, since we only set `should_continue` if the
|
|
|
|
|
// `required_bounds` for this item grows. Since we are not creating any new region or type
|
|
|
|
|
// variables, the set of all region and type bounds that we could ever insert are limited
|
|
|
|
|
// by the number of unique types and regions we observe in a given item.
|
2022-02-11 00:17:22 -08:00
|
|
|
if !should_continue {
|
|
|
|
|
break;
|
2022-02-11 00:08:17 -08:00
|
|
|
}
|
2021-10-16 02:29:59 -04:00
|
|
|
}
|
|
|
|
|
|
2022-02-11 00:08:17 -08:00
|
|
|
for (gat_def_id, required_bounds) in required_bounds_by_item {
|
2023-10-16 15:39:07 +00:00
|
|
|
// Don't suggest adding `Self: 'a` to a GAT that can't be named
|
|
|
|
|
if tcx.is_impl_trait_in_trait(gat_def_id.to_def_id()) {
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
let gat_item_hir = tcx.hir().expect_trait_item(gat_def_id);
|
2022-02-11 00:08:17 -08:00
|
|
|
debug!(?required_bounds);
|
2022-02-10 23:42:28 -08:00
|
|
|
let param_env = tcx.param_env(gat_def_id);
|
2021-12-12 23:23:55 -05:00
|
|
|
|
2024-10-06 15:57:23 +03:00
|
|
|
let unsatisfied_bounds: Vec<_> = required_bounds
|
2021-12-13 01:10:39 -05:00
|
|
|
.into_iter()
|
|
|
|
|
.filter(|clause| match clause.kind().skip_binder() {
|
2023-06-22 18:17:13 +00:00
|
|
|
ty::ClauseKind::RegionOutlives(ty::OutlivesPredicate(a, b)) => {
|
|
|
|
|
!region_known_to_outlive(
|
|
|
|
|
tcx,
|
2023-10-16 15:39:07 +00:00
|
|
|
gat_def_id,
|
2023-06-22 18:17:13 +00:00
|
|
|
param_env,
|
|
|
|
|
&FxIndexSet::default(),
|
|
|
|
|
a,
|
|
|
|
|
b,
|
|
|
|
|
)
|
|
|
|
|
}
|
2023-10-16 15:39:07 +00:00
|
|
|
ty::ClauseKind::TypeOutlives(ty::OutlivesPredicate(a, b)) => {
|
|
|
|
|
!ty_known_to_outlive(tcx, gat_def_id, param_env, &FxIndexSet::default(), a, b)
|
|
|
|
|
}
|
2023-06-22 18:17:13 +00:00
|
|
|
_ => bug!("Unexpected ClauseKind"),
|
2021-12-13 01:10:39 -05:00
|
|
|
})
|
2022-02-11 00:08:17 -08:00
|
|
|
.map(|clause| clause.to_string())
|
2021-12-13 01:10:39 -05:00
|
|
|
.collect();
|
|
|
|
|
|
2022-02-11 00:08:17 -08:00
|
|
|
if !unsatisfied_bounds.is_empty() {
|
2022-07-27 10:09:06 +09:00
|
|
|
let plural = pluralize!(unsatisfied_bounds.len());
|
2021-12-13 01:10:39 -05:00
|
|
|
let suggestion = format!(
|
|
|
|
|
"{} {}",
|
2022-06-05 17:37:45 -07:00
|
|
|
gat_item_hir.generics.add_where_or_trailing_comma(),
|
2022-02-11 00:08:17 -08:00
|
|
|
unsatisfied_bounds.join(", "),
|
2021-12-13 01:10:39 -05:00
|
|
|
);
|
2022-02-11 00:08:17 -08:00
|
|
|
let bound =
|
|
|
|
|
if unsatisfied_bounds.len() > 1 { "these bounds are" } else { "this bound is" };
|
2024-01-03 17:03:10 +11:00
|
|
|
tcx.dcx()
|
|
|
|
|
.struct_span_err(
|
|
|
|
|
gat_item_hir.span,
|
|
|
|
|
format!("missing required bound{} on `{}`", plural, gat_item_hir.ident),
|
|
|
|
|
)
|
2024-01-09 09:08:49 +11:00
|
|
|
.with_span_suggestion(
|
2024-01-03 17:03:10 +11:00
|
|
|
gat_item_hir.generics.tail_span_for_predicate_suggestion(),
|
|
|
|
|
format!("add the required where clause{plural}"),
|
|
|
|
|
suggestion,
|
|
|
|
|
Applicability::MachineApplicable,
|
|
|
|
|
)
|
2024-01-09 09:08:49 +11:00
|
|
|
.with_note(format!(
|
2024-01-03 17:03:10 +11:00
|
|
|
"{bound} currently required to ensure that impls have maximum flexibility"
|
|
|
|
|
))
|
2024-01-09 09:08:49 +11:00
|
|
|
.with_note(
|
2024-01-03 17:03:10 +11:00
|
|
|
"we are soliciting feedback, see issue #87479 \
|
2024-01-09 09:08:49 +11:00
|
|
|
<https://github.com/rust-lang/rust/issues/87479> for more information",
|
2024-01-03 17:03:10 +11:00
|
|
|
)
|
|
|
|
|
.emit();
|
2021-12-13 01:10:39 -05:00
|
|
|
}
|
2021-10-07 17:00:39 -04:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2022-02-12 14:55:53 -08:00
|
|
|
/// Add a new set of predicates to the caller_bounds of an existing param_env.
|
2022-02-11 00:17:22 -08:00
|
|
|
fn augment_param_env<'tcx>(
|
|
|
|
|
tcx: TyCtxt<'tcx>,
|
|
|
|
|
param_env: ty::ParamEnv<'tcx>,
|
2024-10-02 08:25:55 +03:00
|
|
|
new_predicates: Option<&FxIndexSet<ty::Clause<'tcx>>>,
|
2022-02-11 00:17:22 -08:00
|
|
|
) -> ty::ParamEnv<'tcx> {
|
|
|
|
|
let Some(new_predicates) = new_predicates else {
|
|
|
|
|
return param_env;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
if new_predicates.is_empty() {
|
|
|
|
|
return param_env;
|
|
|
|
|
}
|
|
|
|
|
|
2023-06-22 18:17:13 +00:00
|
|
|
let bounds = tcx.mk_clauses_from_iter(
|
2023-02-17 14:33:08 +11:00
|
|
|
param_env.caller_bounds().iter().chain(new_predicates.iter().cloned()),
|
|
|
|
|
);
|
2022-02-11 00:17:22 -08:00
|
|
|
// FIXME(compiler-errors): Perhaps there is a case where we need to normalize this
|
|
|
|
|
// i.e. traits::normalize_param_env_or_error
|
2024-11-20 11:31:49 +01:00
|
|
|
ty::ParamEnv::new(bounds)
|
2022-02-11 00:17:22 -08:00
|
|
|
}
|
|
|
|
|
|
2022-02-12 14:55:53 -08:00
|
|
|
/// We use the following trait as an example throughout this function.
|
|
|
|
|
/// Specifically, let's assume that `to_check` here is the return type
|
|
|
|
|
/// of `into_iter`, and the GAT we are checking this for is `Iter`.
|
|
|
|
|
/// ```rust,ignore (this code fails due to this lint)
|
|
|
|
|
/// trait IntoIter {
|
|
|
|
|
/// type Iter<'a>: Iterator<Item = Self::Item<'a>>;
|
|
|
|
|
/// type Item<'a>;
|
|
|
|
|
/// fn into_iter<'a>(&'a self) -> Self::Iter<'a>;
|
|
|
|
|
/// }
|
|
|
|
|
/// ```
|
2023-02-22 02:18:40 +00:00
|
|
|
fn gather_gat_bounds<'tcx, T: TypeFoldable<TyCtxt<'tcx>>>(
|
2022-02-10 23:36:37 -08:00
|
|
|
tcx: TyCtxt<'tcx>,
|
|
|
|
|
param_env: ty::ParamEnv<'tcx>,
|
2023-10-16 15:39:07 +00:00
|
|
|
item_def_id: LocalDefId,
|
2022-02-10 23:36:37 -08:00
|
|
|
to_check: T,
|
2022-10-28 23:32:41 +02:00
|
|
|
wf_tys: &FxIndexSet<Ty<'tcx>>,
|
2022-02-10 23:36:37 -08:00
|
|
|
gat_def_id: LocalDefId,
|
|
|
|
|
gat_generics: &'tcx ty::Generics,
|
2024-10-02 08:25:55 +03:00
|
|
|
) -> Option<FxIndexSet<ty::Clause<'tcx>>> {
|
2022-02-12 14:55:53 -08:00
|
|
|
// The bounds we that we would require from `to_check`
|
2024-10-02 08:25:55 +03:00
|
|
|
let mut bounds = FxIndexSet::default();
|
2022-02-10 23:36:37 -08:00
|
|
|
|
2024-02-12 15:39:32 +09:00
|
|
|
let (regions, types) = GATArgsCollector::visit(gat_def_id.to_def_id(), to_check);
|
2022-02-10 23:36:37 -08:00
|
|
|
|
|
|
|
|
// If both regions and types are empty, then this GAT isn't in the
|
2022-02-12 14:55:53 -08:00
|
|
|
// set of types we are checking, and we shouldn't try to do clause analysis
|
2022-02-10 23:36:37 -08:00
|
|
|
// (particularly, doing so would end up with an empty set of clauses,
|
|
|
|
|
// since the current method would require none, and we take the
|
|
|
|
|
// intersection of requirements of all methods)
|
|
|
|
|
if types.is_empty() && regions.is_empty() {
|
|
|
|
|
return None;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
for (region_a, region_a_idx) in ®ions {
|
|
|
|
|
// Ignore `'static` lifetimes for the purpose of this lint: it's
|
2022-03-30 15:14:15 -04:00
|
|
|
// because we know it outlives everything and so doesn't give meaningful
|
2023-07-31 18:23:12 +00:00
|
|
|
// clues. Also ignore `ReError`, to avoid knock-down errors.
|
|
|
|
|
if let ty::ReStatic | ty::ReError(_) = **region_a {
|
2022-02-10 23:36:37 -08:00
|
|
|
continue;
|
|
|
|
|
}
|
2022-02-12 14:55:53 -08:00
|
|
|
// For each region argument (e.g., `'a` in our example), check for a
|
|
|
|
|
// relationship to the type arguments (e.g., `Self`). If there is an
|
2022-02-10 23:36:37 -08:00
|
|
|
// outlives relationship (`Self: 'a`), then we want to ensure that is
|
|
|
|
|
// reflected in a where clause on the GAT itself.
|
|
|
|
|
for (ty, ty_idx) in &types {
|
2022-02-12 14:55:53 -08:00
|
|
|
// In our example, requires that `Self: 'a`
|
2023-11-21 20:07:32 +01:00
|
|
|
if ty_known_to_outlive(tcx, item_def_id, param_env, wf_tys, *ty, *region_a) {
|
2022-02-10 23:36:37 -08:00
|
|
|
debug!(?ty_idx, ?region_a_idx);
|
2022-04-15 15:56:32 +09:00
|
|
|
debug!("required clause: {ty} must outlive {region_a}");
|
2022-02-10 23:36:37 -08:00
|
|
|
// Translate into the generic parameters of the GAT. In
|
2022-02-12 14:55:53 -08:00
|
|
|
// our example, the type was `Self`, which will also be
|
|
|
|
|
// `Self` in the GAT.
|
2022-02-10 23:36:37 -08:00
|
|
|
let ty_param = gat_generics.param_at(*ty_idx, tcx);
|
2023-07-05 20:13:26 +01:00
|
|
|
let ty_param = Ty::new_param(tcx, ty_param.index, ty_param.name);
|
2022-02-10 23:36:37 -08:00
|
|
|
// Same for the region. In our example, 'a corresponds
|
|
|
|
|
// to the 'me parameter.
|
|
|
|
|
let region_param = gat_generics.param_at(*region_a_idx, tcx);
|
2024-09-22 19:05:04 -04:00
|
|
|
let region_param = ty::Region::new_early_param(tcx, ty::EarlyParamRegion {
|
|
|
|
|
index: region_param.index,
|
|
|
|
|
name: region_param.name,
|
|
|
|
|
});
|
2022-02-10 23:36:37 -08:00
|
|
|
// The predicate we expect to see. (In our example,
|
|
|
|
|
// `Self: 'me`.)
|
2023-06-22 18:17:13 +00:00
|
|
|
bounds.insert(
|
|
|
|
|
ty::ClauseKind::TypeOutlives(ty::OutlivesPredicate(ty_param, region_param))
|
2024-05-15 10:05:25 -04:00
|
|
|
.upcast(tcx),
|
2023-06-22 18:17:13 +00:00
|
|
|
);
|
2022-02-10 23:36:37 -08:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2022-02-12 14:55:53 -08:00
|
|
|
// For each region argument (e.g., `'a` in our example), also check for a
|
|
|
|
|
// relationship to the other region arguments. If there is an outlives
|
|
|
|
|
// relationship, then we want to ensure that is reflected in the where clause
|
|
|
|
|
// on the GAT itself.
|
2022-02-10 23:36:37 -08:00
|
|
|
for (region_b, region_b_idx) in ®ions {
|
2022-02-12 14:55:53 -08:00
|
|
|
// Again, skip `'static` because it outlives everything. Also, we trivially
|
2023-07-31 18:23:12 +00:00
|
|
|
// know that a region outlives itself. Also ignore `ReError`, to avoid
|
|
|
|
|
// knock-down errors.
|
|
|
|
|
if matches!(**region_b, ty::ReStatic | ty::ReError(_)) || region_a == region_b {
|
2022-02-10 23:36:37 -08:00
|
|
|
continue;
|
|
|
|
|
}
|
2023-11-21 20:07:32 +01:00
|
|
|
if region_known_to_outlive(tcx, item_def_id, param_env, wf_tys, *region_a, *region_b) {
|
2022-02-10 23:36:37 -08:00
|
|
|
debug!(?region_a_idx, ?region_b_idx);
|
2022-04-15 15:56:32 +09:00
|
|
|
debug!("required clause: {region_a} must outlive {region_b}");
|
2022-02-10 23:36:37 -08:00
|
|
|
// Translate into the generic parameters of the GAT.
|
|
|
|
|
let region_a_param = gat_generics.param_at(*region_a_idx, tcx);
|
2024-09-22 19:05:04 -04:00
|
|
|
let region_a_param = ty::Region::new_early_param(tcx, ty::EarlyParamRegion {
|
|
|
|
|
index: region_a_param.index,
|
|
|
|
|
name: region_a_param.name,
|
|
|
|
|
});
|
2022-02-10 23:36:37 -08:00
|
|
|
// Same for the region.
|
|
|
|
|
let region_b_param = gat_generics.param_at(*region_b_idx, tcx);
|
2024-09-22 19:05:04 -04:00
|
|
|
let region_b_param = ty::Region::new_early_param(tcx, ty::EarlyParamRegion {
|
|
|
|
|
index: region_b_param.index,
|
|
|
|
|
name: region_b_param.name,
|
|
|
|
|
});
|
2022-02-10 23:36:37 -08:00
|
|
|
// The predicate we expect to see.
|
2023-06-22 18:17:13 +00:00
|
|
|
bounds.insert(
|
|
|
|
|
ty::ClauseKind::RegionOutlives(ty::OutlivesPredicate(
|
|
|
|
|
region_a_param,
|
|
|
|
|
region_b_param,
|
|
|
|
|
))
|
2024-05-15 10:05:25 -04:00
|
|
|
.upcast(tcx),
|
2023-06-22 18:17:13 +00:00
|
|
|
);
|
2022-02-10 23:36:37 -08:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Some(bounds)
|
|
|
|
|
}
|
|
|
|
|
|
2021-10-31 23:04:42 -04:00
|
|
|
/// Given a known `param_env` and a set of well formed types, can we prove that
|
|
|
|
|
/// `ty` outlives `region`.
|
|
|
|
|
fn ty_known_to_outlive<'tcx>(
|
|
|
|
|
tcx: TyCtxt<'tcx>,
|
2023-01-15 12:58:46 +01:00
|
|
|
id: LocalDefId,
|
2021-10-31 23:04:42 -04:00
|
|
|
param_env: ty::ParamEnv<'tcx>,
|
2022-10-28 23:32:41 +02:00
|
|
|
wf_tys: &FxIndexSet<Ty<'tcx>>,
|
2021-10-31 23:04:42 -04:00
|
|
|
ty: Ty<'tcx>,
|
|
|
|
|
region: ty::Region<'tcx>,
|
|
|
|
|
) -> bool {
|
2023-12-19 00:42:58 +00:00
|
|
|
test_region_obligations(tcx, id, param_env, wf_tys, |infcx| {
|
|
|
|
|
infcx.register_region_obligation(infer::RegionObligation {
|
|
|
|
|
sub_region: region,
|
|
|
|
|
sup_type: ty,
|
|
|
|
|
origin: infer::RelateParamBound(DUMMY_SP, ty, None),
|
|
|
|
|
});
|
2021-10-31 23:04:42 -04:00
|
|
|
})
|
|
|
|
|
}
|
|
|
|
|
|
2022-01-13 15:07:12 -05:00
|
|
|
/// Given a known `param_env` and a set of well formed types, can we prove that
|
|
|
|
|
/// `region_a` outlives `region_b`
|
2021-10-31 23:04:42 -04:00
|
|
|
fn region_known_to_outlive<'tcx>(
|
|
|
|
|
tcx: TyCtxt<'tcx>,
|
2023-01-15 12:58:46 +01:00
|
|
|
id: LocalDefId,
|
2021-10-31 23:04:42 -04:00
|
|
|
param_env: ty::ParamEnv<'tcx>,
|
2022-10-28 23:32:41 +02:00
|
|
|
wf_tys: &FxIndexSet<Ty<'tcx>>,
|
2021-10-31 23:04:42 -04:00
|
|
|
region_a: ty::Region<'tcx>,
|
|
|
|
|
region_b: ty::Region<'tcx>,
|
2022-01-13 15:07:12 -05:00
|
|
|
) -> bool {
|
2023-12-19 00:42:58 +00:00
|
|
|
test_region_obligations(tcx, id, param_env, wf_tys, |infcx| {
|
2024-08-12 22:57:14 +00:00
|
|
|
infcx.sub_regions(infer::RelateRegionParamBound(DUMMY_SP, None), region_b, region_a);
|
2022-01-13 15:07:12 -05:00
|
|
|
})
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// Given a known `param_env` and a set of well formed types, set up an
|
|
|
|
|
/// `InferCtxt`, call the passed function (to e.g. set up region constraints
|
|
|
|
|
/// to be tested), then resolve region and return errors
|
2023-12-19 00:42:58 +00:00
|
|
|
fn test_region_obligations<'tcx>(
|
2022-01-13 15:07:12 -05:00
|
|
|
tcx: TyCtxt<'tcx>,
|
2023-01-15 12:58:46 +01:00
|
|
|
id: LocalDefId,
|
2022-01-13 15:07:12 -05:00
|
|
|
param_env: ty::ParamEnv<'tcx>,
|
2022-10-28 23:32:41 +02:00
|
|
|
wf_tys: &FxIndexSet<Ty<'tcx>>,
|
2023-12-19 00:42:58 +00:00
|
|
|
add_constraints: impl FnOnce(&InferCtxt<'tcx>),
|
2021-10-31 23:04:42 -04:00
|
|
|
) -> bool {
|
|
|
|
|
// Unfortunately, we have to use a new `InferCtxt` each call, because
|
|
|
|
|
// region constraints get added and solved there and we need to test each
|
|
|
|
|
// call individually.
|
2024-10-18 00:28:43 +02:00
|
|
|
let infcx = tcx.infer_ctxt().build(TypingMode::non_body_analysis());
|
2023-12-19 00:42:58 +00:00
|
|
|
|
|
|
|
|
add_constraints(&infcx);
|
|
|
|
|
|
2022-09-19 22:03:59 -05:00
|
|
|
let outlives_environment = OutlivesEnvironment::with_bounds(
|
|
|
|
|
param_env,
|
2024-01-16 18:39:00 -05:00
|
|
|
infcx.implied_bounds_tys(param_env, id, wf_tys),
|
2022-09-19 22:03:59 -05:00
|
|
|
);
|
2021-10-31 23:04:42 -04:00
|
|
|
|
2022-09-19 22:03:59 -05:00
|
|
|
let errors = infcx.resolve_regions(&outlives_environment);
|
|
|
|
|
debug!(?errors, "errors");
|
2021-10-31 23:04:42 -04:00
|
|
|
|
2022-09-19 22:03:59 -05:00
|
|
|
// If we were able to prove that the type outlives the region without
|
|
|
|
|
// an error, it must be because of the implied or explicit bounds...
|
|
|
|
|
errors.is_empty()
|
2021-10-31 23:04:42 -04:00
|
|
|
}
|
|
|
|
|
|
2021-10-31 21:36:04 -04:00
|
|
|
/// TypeVisitor that looks for uses of GATs like
|
|
|
|
|
/// `<P0 as Trait<P1..Pn>>::GAT<Pn..Pm>` and adds the arguments `P0..Pm` into
|
|
|
|
|
/// the two vectors, `regions` and `types` (depending on their kind). For each
|
|
|
|
|
/// parameter `Pi` also track the index `i`.
|
2024-02-12 15:39:32 +09:00
|
|
|
struct GATArgsCollector<'tcx> {
|
2021-10-07 17:00:39 -04:00
|
|
|
gat: DefId,
|
2024-02-12 15:39:32 +09:00
|
|
|
// Which region appears and which parameter index its instantiated with
|
2024-10-02 08:25:55 +03:00
|
|
|
regions: FxIndexSet<(ty::Region<'tcx>, usize)>,
|
2024-02-12 15:39:32 +09:00
|
|
|
// Which params appears and which parameter index its instantiated with
|
2024-10-02 08:25:55 +03:00
|
|
|
types: FxIndexSet<(Ty<'tcx>, usize)>,
|
2021-10-07 17:00:39 -04:00
|
|
|
}
|
|
|
|
|
|
2024-02-12 15:39:32 +09:00
|
|
|
impl<'tcx> GATArgsCollector<'tcx> {
|
2023-02-22 02:18:40 +00:00
|
|
|
fn visit<T: TypeFoldable<TyCtxt<'tcx>>>(
|
2021-11-05 21:33:14 -04:00
|
|
|
gat: DefId,
|
|
|
|
|
t: T,
|
2024-10-02 08:25:55 +03:00
|
|
|
) -> (FxIndexSet<(ty::Region<'tcx>, usize)>, FxIndexSet<(Ty<'tcx>, usize)>) {
|
2022-06-18 04:11:47 +01:00
|
|
|
let mut visitor =
|
2024-10-02 08:25:55 +03:00
|
|
|
GATArgsCollector { gat, regions: FxIndexSet::default(), types: FxIndexSet::default() };
|
2021-11-05 21:33:14 -04:00
|
|
|
t.visit_with(&mut visitor);
|
|
|
|
|
(visitor.regions, visitor.types)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2024-02-12 15:39:32 +09:00
|
|
|
impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for GATArgsCollector<'tcx> {
|
2024-02-24 17:22:28 -05:00
|
|
|
fn visit_ty(&mut self, t: Ty<'tcx>) {
|
2021-10-07 17:00:39 -04:00
|
|
|
match t.kind() {
|
2022-11-26 21:51:55 +00:00
|
|
|
ty::Alias(ty::Projection, p) if p.def_id == self.gat => {
|
2024-02-12 15:39:32 +09:00
|
|
|
for (idx, arg) in p.args.iter().enumerate() {
|
|
|
|
|
match arg.unpack() {
|
2023-11-13 14:00:05 +00:00
|
|
|
GenericArgKind::Lifetime(lt) if !lt.is_bound() => {
|
2021-10-16 02:29:59 -04:00
|
|
|
self.regions.insert((lt, idx));
|
|
|
|
|
}
|
2021-10-18 09:40:27 -04:00
|
|
|
GenericArgKind::Type(t) => {
|
|
|
|
|
self.types.insert((t, idx));
|
|
|
|
|
}
|
2021-10-16 02:29:59 -04:00
|
|
|
_ => {}
|
2021-10-07 17:00:39 -04:00
|
|
|
}
|
2021-10-16 02:29:59 -04:00
|
|
|
}
|
2021-10-07 17:00:39 -04:00
|
|
|
}
|
|
|
|
|
_ => {}
|
|
|
|
|
}
|
|
|
|
|
t.super_visit_with(self)
|
|
|
|
|
}
|
2018-03-12 22:18:51 -04:00
|
|
|
}
|
2018-03-10 11:25:03 -05:00
|
|
|
|
2020-04-09 09:43:00 +01:00
|
|
|
fn could_be_self(trait_def_id: LocalDefId, ty: &hir::Ty<'_>) -> bool {
|
2020-01-19 17:27:37 -08:00
|
|
|
match ty.kind {
|
2024-10-13 09:16:03 -04:00
|
|
|
hir::TyKind::TraitObject([trait_ref], ..) => match trait_ref.trait_ref.path.segments {
|
2022-08-30 15:10:28 +10:00
|
|
|
[s] => s.res.opt_def_id() == Some(trait_def_id.to_def_id()),
|
2020-01-30 19:35:48 -08:00
|
|
|
_ => false,
|
|
|
|
|
},
|
2020-01-19 17:27:37 -08:00
|
|
|
_ => false,
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2024-09-25 10:38:40 +02:00
|
|
|
/// Detect when a dyn-incompatible trait is referring to itself in one of its associated items.
|
|
|
|
|
///
|
|
|
|
|
/// In such cases, suggest using `Self` instead.
|
|
|
|
|
fn check_dyn_incompatible_self_trait_by_name(tcx: TyCtxt<'_>, item: &hir::TraitItem<'_>) {
|
2021-10-21 19:41:47 +02:00
|
|
|
let (trait_name, trait_def_id) =
|
2023-12-01 05:28:34 -08:00
|
|
|
match tcx.hir_node_by_def_id(tcx.hir().get_parent_item(item.hir_id()).def_id) {
|
2021-10-21 19:41:47 +02:00
|
|
|
hir::Node::Item(item) => match item.kind {
|
2022-10-27 14:02:18 +11:00
|
|
|
hir::ItemKind::Trait(..) => (item.ident, item.owner_id),
|
2021-10-21 19:41:47 +02:00
|
|
|
_ => return,
|
|
|
|
|
},
|
2020-01-19 17:27:37 -08:00
|
|
|
_ => return,
|
2021-10-21 19:41:47 +02:00
|
|
|
};
|
2020-01-19 17:27:37 -08:00
|
|
|
let mut trait_should_be_self = vec![];
|
|
|
|
|
match &item.kind {
|
|
|
|
|
hir::TraitItemKind::Const(ty, _) | hir::TraitItemKind::Type(_, Some(ty))
|
2022-09-20 14:11:23 +09:00
|
|
|
if could_be_self(trait_def_id.def_id, ty) =>
|
2020-01-19 17:27:37 -08:00
|
|
|
{
|
|
|
|
|
trait_should_be_self.push(ty.span)
|
|
|
|
|
}
|
2020-03-03 12:46:22 -06:00
|
|
|
hir::TraitItemKind::Fn(sig, _) => {
|
2020-01-19 17:27:37 -08:00
|
|
|
for ty in sig.decl.inputs {
|
2022-09-20 14:11:23 +09:00
|
|
|
if could_be_self(trait_def_id.def_id, ty) {
|
2020-01-19 17:27:37 -08:00
|
|
|
trait_should_be_self.push(ty.span);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
match sig.decl.output {
|
2022-09-20 14:11:23 +09:00
|
|
|
hir::FnRetTy::Return(ty) if could_be_self(trait_def_id.def_id, ty) => {
|
2020-01-19 17:27:37 -08:00
|
|
|
trait_should_be_self.push(ty.span);
|
|
|
|
|
}
|
|
|
|
|
_ => {}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
_ => {}
|
|
|
|
|
}
|
|
|
|
|
if !trait_should_be_self.is_empty() {
|
2024-09-25 10:38:40 +02:00
|
|
|
if tcx.is_dyn_compatible(trait_def_id) {
|
2020-01-19 17:27:37 -08:00
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
let sugg = trait_should_be_self.iter().map(|span| (*span, "Self".to_string())).collect();
|
2023-12-18 22:21:37 +11:00
|
|
|
tcx.dcx()
|
2020-01-25 14:28:23 -08:00
|
|
|
.struct_span_err(
|
|
|
|
|
trait_should_be_self,
|
|
|
|
|
"associated item referring to unboxed trait object for its own trait",
|
|
|
|
|
)
|
2024-01-09 09:08:49 +11:00
|
|
|
.with_span_label(trait_name.span, "in this trait")
|
|
|
|
|
.with_multipart_suggestion(
|
2020-01-25 14:28:23 -08:00
|
|
|
"you might have meant to use `Self` to refer to the implementing type",
|
|
|
|
|
sugg,
|
|
|
|
|
Applicability::MachineApplicable,
|
|
|
|
|
)
|
|
|
|
|
.emit();
|
2020-01-19 17:27:37 -08:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2024-02-23 11:45:44 +00:00
|
|
|
fn check_impl_item<'tcx>(
|
|
|
|
|
tcx: TyCtxt<'tcx>,
|
|
|
|
|
impl_item: &'tcx hir::ImplItem<'tcx>,
|
|
|
|
|
) -> Result<(), ErrorGuaranteed> {
|
|
|
|
|
CollectItemTypesVisitor { tcx }.visit_impl_item(impl_item);
|
|
|
|
|
|
2021-08-06 15:46:20 +00:00
|
|
|
let (method_sig, span) = match impl_item.kind {
|
|
|
|
|
hir::ImplItemKind::Fn(ref sig, _) => (Some(sig), impl_item.span),
|
2021-12-11 02:20:41 +00:00
|
|
|
// Constrain binding and overflow error spans to `<Ty>` in `type foo = <Ty>`.
|
2022-10-09 07:09:57 +00:00
|
|
|
hir::ImplItemKind::Type(ty) if ty.span != DUMMY_SP => (None, ty.span),
|
2021-08-06 15:46:20 +00:00
|
|
|
_ => (None, impl_item.span),
|
2018-03-12 22:18:51 -04:00
|
|
|
};
|
2024-10-24 16:25:02 +00:00
|
|
|
check_associated_item(tcx, impl_item.owner_id.def_id, span, method_sig)
|
2018-03-12 22:18:51 -04:00
|
|
|
}
|
2018-03-10 17:17:30 -05:00
|
|
|
|
2023-10-18 08:47:17 +00:00
|
|
|
fn check_param_wf(tcx: TyCtxt<'_>, param: &hir::GenericParam<'_>) -> Result<(), ErrorGuaranteed> {
|
2020-08-02 21:28:18 +02:00
|
|
|
match param.kind {
|
|
|
|
|
// We currently only check wf of const params here.
|
2023-10-18 08:47:17 +00:00
|
|
|
hir::GenericParamKind::Lifetime { .. } | hir::GenericParamKind::Type { .. } => Ok(()),
|
2020-08-02 21:28:18 +02:00
|
|
|
|
2020-12-31 01:58:27 +01:00
|
|
|
// Const parameters are well formed if their type is structural match.
|
2024-10-20 20:22:11 +00:00
|
|
|
hir::GenericParamKind::Const { ty: hir_ty, default: _, synthetic: _ } => {
|
2023-07-11 22:35:29 +01:00
|
|
|
let ty = tcx.type_of(param.def_id).instantiate_identity();
|
2020-08-02 21:28:18 +02:00
|
|
|
|
2024-10-09 09:01:57 +02:00
|
|
|
if tcx.features().unsized_const_params() {
|
2023-05-16 19:58:54 +01:00
|
|
|
enter_wf_checking_ctxt(tcx, hir_ty.span, param.def_id, |wfcx| {
|
|
|
|
|
wfcx.register_bound(
|
|
|
|
|
ObligationCause::new(
|
|
|
|
|
hir_ty.span,
|
|
|
|
|
param.def_id,
|
2023-05-17 04:05:46 +00:00
|
|
|
ObligationCauseCode::ConstParam(ty),
|
2023-05-16 19:58:54 +01:00
|
|
|
),
|
|
|
|
|
wfcx.param_env,
|
|
|
|
|
ty,
|
2024-07-14 13:38:51 +01:00
|
|
|
tcx.require_lang_item(LangItem::UnsizedConstParamTy, Some(hir_ty.span)),
|
2024-07-14 12:50:41 +01:00
|
|
|
);
|
2024-07-14 13:38:51 +01:00
|
|
|
Ok(())
|
|
|
|
|
})
|
2024-10-09 09:01:57 +02:00
|
|
|
} else if tcx.features().adt_const_params() {
|
2024-07-14 13:38:51 +01:00
|
|
|
enter_wf_checking_ctxt(tcx, hir_ty.span, param.def_id, |wfcx| {
|
2024-07-14 12:50:41 +01:00
|
|
|
wfcx.register_bound(
|
2024-07-14 13:38:51 +01:00
|
|
|
ObligationCause::new(
|
|
|
|
|
hir_ty.span,
|
|
|
|
|
param.def_id,
|
|
|
|
|
ObligationCauseCode::ConstParam(ty),
|
|
|
|
|
),
|
2024-07-14 12:50:41 +01:00
|
|
|
wfcx.param_env,
|
|
|
|
|
ty,
|
2024-07-14 13:38:51 +01:00
|
|
|
tcx.require_lang_item(LangItem::ConstParamTy, Some(hir_ty.span)),
|
2023-05-16 19:58:54 +01:00
|
|
|
);
|
2023-10-30 15:54:08 +00:00
|
|
|
Ok(())
|
2023-10-18 08:47:17 +00:00
|
|
|
})
|
2020-11-17 10:55:13 +01:00
|
|
|
} else {
|
2023-10-18 08:47:17 +00:00
|
|
|
let mut diag = match ty.kind() {
|
|
|
|
|
ty::Bool | ty::Char | ty::Int(_) | ty::Uint(_) | ty::Error(_) => return Ok(()),
|
2024-08-08 17:18:20 +10:00
|
|
|
ty::FnPtr(..) => tcx.dcx().struct_span_err(
|
2023-09-28 20:51:48 +00:00
|
|
|
hir_ty.span,
|
|
|
|
|
"using function pointers as const generic parameters is forbidden",
|
2023-10-18 08:47:17 +00:00
|
|
|
),
|
2024-03-21 17:11:06 -04:00
|
|
|
ty::RawPtr(_, _) => tcx.dcx().struct_span_err(
|
2023-09-28 20:51:48 +00:00
|
|
|
hir_ty.span,
|
|
|
|
|
"using raw pointers as const generic parameters is forbidden",
|
2023-10-18 08:47:17 +00:00
|
|
|
),
|
2024-09-29 15:28:11 -05:00
|
|
|
_ => {
|
|
|
|
|
// Avoid showing "{type error}" to users. See #118179.
|
|
|
|
|
ty.error_reported()?;
|
|
|
|
|
|
|
|
|
|
tcx.dcx().struct_span_err(
|
|
|
|
|
hir_ty.span,
|
|
|
|
|
format!(
|
|
|
|
|
"`{ty}` is forbidden as the type of a const generic parameter",
|
|
|
|
|
),
|
|
|
|
|
)
|
|
|
|
|
}
|
2022-04-08 19:10:07 +01:00
|
|
|
};
|
|
|
|
|
|
2024-09-29 15:28:11 -05:00
|
|
|
diag.note("the only supported types are integers, `bool`, and `char`");
|
2023-09-28 20:51:48 +00:00
|
|
|
|
2023-10-18 08:47:17 +00:00
|
|
|
let cause = ObligationCause::misc(hir_ty.span, param.def_id);
|
2024-07-14 13:38:51 +01:00
|
|
|
let adt_const_params_feature_string =
|
|
|
|
|
" more complex and user defined types".to_string();
|
2023-10-18 08:47:17 +00:00
|
|
|
let may_suggest_feature = match type_allowed_to_implement_const_param_ty(
|
|
|
|
|
tcx,
|
|
|
|
|
tcx.param_env(param.def_id),
|
|
|
|
|
ty,
|
2024-07-14 13:38:51 +01:00
|
|
|
LangItem::ConstParamTy,
|
2023-10-18 08:47:17 +00:00
|
|
|
cause,
|
|
|
|
|
) {
|
|
|
|
|
// Can never implement `ConstParamTy`, don't suggest anything.
|
2024-07-14 12:50:41 +01:00
|
|
|
Err(
|
|
|
|
|
ConstParamTyImplementationError::NotAnAdtOrBuiltinAllowed
|
2024-07-14 13:38:51 +01:00
|
|
|
| ConstParamTyImplementationError::InvalidInnerTyOfBuiltinTy(..),
|
|
|
|
|
) => None,
|
|
|
|
|
Err(ConstParamTyImplementationError::UnsizedConstParamsFeatureRequired) => {
|
|
|
|
|
Some(vec![
|
|
|
|
|
(adt_const_params_feature_string, sym::adt_const_params),
|
|
|
|
|
(
|
|
|
|
|
" references to implement the `ConstParamTy` trait".into(),
|
|
|
|
|
sym::unsized_const_params,
|
|
|
|
|
),
|
|
|
|
|
])
|
|
|
|
|
}
|
2023-10-18 08:47:17 +00:00
|
|
|
// May be able to implement `ConstParamTy`. Only emit the feature help
|
|
|
|
|
// if the type is local, since the user may be able to fix the local type.
|
|
|
|
|
Err(ConstParamTyImplementationError::InfrigingFields(..)) => {
|
|
|
|
|
fn ty_is_local(ty: Ty<'_>) -> bool {
|
|
|
|
|
match ty.kind() {
|
|
|
|
|
ty::Adt(adt_def, ..) => adt_def.did().is_local(),
|
|
|
|
|
// Arrays and slices use the inner type's `ConstParamTy`.
|
|
|
|
|
ty::Array(ty, ..) => ty_is_local(*ty),
|
|
|
|
|
ty::Slice(ty) => ty_is_local(*ty),
|
|
|
|
|
// `&` references use the inner type's `ConstParamTy`.
|
|
|
|
|
// `&mut` are not supported.
|
|
|
|
|
ty::Ref(_, ty, ast::Mutability::Not) => ty_is_local(*ty),
|
|
|
|
|
// Say that a tuple is local if any of its components are local.
|
|
|
|
|
// This is not strictly correct, but it's likely that the user can fix the local component.
|
|
|
|
|
ty::Tuple(tys) => tys.iter().any(|ty| ty_is_local(ty)),
|
|
|
|
|
_ => false,
|
2023-09-28 20:51:48 +00:00
|
|
|
}
|
2022-04-08 19:10:07 +01:00
|
|
|
}
|
2023-10-18 08:47:17 +00:00
|
|
|
|
2024-07-14 13:38:51 +01:00
|
|
|
ty_is_local(ty).then_some(vec![(
|
|
|
|
|
adt_const_params_feature_string,
|
|
|
|
|
sym::adt_const_params,
|
|
|
|
|
)])
|
2023-10-18 08:47:17 +00:00
|
|
|
}
|
2024-09-02 07:42:38 +02:00
|
|
|
// Implements `ConstParamTy`, suggest adding the feature to enable.
|
2024-07-14 13:38:51 +01:00
|
|
|
Ok(..) => Some(vec![(adt_const_params_feature_string, sym::adt_const_params)]),
|
2023-10-18 08:47:17 +00:00
|
|
|
};
|
2024-07-14 13:38:51 +01:00
|
|
|
if let Some(features) = may_suggest_feature {
|
|
|
|
|
tcx.disabled_nightly_features(&mut diag, Some(param.hir_id), features);
|
2020-08-02 21:28:18 +02:00
|
|
|
}
|
2023-10-18 08:47:17 +00:00
|
|
|
|
|
|
|
|
Err(diag.emit())
|
2020-08-02 21:28:18 +02:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2022-08-31 13:01:10 +00:00
|
|
|
#[instrument(level = "debug", skip(tcx, span, sig_if_method))]
|
2019-06-21 20:05:14 +02:00
|
|
|
fn check_associated_item(
|
|
|
|
|
tcx: TyCtxt<'_>,
|
2021-10-13 22:22:09 -04:00
|
|
|
item_id: LocalDefId,
|
2019-06-12 00:11:55 +03:00
|
|
|
span: Span,
|
2019-11-30 15:20:35 +01:00
|
|
|
sig_if_method: Option<&hir::FnSig<'_>>,
|
2023-10-18 08:47:17 +00:00
|
|
|
) -> Result<(), ErrorGuaranteed> {
|
2022-07-07 15:12:32 +02:00
|
|
|
let loc = Some(WellFormedLoc::Ty(item_id));
|
|
|
|
|
enter_wf_checking_ctxt(tcx, span, item_id, |wfcx| {
|
|
|
|
|
let item = tcx.associated_item(item_id);
|
2018-03-12 22:18:51 -04:00
|
|
|
|
2024-02-02 08:36:46 +00:00
|
|
|
// Avoid bogus "type annotations needed `Foo: Bar`" errors on `impl Bar for Foo` in case
|
|
|
|
|
// other `Foo` impls are incoherent.
|
|
|
|
|
tcx.ensure()
|
|
|
|
|
.coherent_trait(tcx.parent(item.trait_item_def_id.unwrap_or(item_id.into())))?;
|
|
|
|
|
|
2022-08-17 12:22:32 +02:00
|
|
|
let self_ty = match item.container {
|
2024-11-03 21:47:56 +00:00
|
|
|
ty::AssocItemContainer::Trait => tcx.types.self_param,
|
|
|
|
|
ty::AssocItemContainer::Impl => {
|
|
|
|
|
tcx.type_of(item.container_id(tcx)).instantiate_identity()
|
|
|
|
|
}
|
2018-03-12 22:18:51 -04:00
|
|
|
};
|
2015-08-07 09:39:54 -04:00
|
|
|
|
2018-03-12 22:18:51 -04:00
|
|
|
match item.kind {
|
2019-05-19 16:26:08 +08:00
|
|
|
ty::AssocKind::Const => {
|
2023-07-11 22:35:29 +01:00
|
|
|
let ty = tcx.type_of(item.def_id).instantiate_identity();
|
2022-07-07 15:12:32 +02:00
|
|
|
let ty = wfcx.normalize(span, Some(WellFormedLoc::Ty(item_id)), ty);
|
|
|
|
|
wfcx.register_wf_obligation(span, loc, ty.into());
|
2023-10-30 15:54:08 +00:00
|
|
|
Ok(())
|
2018-03-12 22:18:51 -04:00
|
|
|
}
|
2020-04-01 10:09:50 +08:00
|
|
|
ty::AssocKind::Fn => {
|
2023-07-11 22:35:29 +01:00
|
|
|
let sig = tcx.fn_sig(item.def_id).instantiate_identity();
|
2020-01-18 14:57:56 -08:00
|
|
|
let hir_sig = sig_if_method.expect("bad signature for method");
|
|
|
|
|
check_fn_or_method(
|
2022-07-07 15:12:32 +02:00
|
|
|
wfcx,
|
|
|
|
|
item.ident(tcx).span,
|
2020-01-18 14:57:56 -08:00
|
|
|
sig,
|
2020-06-13 19:37:25 +01:00
|
|
|
hir_sig.decl,
|
2022-04-01 13:38:43 +02:00
|
|
|
item.def_id.expect_local(),
|
2020-01-18 14:57:56 -08:00
|
|
|
);
|
2024-10-24 16:25:02 +00:00
|
|
|
check_method_receiver(wfcx, hir_sig, item, self_ty)
|
2018-03-12 22:18:51 -04:00
|
|
|
}
|
2019-05-19 16:26:08 +08:00
|
|
|
ty::AssocKind::Type => {
|
2024-11-03 21:47:56 +00:00
|
|
|
if let ty::AssocItemContainer::Trait = item.container {
|
2022-07-07 15:12:32 +02:00
|
|
|
check_associated_type_bounds(wfcx, item, span)
|
2020-06-27 21:36:35 +01:00
|
|
|
}
|
2022-03-12 19:36:11 +01:00
|
|
|
if item.defaultness(tcx).has_value() {
|
2023-07-11 22:35:29 +01:00
|
|
|
let ty = tcx.type_of(item.def_id).instantiate_identity();
|
2022-07-07 15:12:32 +02:00
|
|
|
let ty = wfcx.normalize(span, Some(WellFormedLoc::Ty(item_id)), ty);
|
|
|
|
|
wfcx.register_wf_obligation(span, loc, ty.into());
|
2015-08-07 09:39:54 -04:00
|
|
|
}
|
2023-10-30 15:54:08 +00:00
|
|
|
Ok(())
|
2015-08-07 09:39:54 -04:00
|
|
|
}
|
2018-03-12 22:18:51 -04:00
|
|
|
}
|
|
|
|
|
})
|
|
|
|
|
}
|
2015-08-07 09:39:54 -04:00
|
|
|
|
2018-03-12 22:18:51 -04:00
|
|
|
/// In a type definition, we check that to ensure that the types of the fields are well-formed.
|
2023-10-18 08:47:17 +00:00
|
|
|
fn check_type_defn<'tcx>(
|
|
|
|
|
tcx: TyCtxt<'tcx>,
|
|
|
|
|
item: &hir::Item<'tcx>,
|
|
|
|
|
all_sized: bool,
|
|
|
|
|
) -> Result<(), ErrorGuaranteed> {
|
2022-10-27 14:02:18 +11:00
|
|
|
let _ = tcx.representability(item.owner_id.def_id);
|
2022-10-30 07:57:23 +00:00
|
|
|
let adt_def = tcx.adt_def(item.owner_id);
|
2022-10-10 11:22:41 -05:00
|
|
|
|
2022-10-27 14:02:18 +11:00
|
|
|
enter_wf_checking_ctxt(tcx, item.span, item.owner_id.def_id, |wfcx| {
|
2022-10-30 07:57:23 +00:00
|
|
|
let variants = adt_def.variants();
|
|
|
|
|
let packed = adt_def.repr().packed();
|
2018-03-12 22:18:51 -04:00
|
|
|
|
2022-10-30 07:57:23 +00:00
|
|
|
for variant in variants.iter() {
|
2022-06-05 23:04:37 -07:00
|
|
|
// All field types must be well-formed.
|
|
|
|
|
for field in &variant.fields {
|
2022-10-30 07:57:23 +00:00
|
|
|
let field_id = field.did.expect_local();
|
2023-01-20 15:59:56 +00:00
|
|
|
let hir::FieldDef { ty: hir_ty, .. } =
|
2023-12-01 05:28:34 -08:00
|
|
|
tcx.hir_node_by_def_id(field_id).expect_field();
|
2023-07-11 22:35:29 +01:00
|
|
|
let ty = wfcx.normalize(
|
|
|
|
|
hir_ty.span,
|
|
|
|
|
None,
|
|
|
|
|
tcx.type_of(field.did).instantiate_identity(),
|
|
|
|
|
);
|
2022-07-07 15:12:32 +02:00
|
|
|
wfcx.register_wf_obligation(
|
2022-10-30 07:57:23 +00:00
|
|
|
hir_ty.span,
|
|
|
|
|
Some(WellFormedLoc::Ty(field_id)),
|
|
|
|
|
ty.into(),
|
2022-06-05 23:04:37 -07:00
|
|
|
)
|
|
|
|
|
}
|
|
|
|
|
|
2018-03-12 22:18:51 -04:00
|
|
|
// For DST, or when drop needs to copy things around, all
|
|
|
|
|
// intermediate types must be sized.
|
|
|
|
|
let needs_drop_copy = || {
|
|
|
|
|
packed && {
|
2023-07-11 22:35:29 +01:00
|
|
|
let ty = tcx.type_of(variant.tail().did).instantiate_identity();
|
2021-05-07 12:15:38 +02:00
|
|
|
let ty = tcx.erase_regions(ty);
|
2024-02-20 09:36:28 +11:00
|
|
|
assert!(!ty.has_infer());
|
2024-11-18 10:50:14 +01:00
|
|
|
ty.needs_drop(tcx, wfcx.infcx.typing_env(wfcx.param_env))
|
2015-08-07 09:39:54 -04:00
|
|
|
}
|
2018-03-12 22:18:51 -04:00
|
|
|
};
|
2022-06-05 23:04:37 -07:00
|
|
|
// All fields (except for possibly the last) should be sized.
|
2019-12-24 17:38:22 -05:00
|
|
|
let all_sized = all_sized || variant.fields.is_empty() || needs_drop_copy();
|
|
|
|
|
let unsized_len = if all_sized { 0 } else { 1 };
|
|
|
|
|
for (idx, field) in
|
2023-03-28 23:32:25 -07:00
|
|
|
variant.fields.raw[..variant.fields.len() - unsized_len].iter().enumerate()
|
2018-08-14 12:50:01 +02:00
|
|
|
{
|
|
|
|
|
let last = idx == variant.fields.len() - 1;
|
2022-10-30 07:57:23 +00:00
|
|
|
let field_id = field.did.expect_local();
|
2023-01-20 15:59:56 +00:00
|
|
|
let hir::FieldDef { ty: hir_ty, .. } =
|
2023-12-01 05:28:34 -08:00
|
|
|
tcx.hir_node_by_def_id(field_id).expect_field();
|
2023-07-11 22:35:29 +01:00
|
|
|
let ty = wfcx.normalize(
|
|
|
|
|
hir_ty.span,
|
|
|
|
|
None,
|
|
|
|
|
tcx.type_of(field.did).instantiate_identity(),
|
|
|
|
|
);
|
2022-07-07 15:12:32 +02:00
|
|
|
wfcx.register_bound(
|
2018-08-14 12:50:01 +02:00
|
|
|
traits::ObligationCause::new(
|
2022-10-30 07:57:23 +00:00
|
|
|
hir_ty.span,
|
2023-01-15 12:58:46 +01:00
|
|
|
wfcx.body_def_id,
|
2024-05-09 20:05:59 -04:00
|
|
|
ObligationCauseCode::FieldSized {
|
2023-12-15 03:19:46 +00:00
|
|
|
adt_kind: match &item.kind {
|
|
|
|
|
ItemKind::Struct(..) => AdtKind::Struct,
|
|
|
|
|
ItemKind::Union(..) => AdtKind::Union,
|
|
|
|
|
ItemKind::Enum(..) => AdtKind::Enum,
|
|
|
|
|
kind => span_bug!(
|
|
|
|
|
item.span,
|
|
|
|
|
"should be wfchecking an ADT, got {kind:?}"
|
|
|
|
|
),
|
2018-08-14 12:50:01 +02:00
|
|
|
},
|
2022-10-30 07:57:23 +00:00
|
|
|
span: hir_ty.span,
|
2019-12-24 17:38:22 -05:00
|
|
|
last,
|
|
|
|
|
},
|
|
|
|
|
),
|
2022-07-07 15:12:32 +02:00
|
|
|
wfcx.param_env,
|
2022-10-30 07:57:23 +00:00
|
|
|
ty,
|
2022-07-07 15:12:32 +02:00
|
|
|
tcx.require_lang_item(LangItem::Sized, None),
|
2018-08-14 12:50:01 +02:00
|
|
|
);
|
2018-03-12 22:18:51 -04:00
|
|
|
}
|
2015-08-07 09:39:54 -04:00
|
|
|
|
2020-04-06 00:13:57 +03:00
|
|
|
// Explicit `enum` discriminant values must const-evaluate successfully.
|
2022-10-30 07:57:23 +00:00
|
|
|
if let ty::VariantDiscr::Explicit(discr_def_id) = variant.discr {
|
2024-11-28 22:04:03 -08:00
|
|
|
match tcx.const_eval_poly(discr_def_id) {
|
|
|
|
|
Ok(_) => {}
|
|
|
|
|
Err(ErrorHandled::Reported(..)) => {}
|
|
|
|
|
Err(ErrorHandled::TooGeneric(sp)) => {
|
|
|
|
|
span_bug!(sp, "enum variant discr was too generic to eval")
|
|
|
|
|
}
|
|
|
|
|
}
|
2020-04-06 00:13:57 +03:00
|
|
|
}
|
2018-03-12 22:18:51 -04:00
|
|
|
}
|
2015-08-07 09:39:54 -04:00
|
|
|
|
2022-10-27 14:02:18 +11:00
|
|
|
check_where_clauses(wfcx, item.span, item.owner_id.def_id);
|
2023-10-30 15:54:08 +00:00
|
|
|
Ok(())
|
2023-10-18 08:47:17 +00:00
|
|
|
})
|
2018-03-12 22:18:51 -04:00
|
|
|
}
|
2015-08-07 09:39:54 -04:00
|
|
|
|
2021-09-16 19:08:25 +00:00
|
|
|
#[instrument(skip(tcx, item))]
|
2023-10-18 08:47:17 +00:00
|
|
|
fn check_trait(tcx: TyCtxt<'_>, item: &hir::Item<'_>) -> Result<(), ErrorGuaranteed> {
|
2022-10-27 14:02:18 +11:00
|
|
|
debug!(?item.owner_id);
|
2018-11-01 19:43:38 +00:00
|
|
|
|
2022-10-27 14:02:18 +11:00
|
|
|
let def_id = item.owner_id.def_id;
|
2022-09-20 14:11:23 +09:00
|
|
|
let trait_def = tcx.trait_def(def_id);
|
2020-02-08 17:56:25 +00:00
|
|
|
if trait_def.is_marker
|
|
|
|
|
|| matches!(trait_def.specialization_kind, TraitSpecializationKind::Marker)
|
|
|
|
|
{
|
2022-09-20 14:11:23 +09:00
|
|
|
for associated_def_id in &*tcx.associated_item_def_ids(def_id) {
|
2024-01-04 09:08:36 +11:00
|
|
|
struct_span_code_err!(
|
2023-12-18 22:21:37 +11:00
|
|
|
tcx.dcx(),
|
2018-09-03 02:17:20 -07:00
|
|
|
tcx.def_span(*associated_def_id),
|
|
|
|
|
E0714,
|
|
|
|
|
"marker traits cannot have associated items",
|
2019-12-24 17:38:22 -05:00
|
|
|
)
|
|
|
|
|
.emit();
|
2018-09-03 01:36:01 -07:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2023-10-18 08:47:17 +00:00
|
|
|
let res = enter_wf_checking_ctxt(tcx, item.span, def_id, |wfcx| {
|
2023-10-30 15:54:08 +00:00
|
|
|
check_where_clauses(wfcx, item.span, def_id);
|
|
|
|
|
Ok(())
|
2018-03-12 22:18:51 -04:00
|
|
|
});
|
2022-02-11 00:08:17 -08:00
|
|
|
|
|
|
|
|
// Only check traits, don't check trait aliases
|
2023-10-16 15:39:07 +00:00
|
|
|
if let hir::ItemKind::Trait(..) = item.kind {
|
|
|
|
|
check_gat_where_clauses(tcx, item.owner_id.def_id);
|
2022-02-11 00:08:17 -08:00
|
|
|
}
|
2023-10-18 08:47:17 +00:00
|
|
|
res
|
2018-03-12 22:18:51 -04:00
|
|
|
}
|
2015-08-07 09:39:54 -04:00
|
|
|
|
2019-06-15 20:51:13 +02:00
|
|
|
/// Checks all associated type defaults of trait `trait_def_id`.
|
|
|
|
|
///
|
|
|
|
|
/// Assuming the defaults are used, check that all predicates (bounds on the
|
|
|
|
|
/// assoc type and where clauses on the trait) hold.
|
2023-02-06 08:57:34 +00:00
|
|
|
fn check_associated_type_bounds(wfcx: &WfCheckingCtxt<'_, '_>, item: ty::AssocItem, span: Span) {
|
2022-07-07 15:12:32 +02:00
|
|
|
let bounds = wfcx.tcx().explicit_item_bounds(item.def_id);
|
2020-06-27 21:36:35 +01:00
|
|
|
|
|
|
|
|
debug!("check_associated_type_bounds: bounds={:?}", bounds);
|
2024-07-06 11:54:22 -04:00
|
|
|
let wf_obligations = bounds.iter_identity_copied().flat_map(|(bound, bound_span)| {
|
|
|
|
|
let normalized_bound = wfcx.normalize(span, None, bound);
|
|
|
|
|
traits::wf::clause_obligations(
|
|
|
|
|
wfcx.infcx,
|
|
|
|
|
wfcx.param_env,
|
|
|
|
|
wfcx.body_def_id,
|
|
|
|
|
normalized_bound,
|
|
|
|
|
bound_span,
|
|
|
|
|
)
|
|
|
|
|
});
|
2019-06-15 19:02:27 +02:00
|
|
|
|
2022-07-07 15:12:32 +02:00
|
|
|
wfcx.register_obligations(wf_obligations);
|
2018-03-12 22:18:51 -04:00
|
|
|
}
|
2015-08-07 09:39:54 -04:00
|
|
|
|
2020-06-13 19:37:25 +01:00
|
|
|
fn check_item_fn(
|
|
|
|
|
tcx: TyCtxt<'_>,
|
2021-10-13 22:22:09 -04:00
|
|
|
def_id: LocalDefId,
|
2020-06-13 19:37:25 +01:00
|
|
|
ident: Ident,
|
|
|
|
|
span: Span,
|
|
|
|
|
decl: &hir::FnDecl<'_>,
|
2023-10-18 08:47:17 +00:00
|
|
|
) -> Result<(), ErrorGuaranteed> {
|
2022-07-07 15:12:32 +02:00
|
|
|
enter_wf_checking_ctxt(tcx, span, def_id, |wfcx| {
|
2023-07-11 22:35:29 +01:00
|
|
|
let sig = tcx.fn_sig(def_id).instantiate_identity();
|
2022-08-17 12:22:32 +02:00
|
|
|
check_fn_or_method(wfcx, ident.span, sig, decl, def_id);
|
2023-10-30 15:54:08 +00:00
|
|
|
Ok(())
|
2018-03-12 22:18:51 -04:00
|
|
|
})
|
|
|
|
|
}
|
2015-08-07 09:39:54 -04:00
|
|
|
|
2023-03-07 12:03:11 +00:00
|
|
|
enum UnsizedHandling {
|
|
|
|
|
Forbid,
|
|
|
|
|
Allow,
|
|
|
|
|
AllowIfForeignTail,
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn check_item_type(
|
|
|
|
|
tcx: TyCtxt<'_>,
|
|
|
|
|
item_id: LocalDefId,
|
|
|
|
|
ty_span: Span,
|
|
|
|
|
unsized_handling: UnsizedHandling,
|
2023-10-18 08:47:17 +00:00
|
|
|
) -> Result<(), ErrorGuaranteed> {
|
2018-10-11 18:02:00 +02:00
|
|
|
debug!("check_item_type: {:?}", item_id);
|
|
|
|
|
|
2022-07-07 15:12:32 +02:00
|
|
|
enter_wf_checking_ctxt(tcx, ty_span, item_id, |wfcx| {
|
2023-07-11 22:35:29 +01:00
|
|
|
let ty = tcx.type_of(item_id).instantiate_identity();
|
2022-07-07 15:12:32 +02:00
|
|
|
let item_ty = wfcx.normalize(ty_span, Some(WellFormedLoc::Ty(item_id)), ty);
|
2018-10-11 18:02:00 +02:00
|
|
|
|
2023-03-07 12:03:11 +00:00
|
|
|
let forbid_unsized = match unsized_handling {
|
|
|
|
|
UnsizedHandling::Forbid => true,
|
|
|
|
|
UnsizedHandling::Allow => false,
|
|
|
|
|
UnsizedHandling::AllowIfForeignTail => {
|
2024-11-15 13:53:31 +01:00
|
|
|
let tail =
|
|
|
|
|
tcx.struct_tail_for_codegen(item_ty, wfcx.infcx.typing_env(wfcx.param_env));
|
2023-03-07 12:03:11 +00:00
|
|
|
!matches!(tail.kind(), ty::Foreign(_))
|
2018-10-21 20:09:42 -07:00
|
|
|
}
|
2023-03-07 12:03:11 +00:00
|
|
|
};
|
2018-10-21 20:09:42 -07:00
|
|
|
|
2022-07-07 15:12:32 +02:00
|
|
|
wfcx.register_wf_obligation(ty_span, Some(WellFormedLoc::Ty(item_id)), item_ty.into());
|
2018-10-22 07:03:53 -07:00
|
|
|
if forbid_unsized {
|
2022-07-07 15:12:32 +02:00
|
|
|
wfcx.register_bound(
|
2024-05-09 20:05:59 -04:00
|
|
|
traits::ObligationCause::new(
|
|
|
|
|
ty_span,
|
|
|
|
|
wfcx.body_def_id,
|
|
|
|
|
ObligationCauseCode::WellFormed(None),
|
|
|
|
|
),
|
2022-07-07 15:12:32 +02:00
|
|
|
wfcx.param_env,
|
2018-10-21 20:09:42 -07:00
|
|
|
item_ty,
|
2021-05-07 12:15:38 +02:00
|
|
|
tcx.require_lang_item(LangItem::Sized, None),
|
2018-10-21 20:09:42 -07:00
|
|
|
);
|
|
|
|
|
}
|
2015-08-07 09:39:54 -04:00
|
|
|
|
2021-11-26 14:11:45 +00:00
|
|
|
// Ensure that the end result is `Sync` in a non-thread local `static`.
|
|
|
|
|
let should_check_for_sync = tcx.static_mutability(item_id.to_def_id())
|
|
|
|
|
== Some(hir::Mutability::Not)
|
|
|
|
|
&& !tcx.is_foreign_item(item_id.to_def_id())
|
|
|
|
|
&& !tcx.is_thread_local_static(item_id.to_def_id());
|
|
|
|
|
|
|
|
|
|
if should_check_for_sync {
|
2022-07-07 15:12:32 +02:00
|
|
|
wfcx.register_bound(
|
2024-05-09 20:05:59 -04:00
|
|
|
traits::ObligationCause::new(
|
|
|
|
|
ty_span,
|
|
|
|
|
wfcx.body_def_id,
|
|
|
|
|
ObligationCauseCode::SharedStatic,
|
|
|
|
|
),
|
2022-07-07 15:12:32 +02:00
|
|
|
wfcx.param_env,
|
2021-11-26 14:11:45 +00:00
|
|
|
item_ty,
|
|
|
|
|
tcx.require_lang_item(LangItem::Sync, Some(ty_span)),
|
|
|
|
|
);
|
|
|
|
|
}
|
2023-10-30 15:54:08 +00:00
|
|
|
Ok(())
|
2023-10-18 08:47:17 +00:00
|
|
|
})
|
2018-03-12 22:18:51 -04:00
|
|
|
}
|
2015-08-07 09:39:54 -04:00
|
|
|
|
2024-03-01 12:33:14 +01:00
|
|
|
#[instrument(level = "debug", skip(tcx, hir_self_ty, hir_trait_ref))]
|
2019-06-12 00:11:55 +03:00
|
|
|
fn check_impl<'tcx>(
|
2019-06-14 00:48:52 +03:00
|
|
|
tcx: TyCtxt<'tcx>,
|
2019-11-28 19:28:50 +01:00
|
|
|
item: &'tcx hir::Item<'tcx>,
|
2024-03-01 12:33:14 +01:00
|
|
|
hir_self_ty: &hir::Ty<'_>,
|
|
|
|
|
hir_trait_ref: &Option<hir::TraitRef<'_>>,
|
2023-10-18 08:47:17 +00:00
|
|
|
) -> Result<(), ErrorGuaranteed> {
|
2022-10-27 14:02:18 +11:00
|
|
|
enter_wf_checking_ctxt(tcx, item.span, item.owner_id.def_id, |wfcx| {
|
2024-03-01 12:33:14 +01:00
|
|
|
match hir_trait_ref {
|
|
|
|
|
Some(hir_trait_ref) => {
|
2019-07-13 18:02:00 +03:00
|
|
|
// `#[rustc_reservation_impl]` impls are not real impls and
|
|
|
|
|
// therefore don't need to be WF (the trait's `Self: Trait` predicate
|
|
|
|
|
// won't hold).
|
2023-07-11 22:35:29 +01:00
|
|
|
let trait_ref = tcx.impl_trait_ref(item.owner_id).unwrap().instantiate_identity();
|
2024-02-02 08:36:46 +00:00
|
|
|
// Avoid bogus "type annotations needed `Foo: Bar`" errors on `impl Bar for Foo` in case
|
|
|
|
|
// other `Foo` impls are incoherent.
|
|
|
|
|
tcx.ensure().coherent_trait(trait_ref.def_id)?;
|
2024-03-01 12:33:14 +01:00
|
|
|
let trait_span = hir_trait_ref.path.span;
|
2023-01-12 18:51:09 +00:00
|
|
|
let trait_ref = wfcx.normalize(
|
2024-02-08 16:56:47 +01:00
|
|
|
trait_span,
|
2023-01-12 18:51:09 +00:00
|
|
|
Some(WellFormedLoc::Ty(item.hir_id().expect_owner().def_id)),
|
|
|
|
|
trait_ref,
|
|
|
|
|
);
|
2023-07-29 08:20:25 +00:00
|
|
|
let trait_pred =
|
2024-03-21 15:45:28 -04:00
|
|
|
ty::TraitPredicate { trait_ref, polarity: ty::PredicatePolarity::Positive };
|
2023-01-12 20:28:57 +00:00
|
|
|
let mut obligations = traits::wf::trait_obligations(
|
2022-07-07 15:12:32 +02:00
|
|
|
wfcx.infcx,
|
|
|
|
|
wfcx.param_env,
|
2023-01-15 12:58:46 +01:00
|
|
|
wfcx.body_def_id,
|
2023-09-29 11:34:50 +02:00
|
|
|
trait_pred,
|
2024-02-08 16:56:47 +01:00
|
|
|
trait_span,
|
2022-06-01 17:06:07 +09:00
|
|
|
item,
|
2019-10-10 16:20:42 -07:00
|
|
|
);
|
2023-01-12 20:28:57 +00:00
|
|
|
for obligation in &mut obligations {
|
2024-02-08 16:56:47 +01:00
|
|
|
if obligation.cause.span != trait_span {
|
|
|
|
|
// We already have a better span.
|
|
|
|
|
continue;
|
|
|
|
|
}
|
2024-05-15 12:58:41 -04:00
|
|
|
if let Some(pred) = obligation.predicate.as_trait_clause()
|
2024-02-08 16:56:47 +01:00
|
|
|
&& pred.skip_binder().self_ty() == trait_ref.self_ty()
|
|
|
|
|
{
|
2024-03-01 12:33:14 +01:00
|
|
|
obligation.cause.span = hir_self_ty.span;
|
2024-02-08 16:56:47 +01:00
|
|
|
}
|
2024-05-15 12:58:41 -04:00
|
|
|
if let Some(pred) = obligation.predicate.as_projection_clause()
|
2024-02-08 16:56:47 +01:00
|
|
|
&& pred.skip_binder().self_ty() == trait_ref.self_ty()
|
2023-01-12 20:28:57 +00:00
|
|
|
{
|
2024-03-01 12:33:14 +01:00
|
|
|
obligation.cause.span = hir_self_ty.span;
|
2023-01-12 20:28:57 +00:00
|
|
|
}
|
|
|
|
|
}
|
2024-10-20 19:49:11 +00:00
|
|
|
|
|
|
|
|
// Ensure that the `~const` where clauses of the trait hold for the impl.
|
2024-10-23 16:53:59 +00:00
|
|
|
if tcx.is_conditionally_const(item.owner_id.def_id) {
|
2024-10-20 19:49:11 +00:00
|
|
|
for (bound, _) in
|
|
|
|
|
tcx.const_conditions(trait_ref.def_id).instantiate(tcx, trait_ref.args)
|
|
|
|
|
{
|
|
|
|
|
let bound = wfcx.normalize(
|
|
|
|
|
item.span,
|
|
|
|
|
Some(WellFormedLoc::Ty(item.hir_id().expect_owner().def_id)),
|
|
|
|
|
bound,
|
|
|
|
|
);
|
|
|
|
|
wfcx.register_obligation(Obligation::new(
|
|
|
|
|
tcx,
|
|
|
|
|
ObligationCause::new(
|
|
|
|
|
hir_self_ty.span,
|
|
|
|
|
wfcx.body_def_id,
|
|
|
|
|
ObligationCauseCode::WellFormed(None),
|
|
|
|
|
),
|
|
|
|
|
wfcx.param_env,
|
2024-10-29 23:42:59 +00:00
|
|
|
bound.to_host_effect_clause(tcx, ty::BoundConstness::Maybe),
|
2024-10-20 19:49:11 +00:00
|
|
|
))
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2021-07-16 16:23:42 -04:00
|
|
|
debug!(?obligations);
|
2022-07-07 15:12:32 +02:00
|
|
|
wfcx.register_obligations(obligations);
|
2015-08-07 09:39:54 -04:00
|
|
|
}
|
2018-03-12 22:18:51 -04:00
|
|
|
None => {
|
2023-07-11 22:35:29 +01:00
|
|
|
let self_ty = tcx.type_of(item.owner_id).instantiate_identity();
|
2022-08-30 06:19:48 +00:00
|
|
|
let self_ty = wfcx.normalize(
|
|
|
|
|
item.span,
|
2022-09-20 14:11:23 +09:00
|
|
|
Some(WellFormedLoc::Ty(item.hir_id().expect_owner().def_id)),
|
2022-08-30 06:19:48 +00:00
|
|
|
self_ty,
|
|
|
|
|
);
|
2022-07-07 15:12:32 +02:00
|
|
|
wfcx.register_wf_obligation(
|
2024-03-01 12:33:14 +01:00
|
|
|
hir_self_ty.span,
|
2022-09-20 14:11:23 +09:00
|
|
|
Some(WellFormedLoc::Ty(item.hir_id().expect_owner().def_id)),
|
2022-07-07 15:12:32 +02:00
|
|
|
self_ty.into(),
|
2019-12-24 17:38:22 -05:00
|
|
|
);
|
2018-03-12 22:18:51 -04:00
|
|
|
}
|
|
|
|
|
}
|
2015-08-07 09:39:54 -04:00
|
|
|
|
2022-10-27 14:02:18 +11:00
|
|
|
check_where_clauses(wfcx, item.span, item.owner_id.def_id);
|
2023-10-30 15:54:08 +00:00
|
|
|
Ok(())
|
2023-10-18 08:47:17 +00:00
|
|
|
})
|
2018-03-12 22:18:51 -04:00
|
|
|
}
|
2015-08-07 09:39:54 -04:00
|
|
|
|
2019-02-08 14:53:55 +01:00
|
|
|
/// Checks where-clauses and inline bounds that are declared on `def_id`.
|
2022-07-07 15:12:32 +02:00
|
|
|
#[instrument(level = "debug", skip(wfcx))]
|
|
|
|
|
fn check_where_clauses<'tcx>(wfcx: &WfCheckingCtxt<'_, 'tcx>, span: Span, def_id: LocalDefId) {
|
|
|
|
|
let infcx = wfcx.infcx;
|
|
|
|
|
let tcx = wfcx.tcx();
|
2019-02-28 22:43:53 +00:00
|
|
|
|
2023-01-03 05:01:17 +00:00
|
|
|
let predicates = tcx.predicates_of(def_id.to_def_id());
|
2018-03-12 22:18:51 -04:00
|
|
|
let generics = tcx.generics_of(def_id);
|
2019-05-03 14:42:32 +01:00
|
|
|
|
2018-03-12 22:18:51 -04:00
|
|
|
// Check that concrete defaults are well-formed. See test `type-check-defaults.rs`.
|
2019-02-28 22:43:53 +00:00
|
|
|
// For example, this forbids the declaration:
|
|
|
|
|
//
|
|
|
|
|
// struct Foo<T = Vec<[u32]>> { .. }
|
|
|
|
|
//
|
|
|
|
|
// Here, the default `Vec<[u32]>` is not WF because `[u32]: Sized` does not hold.
|
2024-05-09 20:56:44 -04:00
|
|
|
for param in &generics.own_params {
|
2024-11-11 18:41:27 +01:00
|
|
|
if let Some(default) = param.default_value(tcx).map(ty::EarlyBinder::instantiate_identity) {
|
|
|
|
|
// Ignore dependent defaults -- that is, where the default of one type
|
|
|
|
|
// parameter includes another (e.g., `<T, U = T>`). In those cases, we can't
|
|
|
|
|
// be sure if it will error or not as user might always specify the other.
|
|
|
|
|
// FIXME(generic_const_exprs): This is incorrect when dealing with unused const params.
|
|
|
|
|
// E.g: `struct Foo<const N: usize, const M: usize = { 1 - 2 }>;`. Here, we should
|
|
|
|
|
// eagerly error but we don't as we have `ConstKind::Unevaluated(.., [N, M])`.
|
|
|
|
|
if !default.has_param() {
|
|
|
|
|
wfcx.register_wf_obligation(
|
|
|
|
|
tcx.def_span(param.def_id),
|
|
|
|
|
matches!(param.kind, GenericParamDefKind::Type { .. })
|
|
|
|
|
.then(|| WellFormedLoc::Ty(param.def_id.expect_local())),
|
|
|
|
|
default,
|
|
|
|
|
);
|
2018-04-14 19:20:51 +01:00
|
|
|
}
|
|
|
|
|
}
|
2018-03-12 22:18:51 -04:00
|
|
|
}
|
2018-01-20 13:33:44 -02:00
|
|
|
|
2024-02-12 15:39:32 +09:00
|
|
|
// Check that trait predicates are WF when params are instantiated with their defaults.
|
2018-03-12 22:18:51 -04:00
|
|
|
// We don't want to overly constrain the predicates that may be written but we want to
|
|
|
|
|
// catch cases where a default my never be applied such as `struct Foo<T: Copy = String>`.
|
|
|
|
|
// Therefore we check if a predicate which contains a single type param
|
2024-02-12 15:39:32 +09:00
|
|
|
// with a concrete default is WF with that default instantiated.
|
2018-03-12 22:18:51 -04:00
|
|
|
// For more examples see tests `defaults-well-formedness.rs` and `type-check-defaults.rs`.
|
|
|
|
|
//
|
2024-02-12 15:39:32 +09:00
|
|
|
// First we build the defaulted generic parameters.
|
2023-07-11 22:35:29 +01:00
|
|
|
let args = GenericArgs::for_item(tcx, def_id.to_def_id(), |param, _| {
|
2024-11-11 18:41:27 +01:00
|
|
|
if param.index >= generics.parent_count as u32
|
|
|
|
|
// If the param has a default, ...
|
|
|
|
|
&& let Some(default) = param.default_value(tcx).map(ty::EarlyBinder::instantiate_identity)
|
|
|
|
|
// ... and it's not a dependent default, ...
|
|
|
|
|
&& !default.has_param()
|
|
|
|
|
{
|
|
|
|
|
// ... then instantiate it with the default.
|
|
|
|
|
return default;
|
2018-05-14 18:27:13 +01:00
|
|
|
}
|
2024-11-11 18:41:27 +01:00
|
|
|
tcx.mk_param_from_def(param)
|
2018-05-14 18:27:13 +01:00
|
|
|
});
|
2019-05-03 14:42:32 +01:00
|
|
|
|
2024-02-12 15:39:32 +09:00
|
|
|
// Now we build the instantiated predicates.
|
2019-12-24 17:38:22 -05:00
|
|
|
let default_obligations = predicates
|
|
|
|
|
.predicates
|
|
|
|
|
.iter()
|
|
|
|
|
.flat_map(|&(pred, sp)| {
|
2022-01-12 03:19:52 +00:00
|
|
|
#[derive(Default)]
|
|
|
|
|
struct CountParams {
|
2019-12-24 17:38:22 -05:00
|
|
|
params: FxHashSet<u32>,
|
2018-02-09 08:42:11 -02:00
|
|
|
}
|
2023-02-22 02:18:40 +00:00
|
|
|
impl<'tcx> ty::visit::TypeVisitor<TyCtxt<'tcx>> for CountParams {
|
2024-02-24 17:22:28 -05:00
|
|
|
type Result = ControlFlow<()>;
|
|
|
|
|
fn visit_ty(&mut self, t: Ty<'tcx>) -> Self::Result {
|
2020-08-03 00:49:11 +02:00
|
|
|
if let ty::Param(param) = t.kind() {
|
2019-12-24 17:38:22 -05:00
|
|
|
self.params.insert(param.index);
|
|
|
|
|
}
|
|
|
|
|
t.super_visit_with(self)
|
|
|
|
|
}
|
2018-04-05 15:21:56 -03:00
|
|
|
|
2024-02-24 17:22:28 -05:00
|
|
|
fn visit_region(&mut self, _: ty::Region<'tcx>) -> Self::Result {
|
2023-01-17 23:17:13 -08:00
|
|
|
ControlFlow::Break(())
|
2019-12-24 17:38:22 -05:00
|
|
|
}
|
2019-02-20 01:17:15 +00:00
|
|
|
|
2024-02-24 17:22:28 -05:00
|
|
|
fn visit_const(&mut self, c: ty::Const<'tcx>) -> Self::Result {
|
2022-06-10 11:18:06 +10:00
|
|
|
if let ty::ConstKind::Param(param) = c.kind() {
|
2019-12-24 17:38:22 -05:00
|
|
|
self.params.insert(param.index);
|
|
|
|
|
}
|
|
|
|
|
c.super_visit_with(self)
|
2019-02-20 01:17:15 +00:00
|
|
|
}
|
|
|
|
|
}
|
2022-01-12 03:19:52 +00:00
|
|
|
let mut param_count = CountParams::default();
|
2020-10-22 10:20:24 +02:00
|
|
|
let has_region = pred.visit_with(&mut param_count).is_break();
|
2024-02-12 15:39:32 +09:00
|
|
|
let instantiated_pred = ty::EarlyBinder::bind(pred).instantiate(tcx, args);
|
2019-12-24 17:38:22 -05:00
|
|
|
// Don't check non-defaulted params, dependent defaults (including lifetimes)
|
|
|
|
|
// or preds with multiple params.
|
2024-02-12 15:39:32 +09:00
|
|
|
if instantiated_pred.has_non_region_param()
|
|
|
|
|
|| param_count.params.len() > 1
|
|
|
|
|
|| has_region
|
2020-04-06 19:03:54 -05:00
|
|
|
{
|
2019-12-24 17:38:22 -05:00
|
|
|
None
|
2024-02-12 15:39:32 +09:00
|
|
|
} else if predicates.predicates.iter().any(|&(p, _)| p == instantiated_pred) {
|
2019-12-24 17:38:22 -05:00
|
|
|
// Avoid duplication of predicates that contain no parameters, for example.
|
|
|
|
|
None
|
|
|
|
|
} else {
|
2024-02-12 15:39:32 +09:00
|
|
|
Some((instantiated_pred, sp))
|
2019-12-24 17:38:22 -05:00
|
|
|
}
|
|
|
|
|
})
|
|
|
|
|
.map(|(pred, sp)| {
|
|
|
|
|
// Convert each of those into an obligation. So if you have
|
|
|
|
|
// something like `struct Foo<T: Copy = String>`, we would
|
2024-02-12 15:39:32 +09:00
|
|
|
// take that predicate `T: Copy`, instantiated with `String: Copy`
|
2019-12-24 17:38:22 -05:00
|
|
|
// (actually that happens in the previous `flat_map` call),
|
|
|
|
|
// and then try to prove it (in this case, we'll fail).
|
|
|
|
|
//
|
|
|
|
|
// Note the subtle difference from how we handle `predicates`
|
|
|
|
|
// below: there, we are not trying to prove those predicates
|
|
|
|
|
// to be *true* but merely *well-formed*.
|
2022-07-07 15:12:32 +02:00
|
|
|
let pred = wfcx.normalize(sp, None, pred);
|
2022-04-01 13:38:43 +02:00
|
|
|
let cause = traits::ObligationCause::new(
|
|
|
|
|
sp,
|
2023-01-15 12:58:46 +01:00
|
|
|
wfcx.body_def_id,
|
2024-05-10 11:04:53 -04:00
|
|
|
ObligationCauseCode::WhereClause(def_id.to_def_id(), DUMMY_SP),
|
2022-04-01 13:38:43 +02:00
|
|
|
);
|
2024-10-20 19:49:11 +00:00
|
|
|
Obligation::new(tcx, cause, wfcx.param_env, pred)
|
2019-12-24 17:38:22 -05:00
|
|
|
});
|
2015-08-07 09:39:54 -04:00
|
|
|
|
2023-01-03 05:01:17 +00:00
|
|
|
let predicates = predicates.instantiate_identity(tcx);
|
2018-07-03 19:38:14 +02:00
|
|
|
|
2022-07-07 15:12:32 +02:00
|
|
|
let predicates = wfcx.normalize(span, None, predicates);
|
2018-03-12 22:18:51 -04:00
|
|
|
|
2021-09-16 19:08:25 +00:00
|
|
|
debug!(?predicates.predicates);
|
2020-01-29 16:55:37 -08:00
|
|
|
assert_eq!(predicates.predicates.len(), predicates.spans.len());
|
2023-01-03 03:32:59 +00:00
|
|
|
let wf_obligations = predicates.into_iter().flat_map(|(p, sp)| {
|
2023-09-29 11:34:50 +02:00
|
|
|
traits::wf::clause_obligations(infcx, wfcx.param_env, wfcx.body_def_id, p, sp)
|
2023-01-03 03:32:59 +00:00
|
|
|
});
|
2022-07-07 15:12:32 +02:00
|
|
|
let obligations: Vec<_> = wf_obligations.chain(default_obligations).collect();
|
|
|
|
|
wfcx.register_obligations(obligations);
|
2018-03-12 22:18:51 -04:00
|
|
|
}
|
2015-08-07 09:39:54 -04:00
|
|
|
|
2022-08-31 13:01:10 +00:00
|
|
|
#[instrument(level = "debug", skip(wfcx, span, hir_decl))]
|
2022-07-07 15:12:32 +02:00
|
|
|
fn check_fn_or_method<'tcx>(
|
|
|
|
|
wfcx: &WfCheckingCtxt<'_, 'tcx>,
|
2019-06-12 00:11:55 +03:00
|
|
|
span: Span,
|
|
|
|
|
sig: ty::PolyFnSig<'tcx>,
|
2020-06-13 19:37:25 +01:00
|
|
|
hir_decl: &hir::FnDecl<'_>,
|
2022-04-01 13:38:43 +02:00
|
|
|
def_id: LocalDefId,
|
2019-06-12 00:11:55 +03:00
|
|
|
) {
|
2022-07-07 15:12:32 +02:00
|
|
|
let tcx = wfcx.tcx();
|
2023-01-08 02:40:59 +00:00
|
|
|
let mut sig = tcx.liberate_late_bound_regions(def_id.to_def_id(), sig);
|
2018-03-12 22:18:51 -04:00
|
|
|
|
Support HIR wf checking for function signatures
During function type-checking, we normalize any associated types in
the function signature (argument types + return type), and then
create WF obligations for each of the normalized types. The HIR wf code
does not currently support this case, so any errors that we get have
imprecise spans.
This commit extends `ObligationCauseCode::WellFormed` to support
recording a function parameter, allowing us to get the corresponding
HIR type if an error occurs. Function typechecking is modified to
pass this information during signature normalization and WF checking.
The resulting code is fairly verbose, due to the fact that we can
no longer normalize the entire signature with a single function call.
As part of the refactoring, we now perform HIR-based WF checking
for several other 'typed items' (statics, consts, and inherent impls).
As a result, WF and projection errors in a function signature now
have a precise span, which points directly at the responsible type.
If a function signature is constructed via a macro, this will allow
the error message to point at the code 'most responsible' for the error
(e.g. a user-supplied macro argument).
2021-07-18 11:33:49 -05:00
|
|
|
// Normalize the input and output types one at a time, using a different
|
|
|
|
|
// `WellFormedLoc` for each. We cannot call `normalize_associated_types`
|
|
|
|
|
// on the entire `FnSig`, since this would use the same `WellFormedLoc`
|
|
|
|
|
// for each type, preventing the HIR wf check from generating
|
|
|
|
|
// a nice error message.
|
2023-01-08 02:40:59 +00:00
|
|
|
let arg_span =
|
|
|
|
|
|idx| hir_decl.inputs.get(idx).map_or(hir_decl.output.span(), |arg: &hir::Ty<'_>| arg.span);
|
|
|
|
|
|
|
|
|
|
sig.inputs_and_output =
|
2023-02-17 14:33:08 +11:00
|
|
|
tcx.mk_type_list_from_iter(sig.inputs_and_output.iter().enumerate().map(|(idx, ty)| {
|
2023-01-08 02:40:59 +00:00
|
|
|
wfcx.normalize(
|
|
|
|
|
arg_span(idx),
|
|
|
|
|
Some(WellFormedLoc::Param {
|
|
|
|
|
function: def_id,
|
|
|
|
|
// Note that the `param_idx` of the output type is
|
|
|
|
|
// one greater than the index of the last input type.
|
2024-09-11 14:58:08 -04:00
|
|
|
param_idx: idx,
|
2023-01-08 02:40:59 +00:00
|
|
|
}),
|
|
|
|
|
ty,
|
|
|
|
|
)
|
|
|
|
|
}));
|
Support HIR wf checking for function signatures
During function type-checking, we normalize any associated types in
the function signature (argument types + return type), and then
create WF obligations for each of the normalized types. The HIR wf code
does not currently support this case, so any errors that we get have
imprecise spans.
This commit extends `ObligationCauseCode::WellFormed` to support
recording a function parameter, allowing us to get the corresponding
HIR type if an error occurs. Function typechecking is modified to
pass this information during signature normalization and WF checking.
The resulting code is fairly verbose, due to the fact that we can
no longer normalize the entire signature with a single function call.
As part of the refactoring, we now perform HIR-based WF checking
for several other 'typed items' (statics, consts, and inherent impls).
As a result, WF and projection errors in a function signature now
have a precise span, which points directly at the responsible type.
If a function signature is constructed via a macro, this will allow
the error message to point at the code 'most responsible' for the error
(e.g. a user-supplied macro argument).
2021-07-18 11:33:49 -05:00
|
|
|
|
2023-01-08 02:40:59 +00:00
|
|
|
for (idx, ty) in sig.inputs_and_output.iter().enumerate() {
|
2022-07-07 15:12:32 +02:00
|
|
|
wfcx.register_wf_obligation(
|
2023-01-08 02:40:59 +00:00
|
|
|
arg_span(idx),
|
2024-09-11 14:58:08 -04:00
|
|
|
Some(WellFormedLoc::Param { function: def_id, param_idx: idx }),
|
2023-01-08 02:40:59 +00:00
|
|
|
ty.into(),
|
Support HIR wf checking for function signatures
During function type-checking, we normalize any associated types in
the function signature (argument types + return type), and then
create WF obligations for each of the normalized types. The HIR wf code
does not currently support this case, so any errors that we get have
imprecise spans.
This commit extends `ObligationCauseCode::WellFormed` to support
recording a function parameter, allowing us to get the corresponding
HIR type if an error occurs. Function typechecking is modified to
pass this information during signature normalization and WF checking.
The resulting code is fairly verbose, due to the fact that we can
no longer normalize the entire signature with a single function call.
As part of the refactoring, we now perform HIR-based WF checking
for several other 'typed items' (statics, consts, and inherent impls).
As a result, WF and projection errors in a function signature now
have a precise span, which points directly at the responsible type.
If a function signature is constructed via a macro, this will allow
the error message to point at the code 'most responsible' for the error
(e.g. a user-supplied macro argument).
2021-07-18 11:33:49 -05:00
|
|
|
);
|
2018-03-12 22:18:51 -04:00
|
|
|
}
|
Support HIR wf checking for function signatures
During function type-checking, we normalize any associated types in
the function signature (argument types + return type), and then
create WF obligations for each of the normalized types. The HIR wf code
does not currently support this case, so any errors that we get have
imprecise spans.
This commit extends `ObligationCauseCode::WellFormed` to support
recording a function parameter, allowing us to get the corresponding
HIR type if an error occurs. Function typechecking is modified to
pass this information during signature normalization and WF checking.
The resulting code is fairly verbose, due to the fact that we can
no longer normalize the entire signature with a single function call.
As part of the refactoring, we now perform HIR-based WF checking
for several other 'typed items' (statics, consts, and inherent impls).
As a result, WF and projection errors in a function signature now
have a precise span, which points directly at the responsible type.
If a function signature is constructed via a macro, this will allow
the error message to point at the code 'most responsible' for the error
(e.g. a user-supplied macro argument).
2021-07-18 11:33:49 -05:00
|
|
|
|
2022-07-07 15:12:32 +02:00
|
|
|
check_where_clauses(wfcx, span, def_id);
|
2022-09-11 06:58:11 +00:00
|
|
|
|
2024-11-02 19:32:56 -07:00
|
|
|
if sig.abi == ExternAbi::RustCall {
|
2022-07-30 03:41:53 +00:00
|
|
|
let span = tcx.def_span(def_id);
|
|
|
|
|
let has_implicit_self = hir_decl.implicit_self != hir::ImplicitSelfKind::None;
|
|
|
|
|
let mut inputs = sig.inputs().iter().skip(if has_implicit_self { 1 } else { 0 });
|
2023-05-23 17:57:08 +00:00
|
|
|
// Check that the argument is a tuple and is sized
|
2022-07-30 03:41:53 +00:00
|
|
|
if let Some(ty) = inputs.next() {
|
|
|
|
|
wfcx.register_bound(
|
2023-01-15 12:58:46 +01:00
|
|
|
ObligationCause::new(span, wfcx.body_def_id, ObligationCauseCode::RustCall),
|
2022-07-30 03:41:53 +00:00
|
|
|
wfcx.param_env,
|
|
|
|
|
*ty,
|
|
|
|
|
tcx.require_lang_item(hir::LangItem::Tuple, Some(span)),
|
|
|
|
|
);
|
2023-05-23 17:57:08 +00:00
|
|
|
wfcx.register_bound(
|
|
|
|
|
ObligationCause::new(span, wfcx.body_def_id, ObligationCauseCode::RustCall),
|
|
|
|
|
wfcx.param_env,
|
|
|
|
|
*ty,
|
|
|
|
|
tcx.require_lang_item(hir::LangItem::Sized, Some(span)),
|
|
|
|
|
);
|
2022-07-30 03:41:53 +00:00
|
|
|
} else {
|
2023-12-18 22:21:37 +11:00
|
|
|
tcx.dcx().span_err(
|
2022-07-30 05:37:48 +00:00
|
|
|
hir_decl.inputs.last().map_or(span, |input| input.span),
|
|
|
|
|
"functions with the \"rust-call\" ABI must take a single non-self tuple argument",
|
|
|
|
|
);
|
2022-07-30 03:41:53 +00:00
|
|
|
}
|
|
|
|
|
// No more inputs other than the `self` type and the tuple type
|
|
|
|
|
if inputs.next().is_some() {
|
2023-12-18 22:21:37 +11:00
|
|
|
tcx.dcx().span_err(
|
2022-07-30 05:37:48 +00:00
|
|
|
hir_decl.inputs.last().map_or(span, |input| input.span),
|
|
|
|
|
"functions with the \"rust-call\" ABI must take a single non-self tuple argument",
|
|
|
|
|
);
|
2022-07-30 03:41:53 +00:00
|
|
|
}
|
|
|
|
|
}
|
2022-09-11 06:58:11 +00:00
|
|
|
}
|
|
|
|
|
|
2024-03-30 19:25:22 +00:00
|
|
|
/// The `arbitrary_self_types_pointers` feature implies `arbitrary_self_types`.
|
2024-08-30 16:57:05 +00:00
|
|
|
#[derive(Clone, Copy, PartialEq)]
|
2024-03-30 19:25:22 +00:00
|
|
|
enum ArbitrarySelfTypesLevel {
|
2024-08-30 16:57:05 +00:00
|
|
|
Basic, // just arbitrary_self_types
|
|
|
|
|
WithPointers, // both arbitrary_self_types and arbitrary_self_types_pointers
|
2024-03-30 19:25:22 +00:00
|
|
|
}
|
|
|
|
|
|
2022-08-31 13:01:10 +00:00
|
|
|
#[instrument(level = "debug", skip(wfcx))]
|
2022-07-07 15:12:32 +02:00
|
|
|
fn check_method_receiver<'tcx>(
|
|
|
|
|
wfcx: &WfCheckingCtxt<'_, 'tcx>,
|
2019-11-30 15:20:35 +01:00
|
|
|
fn_sig: &hir::FnSig<'_>,
|
2023-02-06 08:57:34 +00:00
|
|
|
method: ty::AssocItem,
|
2019-06-14 01:32:15 +03:00
|
|
|
self_ty: Ty<'tcx>,
|
2023-10-30 15:54:08 +00:00
|
|
|
) -> Result<(), ErrorGuaranteed> {
|
2022-07-07 15:12:32 +02:00
|
|
|
let tcx = wfcx.tcx();
|
2018-03-12 22:18:51 -04:00
|
|
|
|
2020-04-01 10:09:50 +08:00
|
|
|
if !method.fn_has_self_parameter {
|
2023-10-30 15:54:08 +00:00
|
|
|
return Ok(());
|
2018-03-12 22:18:51 -04:00
|
|
|
}
|
2016-07-22 23:52:53 +03:00
|
|
|
|
2019-11-07 13:06:52 +01:00
|
|
|
let span = fn_sig.decl.inputs[0].span;
|
2016-07-22 23:52:53 +03:00
|
|
|
|
2023-07-11 22:35:29 +01:00
|
|
|
let sig = tcx.fn_sig(method.def_id).instantiate_identity();
|
2022-07-07 15:12:32 +02:00
|
|
|
let sig = tcx.liberate_late_bound_regions(method.def_id, sig);
|
|
|
|
|
let sig = wfcx.normalize(span, None, sig);
|
2016-07-22 23:52:53 +03:00
|
|
|
|
2018-03-12 22:18:51 -04:00
|
|
|
debug!("check_method_receiver: sig={:?}", sig);
|
2016-07-22 23:52:53 +03:00
|
|
|
|
2022-07-07 15:12:32 +02:00
|
|
|
let self_ty = wfcx.normalize(span, None, self_ty);
|
2017-11-08 08:24:33 -05:00
|
|
|
|
Stabilize `Rc`, `Arc` and `Pin` as method receivers
This lets you write methods using `self: Rc<Self>`, `self: Arc<Self>`, `self: Pin<&mut Self>`, `self: Pin<Box<Self>`, and other combinations involving `Pin` and another stdlib receiver type, without needing the `arbitrary_self_types`. Other user-created receiver types can be used, but they still require the feature flag to use.
This is implemented by introducing a new trait, `Receiver`, which the method receiver's type must implement if the `arbitrary_self_types` feature is not enabled. To keep composed receiver types such as `&Arc<Self>` unstable, the receiver type is also required to implement `Deref<Target=Self>` when the feature flag is not enabled.
This lets you use `self: Rc<Self>` and `self: Arc<Self>` in stable Rust, which was not allowed previously. It was agreed that they would be stabilized in #55786. `self: Pin<&Self>` and other pinned receiver types do not require the `arbitrary_self_types` feature, but they cannot be used on stable because `Pin` still requires the `pin` feature.
2018-11-20 11:50:50 -05:00
|
|
|
let receiver_ty = sig.inputs()[0];
|
2022-07-07 15:12:32 +02:00
|
|
|
let receiver_ty = wfcx.normalize(span, None, receiver_ty);
|
2017-11-08 08:24:33 -05:00
|
|
|
|
2024-02-11 23:26:06 +01:00
|
|
|
// If the receiver already has errors reported, consider it valid to avoid
|
|
|
|
|
// unnecessary errors (#58712).
|
|
|
|
|
if receiver_ty.references_error() {
|
|
|
|
|
return Ok(());
|
|
|
|
|
}
|
|
|
|
|
|
2024-10-09 09:01:57 +02:00
|
|
|
let arbitrary_self_types_level = if tcx.features().arbitrary_self_types_pointers() {
|
2024-08-30 16:57:05 +00:00
|
|
|
Some(ArbitrarySelfTypesLevel::WithPointers)
|
2024-10-09 09:01:57 +02:00
|
|
|
} else if tcx.features().arbitrary_self_types() {
|
2024-08-30 16:57:05 +00:00
|
|
|
Some(ArbitrarySelfTypesLevel::Basic)
|
Stabilize `Rc`, `Arc` and `Pin` as method receivers
This lets you write methods using `self: Rc<Self>`, `self: Arc<Self>`, `self: Pin<&mut Self>`, `self: Pin<Box<Self>`, and other combinations involving `Pin` and another stdlib receiver type, without needing the `arbitrary_self_types`. Other user-created receiver types can be used, but they still require the feature flag to use.
This is implemented by introducing a new trait, `Receiver`, which the method receiver's type must implement if the `arbitrary_self_types` feature is not enabled. To keep composed receiver types such as `&Arc<Self>` unstable, the receiver type is also required to implement `Deref<Target=Self>` when the feature flag is not enabled.
This lets you use `self: Rc<Self>` and `self: Arc<Self>` in stable Rust, which was not allowed previously. It was agreed that they would be stabilized in #55786. `self: Pin<&Self>` and other pinned receiver types do not require the `arbitrary_self_types` feature, but they cannot be used on stable because `Pin` still requires the `pin` feature.
2018-11-20 11:50:50 -05:00
|
|
|
} else {
|
2024-08-30 16:57:05 +00:00
|
|
|
None
|
2024-03-30 19:25:22 +00:00
|
|
|
};
|
2024-10-24 16:25:02 +00:00
|
|
|
let generics = tcx.generics_of(method.def_id);
|
2024-03-30 19:25:22 +00:00
|
|
|
|
Reject generic self types.
The RFC for arbitrary self types v2 declares that we should reject
"generic" self types. This commit does so.
The definition of "generic" was unclear in the RFC, but has been
explored in
https://github.com/rust-lang/rust/issues/129147
and the conclusion is that "generic" means any `self` type which
is a type parameter defined on the method itself, or references
to such a type.
This approach was chosen because other definitions of "generic"
don't work. Specifically,
* we can't filter out generic type _arguments_, because that would
filter out Rc<Self> and all the other types of smart pointer
we want to support;
* we can't filter out all type params, because Self itself is a
type param, and because existing Rust code depends on other
type params declared on the type (as opposed to the method).
This PR decides to make a new error code for this case, instead of
reusing the existing E0307 error. This makes the code a
bit more complex, but it seems we have an opportunity to provide
specific diagnostics for this case so we should do so.
This PR filters out generic self types whether or not the
'arbitrary self types' feature is enabled. However, it's believed
that it can't have any effect on code which uses stable Rust, since
there are no stable traits which can be used to indicate a valid
generic receiver type, and thus it would have been impossible to
write code which could trigger this new error case.
It is however possible that this could break existing code which
uses either of the unstable `arbitrary_self_types` or
`receiver_trait` features. This breakage is intentional; as
we move arbitrary self types towards stabilization we don't want
to continue to support generic such types.
This PR adds lots of extra tests to arbitrary-self-from-method-substs.
Most of these are ways to trigger a "type mismatch" error which
https://github.com/rust-lang/rust/blob/9b82580c7347f800c2550e6719e4218a60a80b28/compiler/rustc_hir_typeck/src/method/confirm.rs#L519
hopes can be minimized by filtering out generics in this way.
We remove a FIXME from confirm.rs suggesting that we make this change.
It's still possible to cause type mismatch errors, and a subsequent
PR may be able to improve diagnostics in this area, but it's harder
to cause these errors without contrived uses of the turbofish.
This is a part of the arbitrary self types v2 project,
https://github.com/rust-lang/rfcs/pull/3519
https://github.com/rust-lang/rust/issues/44874
r? @wesleywiser
2024-09-02 12:52:39 +00:00
|
|
|
let receiver_validity =
|
|
|
|
|
receiver_is_valid(wfcx, span, receiver_ty, self_ty, arbitrary_self_types_level, generics);
|
|
|
|
|
if let Err(receiver_validity_err) = receiver_validity {
|
2024-03-30 19:25:22 +00:00
|
|
|
return Err(match arbitrary_self_types_level {
|
|
|
|
|
// Wherever possible, emit a message advising folks that the features
|
|
|
|
|
// `arbitrary_self_types` or `arbitrary_self_types_pointers` might
|
|
|
|
|
// have helped.
|
2024-08-30 16:57:05 +00:00
|
|
|
None if receiver_is_valid(
|
|
|
|
|
wfcx,
|
|
|
|
|
span,
|
|
|
|
|
receiver_ty,
|
|
|
|
|
self_ty,
|
|
|
|
|
Some(ArbitrarySelfTypesLevel::Basic),
|
Reject generic self types.
The RFC for arbitrary self types v2 declares that we should reject
"generic" self types. This commit does so.
The definition of "generic" was unclear in the RFC, but has been
explored in
https://github.com/rust-lang/rust/issues/129147
and the conclusion is that "generic" means any `self` type which
is a type parameter defined on the method itself, or references
to such a type.
This approach was chosen because other definitions of "generic"
don't work. Specifically,
* we can't filter out generic type _arguments_, because that would
filter out Rc<Self> and all the other types of smart pointer
we want to support;
* we can't filter out all type params, because Self itself is a
type param, and because existing Rust code depends on other
type params declared on the type (as opposed to the method).
This PR decides to make a new error code for this case, instead of
reusing the existing E0307 error. This makes the code a
bit more complex, but it seems we have an opportunity to provide
specific diagnostics for this case so we should do so.
This PR filters out generic self types whether or not the
'arbitrary self types' feature is enabled. However, it's believed
that it can't have any effect on code which uses stable Rust, since
there are no stable traits which can be used to indicate a valid
generic receiver type, and thus it would have been impossible to
write code which could trigger this new error case.
It is however possible that this could break existing code which
uses either of the unstable `arbitrary_self_types` or
`receiver_trait` features. This breakage is intentional; as
we move arbitrary self types towards stabilization we don't want
to continue to support generic such types.
This PR adds lots of extra tests to arbitrary-self-from-method-substs.
Most of these are ways to trigger a "type mismatch" error which
https://github.com/rust-lang/rust/blob/9b82580c7347f800c2550e6719e4218a60a80b28/compiler/rustc_hir_typeck/src/method/confirm.rs#L519
hopes can be minimized by filtering out generics in this way.
We remove a FIXME from confirm.rs suggesting that we make this change.
It's still possible to cause type mismatch errors, and a subsequent
PR may be able to improve diagnostics in this area, but it's harder
to cause these errors without contrived uses of the turbofish.
This is a part of the arbitrary self types v2 project,
https://github.com/rust-lang/rfcs/pull/3519
https://github.com/rust-lang/rust/issues/44874
r? @wesleywiser
2024-09-02 12:52:39 +00:00
|
|
|
generics,
|
|
|
|
|
)
|
|
|
|
|
.is_ok() =>
|
2024-03-30 19:25:22 +00:00
|
|
|
{
|
2019-02-28 22:43:53 +00:00
|
|
|
// Report error; would have worked with `arbitrary_self_types`.
|
2020-01-02 12:42:42 +01:00
|
|
|
feature_err(
|
2024-01-10 00:37:30 -05:00
|
|
|
&tcx.sess,
|
2019-05-08 13:21:18 +10:00
|
|
|
sym::arbitrary_self_types,
|
2018-03-12 22:18:51 -04:00
|
|
|
span,
|
Restrict `From<S>` for `{D,Subd}iagnosticMessage`.
Currently a `{D,Subd}iagnosticMessage` can be created from any type that
impls `Into<String>`. That includes `&str`, `String`, and `Cow<'static,
str>`, which are reasonable. It also includes `&String`, which is pretty
weird, and results in many places making unnecessary allocations for
patterns like this:
```
self.fatal(&format!(...))
```
This creates a string with `format!`, takes a reference, passes the
reference to `fatal`, which does an `into()`, which clones the
reference, doing a second allocation. Two allocations for a single
string, bleh.
This commit changes the `From` impls so that you can only create a
`{D,Subd}iagnosticMessage` from `&str`, `String`, or `Cow<'static,
str>`. This requires changing all the places that currently create one
from a `&String`. Most of these are of the `&format!(...)` form
described above; each one removes an unnecessary static `&`, plus an
allocation when executed. There are also a few places where the existing
use of `&String` was more reasonable; these now just use `clone()` at
the call site.
As well as making the code nicer and more efficient, this is a step
towards possibly using `Cow<'static, str>` in
`{D,Subd}iagnosticMessage::{Str,Eager}`. That would require changing
the `From<&'a str>` impls to `From<&'static str>`, which is doable, but
I'm not yet sure if it's worthwhile.
2023-04-20 13:26:58 +10:00
|
|
|
format!(
|
2022-04-15 15:56:32 +09:00
|
|
|
"`{receiver_ty}` cannot be used as the type of `self` without \
|
2024-03-30 19:25:22 +00:00
|
|
|
the `arbitrary_self_types` feature",
|
Stabilize `Rc`, `Arc` and `Pin` as method receivers
This lets you write methods using `self: Rc<Self>`, `self: Arc<Self>`, `self: Pin<&mut Self>`, `self: Pin<Box<Self>`, and other combinations involving `Pin` and another stdlib receiver type, without needing the `arbitrary_self_types`. Other user-created receiver types can be used, but they still require the feature flag to use.
This is implemented by introducing a new trait, `Receiver`, which the method receiver's type must implement if the `arbitrary_self_types` feature is not enabled. To keep composed receiver types such as `&Arc<Self>` unstable, the receiver type is also required to implement `Deref<Target=Self>` when the feature flag is not enabled.
This lets you use `self: Rc<Self>` and `self: Arc<Self>` in stable Rust, which was not allowed previously. It was agreed that they would be stabilized in #55786. `self: Pin<&Self>` and other pinned receiver types do not require the `arbitrary_self_types` feature, but they cannot be used on stable because `Pin` still requires the `pin` feature.
2018-11-20 11:50:50 -05:00
|
|
|
),
|
2019-11-30 07:40:28 +01:00
|
|
|
)
|
2024-04-25 03:11:19 +02:00
|
|
|
.with_help(fluent::hir_analysis_invalid_receiver_ty_help)
|
2023-10-30 15:54:08 +00:00
|
|
|
.emit()
|
2024-03-30 19:25:22 +00:00
|
|
|
}
|
2024-08-30 16:57:05 +00:00
|
|
|
None | Some(ArbitrarySelfTypesLevel::Basic)
|
2024-03-30 19:25:22 +00:00
|
|
|
if receiver_is_valid(
|
|
|
|
|
wfcx,
|
|
|
|
|
span,
|
|
|
|
|
receiver_ty,
|
|
|
|
|
self_ty,
|
2024-08-30 16:57:05 +00:00
|
|
|
Some(ArbitrarySelfTypesLevel::WithPointers),
|
Reject generic self types.
The RFC for arbitrary self types v2 declares that we should reject
"generic" self types. This commit does so.
The definition of "generic" was unclear in the RFC, but has been
explored in
https://github.com/rust-lang/rust/issues/129147
and the conclusion is that "generic" means any `self` type which
is a type parameter defined on the method itself, or references
to such a type.
This approach was chosen because other definitions of "generic"
don't work. Specifically,
* we can't filter out generic type _arguments_, because that would
filter out Rc<Self> and all the other types of smart pointer
we want to support;
* we can't filter out all type params, because Self itself is a
type param, and because existing Rust code depends on other
type params declared on the type (as opposed to the method).
This PR decides to make a new error code for this case, instead of
reusing the existing E0307 error. This makes the code a
bit more complex, but it seems we have an opportunity to provide
specific diagnostics for this case so we should do so.
This PR filters out generic self types whether or not the
'arbitrary self types' feature is enabled. However, it's believed
that it can't have any effect on code which uses stable Rust, since
there are no stable traits which can be used to indicate a valid
generic receiver type, and thus it would have been impossible to
write code which could trigger this new error case.
It is however possible that this could break existing code which
uses either of the unstable `arbitrary_self_types` or
`receiver_trait` features. This breakage is intentional; as
we move arbitrary self types towards stabilization we don't want
to continue to support generic such types.
This PR adds lots of extra tests to arbitrary-self-from-method-substs.
Most of these are ways to trigger a "type mismatch" error which
https://github.com/rust-lang/rust/blob/9b82580c7347f800c2550e6719e4218a60a80b28/compiler/rustc_hir_typeck/src/method/confirm.rs#L519
hopes can be minimized by filtering out generics in this way.
We remove a FIXME from confirm.rs suggesting that we make this change.
It's still possible to cause type mismatch errors, and a subsequent
PR may be able to improve diagnostics in this area, but it's harder
to cause these errors without contrived uses of the turbofish.
This is a part of the arbitrary self types v2 project,
https://github.com/rust-lang/rfcs/pull/3519
https://github.com/rust-lang/rust/issues/44874
r? @wesleywiser
2024-09-02 12:52:39 +00:00
|
|
|
generics,
|
|
|
|
|
)
|
|
|
|
|
.is_ok() =>
|
2024-03-30 19:25:22 +00:00
|
|
|
{
|
|
|
|
|
// Report error; would have worked with `arbitrary_self_types_pointers`.
|
|
|
|
|
feature_err(
|
|
|
|
|
&tcx.sess,
|
|
|
|
|
sym::arbitrary_self_types_pointers,
|
|
|
|
|
span,
|
|
|
|
|
format!(
|
|
|
|
|
"`{receiver_ty}` cannot be used as the type of `self` without \
|
|
|
|
|
the `arbitrary_self_types_pointers` feature",
|
|
|
|
|
),
|
|
|
|
|
)
|
|
|
|
|
.with_help(fluent::hir_analysis_invalid_receiver_ty_help)
|
|
|
|
|
.emit()
|
|
|
|
|
}
|
|
|
|
|
_ =>
|
|
|
|
|
// Report error; would not have worked with `arbitrary_self_types[_pointers]`.
|
|
|
|
|
{
|
Reject generic self types.
The RFC for arbitrary self types v2 declares that we should reject
"generic" self types. This commit does so.
The definition of "generic" was unclear in the RFC, but has been
explored in
https://github.com/rust-lang/rust/issues/129147
and the conclusion is that "generic" means any `self` type which
is a type parameter defined on the method itself, or references
to such a type.
This approach was chosen because other definitions of "generic"
don't work. Specifically,
* we can't filter out generic type _arguments_, because that would
filter out Rc<Self> and all the other types of smart pointer
we want to support;
* we can't filter out all type params, because Self itself is a
type param, and because existing Rust code depends on other
type params declared on the type (as opposed to the method).
This PR decides to make a new error code for this case, instead of
reusing the existing E0307 error. This makes the code a
bit more complex, but it seems we have an opportunity to provide
specific diagnostics for this case so we should do so.
This PR filters out generic self types whether or not the
'arbitrary self types' feature is enabled. However, it's believed
that it can't have any effect on code which uses stable Rust, since
there are no stable traits which can be used to indicate a valid
generic receiver type, and thus it would have been impossible to
write code which could trigger this new error case.
It is however possible that this could break existing code which
uses either of the unstable `arbitrary_self_types` or
`receiver_trait` features. This breakage is intentional; as
we move arbitrary self types towards stabilization we don't want
to continue to support generic such types.
This PR adds lots of extra tests to arbitrary-self-from-method-substs.
Most of these are ways to trigger a "type mismatch" error which
https://github.com/rust-lang/rust/blob/9b82580c7347f800c2550e6719e4218a60a80b28/compiler/rustc_hir_typeck/src/method/confirm.rs#L519
hopes can be minimized by filtering out generics in this way.
We remove a FIXME from confirm.rs suggesting that we make this change.
It's still possible to cause type mismatch errors, and a subsequent
PR may be able to improve diagnostics in this area, but it's harder
to cause these errors without contrived uses of the turbofish.
This is a part of the arbitrary self types v2 project,
https://github.com/rust-lang/rfcs/pull/3519
https://github.com/rust-lang/rust/issues/44874
r? @wesleywiser
2024-09-02 12:52:39 +00:00
|
|
|
match receiver_validity_err {
|
|
|
|
|
ReceiverValidityError::DoesNotDeref => {
|
|
|
|
|
tcx.dcx().emit_err(errors::InvalidReceiverTy { span, receiver_ty })
|
|
|
|
|
}
|
|
|
|
|
ReceiverValidityError::MethodGenericParamUsed => {
|
|
|
|
|
tcx.dcx().emit_err(errors::InvalidGenericReceiverTy { span, receiver_ty })
|
|
|
|
|
}
|
|
|
|
|
}
|
2024-03-30 19:25:22 +00:00
|
|
|
}
|
|
|
|
|
});
|
Stabilize `Rc`, `Arc` and `Pin` as method receivers
This lets you write methods using `self: Rc<Self>`, `self: Arc<Self>`, `self: Pin<&mut Self>`, `self: Pin<Box<Self>`, and other combinations involving `Pin` and another stdlib receiver type, without needing the `arbitrary_self_types`. Other user-created receiver types can be used, but they still require the feature flag to use.
This is implemented by introducing a new trait, `Receiver`, which the method receiver's type must implement if the `arbitrary_self_types` feature is not enabled. To keep composed receiver types such as `&Arc<Self>` unstable, the receiver type is also required to implement `Deref<Target=Self>` when the feature flag is not enabled.
This lets you use `self: Rc<Self>` and `self: Arc<Self>` in stable Rust, which was not allowed previously. It was agreed that they would be stabilized in #55786. `self: Pin<&Self>` and other pinned receiver types do not require the `arbitrary_self_types` feature, but they cannot be used on stable because `Pin` still requires the `pin` feature.
2018-11-20 11:50:50 -05:00
|
|
|
}
|
2023-10-30 15:54:08 +00:00
|
|
|
Ok(())
|
Stabilize `Rc`, `Arc` and `Pin` as method receivers
This lets you write methods using `self: Rc<Self>`, `self: Arc<Self>`, `self: Pin<&mut Self>`, `self: Pin<Box<Self>`, and other combinations involving `Pin` and another stdlib receiver type, without needing the `arbitrary_self_types`. Other user-created receiver types can be used, but they still require the feature flag to use.
This is implemented by introducing a new trait, `Receiver`, which the method receiver's type must implement if the `arbitrary_self_types` feature is not enabled. To keep composed receiver types such as `&Arc<Self>` unstable, the receiver type is also required to implement `Deref<Target=Self>` when the feature flag is not enabled.
This lets you use `self: Rc<Self>` and `self: Arc<Self>` in stable Rust, which was not allowed previously. It was agreed that they would be stabilized in #55786. `self: Pin<&Self>` and other pinned receiver types do not require the `arbitrary_self_types` feature, but they cannot be used on stable because `Pin` still requires the `pin` feature.
2018-11-20 11:50:50 -05:00
|
|
|
}
|
2017-11-09 16:15:35 -05:00
|
|
|
|
Reject generic self types.
The RFC for arbitrary self types v2 declares that we should reject
"generic" self types. This commit does so.
The definition of "generic" was unclear in the RFC, but has been
explored in
https://github.com/rust-lang/rust/issues/129147
and the conclusion is that "generic" means any `self` type which
is a type parameter defined on the method itself, or references
to such a type.
This approach was chosen because other definitions of "generic"
don't work. Specifically,
* we can't filter out generic type _arguments_, because that would
filter out Rc<Self> and all the other types of smart pointer
we want to support;
* we can't filter out all type params, because Self itself is a
type param, and because existing Rust code depends on other
type params declared on the type (as opposed to the method).
This PR decides to make a new error code for this case, instead of
reusing the existing E0307 error. This makes the code a
bit more complex, but it seems we have an opportunity to provide
specific diagnostics for this case so we should do so.
This PR filters out generic self types whether or not the
'arbitrary self types' feature is enabled. However, it's believed
that it can't have any effect on code which uses stable Rust, since
there are no stable traits which can be used to indicate a valid
generic receiver type, and thus it would have been impossible to
write code which could trigger this new error case.
It is however possible that this could break existing code which
uses either of the unstable `arbitrary_self_types` or
`receiver_trait` features. This breakage is intentional; as
we move arbitrary self types towards stabilization we don't want
to continue to support generic such types.
This PR adds lots of extra tests to arbitrary-self-from-method-substs.
Most of these are ways to trigger a "type mismatch" error which
https://github.com/rust-lang/rust/blob/9b82580c7347f800c2550e6719e4218a60a80b28/compiler/rustc_hir_typeck/src/method/confirm.rs#L519
hopes can be minimized by filtering out generics in this way.
We remove a FIXME from confirm.rs suggesting that we make this change.
It's still possible to cause type mismatch errors, and a subsequent
PR may be able to improve diagnostics in this area, but it's harder
to cause these errors without contrived uses of the turbofish.
This is a part of the arbitrary self types v2 project,
https://github.com/rust-lang/rfcs/pull/3519
https://github.com/rust-lang/rust/issues/44874
r? @wesleywiser
2024-09-02 12:52:39 +00:00
|
|
|
/// Error cases which may be returned from `receiver_is_valid`. These error
|
|
|
|
|
/// cases are generated in this function as they may be unearthed as we explore
|
|
|
|
|
/// the `autoderef` chain, but they're converted to diagnostics in the caller.
|
|
|
|
|
enum ReceiverValidityError {
|
|
|
|
|
/// The self type does not get to the receiver type by following the
|
|
|
|
|
/// autoderef chain.
|
|
|
|
|
DoesNotDeref,
|
|
|
|
|
/// A type was found which is a method type parameter, and that's not allowed.
|
|
|
|
|
MethodGenericParamUsed,
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// Confirms that a type is not a type parameter referring to one of the
|
|
|
|
|
/// method's type params.
|
|
|
|
|
fn confirm_type_is_not_a_method_generic_param(
|
|
|
|
|
ty: Ty<'_>,
|
2024-10-24 16:25:02 +00:00
|
|
|
method_generics: &ty::Generics,
|
Reject generic self types.
The RFC for arbitrary self types v2 declares that we should reject
"generic" self types. This commit does so.
The definition of "generic" was unclear in the RFC, but has been
explored in
https://github.com/rust-lang/rust/issues/129147
and the conclusion is that "generic" means any `self` type which
is a type parameter defined on the method itself, or references
to such a type.
This approach was chosen because other definitions of "generic"
don't work. Specifically,
* we can't filter out generic type _arguments_, because that would
filter out Rc<Self> and all the other types of smart pointer
we want to support;
* we can't filter out all type params, because Self itself is a
type param, and because existing Rust code depends on other
type params declared on the type (as opposed to the method).
This PR decides to make a new error code for this case, instead of
reusing the existing E0307 error. This makes the code a
bit more complex, but it seems we have an opportunity to provide
specific diagnostics for this case so we should do so.
This PR filters out generic self types whether or not the
'arbitrary self types' feature is enabled. However, it's believed
that it can't have any effect on code which uses stable Rust, since
there are no stable traits which can be used to indicate a valid
generic receiver type, and thus it would have been impossible to
write code which could trigger this new error case.
It is however possible that this could break existing code which
uses either of the unstable `arbitrary_self_types` or
`receiver_trait` features. This breakage is intentional; as
we move arbitrary self types towards stabilization we don't want
to continue to support generic such types.
This PR adds lots of extra tests to arbitrary-self-from-method-substs.
Most of these are ways to trigger a "type mismatch" error which
https://github.com/rust-lang/rust/blob/9b82580c7347f800c2550e6719e4218a60a80b28/compiler/rustc_hir_typeck/src/method/confirm.rs#L519
hopes can be minimized by filtering out generics in this way.
We remove a FIXME from confirm.rs suggesting that we make this change.
It's still possible to cause type mismatch errors, and a subsequent
PR may be able to improve diagnostics in this area, but it's harder
to cause these errors without contrived uses of the turbofish.
This is a part of the arbitrary self types v2 project,
https://github.com/rust-lang/rfcs/pull/3519
https://github.com/rust-lang/rust/issues/44874
r? @wesleywiser
2024-09-02 12:52:39 +00:00
|
|
|
) -> Result<(), ReceiverValidityError> {
|
|
|
|
|
if let ty::Param(param) = ty.kind() {
|
2024-10-24 16:25:02 +00:00
|
|
|
if (param.index as usize) >= method_generics.parent_count {
|
|
|
|
|
return Err(ReceiverValidityError::MethodGenericParamUsed);
|
Reject generic self types.
The RFC for arbitrary self types v2 declares that we should reject
"generic" self types. This commit does so.
The definition of "generic" was unclear in the RFC, but has been
explored in
https://github.com/rust-lang/rust/issues/129147
and the conclusion is that "generic" means any `self` type which
is a type parameter defined on the method itself, or references
to such a type.
This approach was chosen because other definitions of "generic"
don't work. Specifically,
* we can't filter out generic type _arguments_, because that would
filter out Rc<Self> and all the other types of smart pointer
we want to support;
* we can't filter out all type params, because Self itself is a
type param, and because existing Rust code depends on other
type params declared on the type (as opposed to the method).
This PR decides to make a new error code for this case, instead of
reusing the existing E0307 error. This makes the code a
bit more complex, but it seems we have an opportunity to provide
specific diagnostics for this case so we should do so.
This PR filters out generic self types whether or not the
'arbitrary self types' feature is enabled. However, it's believed
that it can't have any effect on code which uses stable Rust, since
there are no stable traits which can be used to indicate a valid
generic receiver type, and thus it would have been impossible to
write code which could trigger this new error case.
It is however possible that this could break existing code which
uses either of the unstable `arbitrary_self_types` or
`receiver_trait` features. This breakage is intentional; as
we move arbitrary self types towards stabilization we don't want
to continue to support generic such types.
This PR adds lots of extra tests to arbitrary-self-from-method-substs.
Most of these are ways to trigger a "type mismatch" error which
https://github.com/rust-lang/rust/blob/9b82580c7347f800c2550e6719e4218a60a80b28/compiler/rustc_hir_typeck/src/method/confirm.rs#L519
hopes can be minimized by filtering out generics in this way.
We remove a FIXME from confirm.rs suggesting that we make this change.
It's still possible to cause type mismatch errors, and a subsequent
PR may be able to improve diagnostics in this area, but it's harder
to cause these errors without contrived uses of the turbofish.
This is a part of the arbitrary self types v2 project,
https://github.com/rust-lang/rfcs/pull/3519
https://github.com/rust-lang/rust/issues/44874
r? @wesleywiser
2024-09-02 12:52:39 +00:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
Ok(())
|
|
|
|
|
}
|
|
|
|
|
|
2019-02-28 22:43:53 +00:00
|
|
|
/// Returns whether `receiver_ty` would be considered a valid receiver type for `self_ty`. If
|
2018-12-14 01:27:49 -05:00
|
|
|
/// `arbitrary_self_types` is enabled, `receiver_ty` must transitively deref to `self_ty`, possibly
|
2024-03-30 19:25:22 +00:00
|
|
|
/// through a `*const/mut T` raw pointer if `arbitrary_self_types_pointers` is also enabled.
|
|
|
|
|
/// If neither feature is enabled, the requirements are more strict: `receiver_ty` must implement
|
|
|
|
|
/// `Receiver` and directly implement `Deref<Target = self_ty>`.
|
2018-12-14 01:27:49 -05:00
|
|
|
///
|
2019-02-08 14:53:55 +01:00
|
|
|
/// N.B., there are cases this function returns `true` but causes an error to be emitted,
|
2018-12-14 01:27:49 -05:00
|
|
|
/// particularly when `receiver_ty` derefs to a type that is the same as `self_ty` but has the
|
2018-12-16 16:47:37 -05:00
|
|
|
/// wrong lifetime. Be careful of this if you are calling this function speculatively.
|
2022-07-07 15:12:32 +02:00
|
|
|
fn receiver_is_valid<'tcx>(
|
|
|
|
|
wfcx: &WfCheckingCtxt<'_, 'tcx>,
|
Stabilize `Rc`, `Arc` and `Pin` as method receivers
This lets you write methods using `self: Rc<Self>`, `self: Arc<Self>`, `self: Pin<&mut Self>`, `self: Pin<Box<Self>`, and other combinations involving `Pin` and another stdlib receiver type, without needing the `arbitrary_self_types`. Other user-created receiver types can be used, but they still require the feature flag to use.
This is implemented by introducing a new trait, `Receiver`, which the method receiver's type must implement if the `arbitrary_self_types` feature is not enabled. To keep composed receiver types such as `&Arc<Self>` unstable, the receiver type is also required to implement `Deref<Target=Self>` when the feature flag is not enabled.
This lets you use `self: Rc<Self>` and `self: Arc<Self>` in stable Rust, which was not allowed previously. It was agreed that they would be stabilized in #55786. `self: Pin<&Self>` and other pinned receiver types do not require the `arbitrary_self_types` feature, but they cannot be used on stable because `Pin` still requires the `pin` feature.
2018-11-20 11:50:50 -05:00
|
|
|
span: Span,
|
|
|
|
|
receiver_ty: Ty<'tcx>,
|
|
|
|
|
self_ty: Ty<'tcx>,
|
2024-08-30 16:57:05 +00:00
|
|
|
arbitrary_self_types_enabled: Option<ArbitrarySelfTypesLevel>,
|
2024-10-24 16:25:02 +00:00
|
|
|
method_generics: &ty::Generics,
|
Reject generic self types.
The RFC for arbitrary self types v2 declares that we should reject
"generic" self types. This commit does so.
The definition of "generic" was unclear in the RFC, but has been
explored in
https://github.com/rust-lang/rust/issues/129147
and the conclusion is that "generic" means any `self` type which
is a type parameter defined on the method itself, or references
to such a type.
This approach was chosen because other definitions of "generic"
don't work. Specifically,
* we can't filter out generic type _arguments_, because that would
filter out Rc<Self> and all the other types of smart pointer
we want to support;
* we can't filter out all type params, because Self itself is a
type param, and because existing Rust code depends on other
type params declared on the type (as opposed to the method).
This PR decides to make a new error code for this case, instead of
reusing the existing E0307 error. This makes the code a
bit more complex, but it seems we have an opportunity to provide
specific diagnostics for this case so we should do so.
This PR filters out generic self types whether or not the
'arbitrary self types' feature is enabled. However, it's believed
that it can't have any effect on code which uses stable Rust, since
there are no stable traits which can be used to indicate a valid
generic receiver type, and thus it would have been impossible to
write code which could trigger this new error case.
It is however possible that this could break existing code which
uses either of the unstable `arbitrary_self_types` or
`receiver_trait` features. This breakage is intentional; as
we move arbitrary self types towards stabilization we don't want
to continue to support generic such types.
This PR adds lots of extra tests to arbitrary-self-from-method-substs.
Most of these are ways to trigger a "type mismatch" error which
https://github.com/rust-lang/rust/blob/9b82580c7347f800c2550e6719e4218a60a80b28/compiler/rustc_hir_typeck/src/method/confirm.rs#L519
hopes can be minimized by filtering out generics in this way.
We remove a FIXME from confirm.rs suggesting that we make this change.
It's still possible to cause type mismatch errors, and a subsequent
PR may be able to improve diagnostics in this area, but it's harder
to cause these errors without contrived uses of the turbofish.
This is a part of the arbitrary self types v2 project,
https://github.com/rust-lang/rfcs/pull/3519
https://github.com/rust-lang/rust/issues/44874
r? @wesleywiser
2024-09-02 12:52:39 +00:00
|
|
|
) -> Result<(), ReceiverValidityError> {
|
2022-07-07 15:12:32 +02:00
|
|
|
let infcx = wfcx.infcx;
|
|
|
|
|
let tcx = wfcx.tcx();
|
|
|
|
|
let cause =
|
2023-01-15 12:58:46 +01:00
|
|
|
ObligationCause::new(span, wfcx.body_def_id, traits::ObligationCauseCode::MethodReceiver);
|
Stabilize `Rc`, `Arc` and `Pin` as method receivers
This lets you write methods using `self: Rc<Self>`, `self: Arc<Self>`, `self: Pin<&mut Self>`, `self: Pin<Box<Self>`, and other combinations involving `Pin` and another stdlib receiver type, without needing the `arbitrary_self_types`. Other user-created receiver types can be used, but they still require the feature flag to use.
This is implemented by introducing a new trait, `Receiver`, which the method receiver's type must implement if the `arbitrary_self_types` feature is not enabled. To keep composed receiver types such as `&Arc<Self>` unstable, the receiver type is also required to implement `Deref<Target=Self>` when the feature flag is not enabled.
This lets you use `self: Rc<Self>` and `self: Arc<Self>` in stable Rust, which was not allowed previously. It was agreed that they would be stabilized in #55786. `self: Pin<&Self>` and other pinned receiver types do not require the `arbitrary_self_types` feature, but they cannot be used on stable because `Pin` still requires the `pin` feature.
2018-11-20 11:50:50 -05:00
|
|
|
|
2024-07-02 17:19:46 -04:00
|
|
|
// Special case `receiver == self_ty`, which doesn't necessarily require the `Receiver` lang item.
|
|
|
|
|
if let Ok(()) = wfcx.infcx.commit_if_ok(|_| {
|
|
|
|
|
let ocx = ObligationCtxt::new(wfcx.infcx);
|
|
|
|
|
ocx.eq(&cause, wfcx.param_env, self_ty, receiver_ty)?;
|
|
|
|
|
if ocx.select_all_or_error().is_empty() { Ok(()) } else { Err(NoSolution) }
|
|
|
|
|
}) {
|
Reject generic self types.
The RFC for arbitrary self types v2 declares that we should reject
"generic" self types. This commit does so.
The definition of "generic" was unclear in the RFC, but has been
explored in
https://github.com/rust-lang/rust/issues/129147
and the conclusion is that "generic" means any `self` type which
is a type parameter defined on the method itself, or references
to such a type.
This approach was chosen because other definitions of "generic"
don't work. Specifically,
* we can't filter out generic type _arguments_, because that would
filter out Rc<Self> and all the other types of smart pointer
we want to support;
* we can't filter out all type params, because Self itself is a
type param, and because existing Rust code depends on other
type params declared on the type (as opposed to the method).
This PR decides to make a new error code for this case, instead of
reusing the existing E0307 error. This makes the code a
bit more complex, but it seems we have an opportunity to provide
specific diagnostics for this case so we should do so.
This PR filters out generic self types whether or not the
'arbitrary self types' feature is enabled. However, it's believed
that it can't have any effect on code which uses stable Rust, since
there are no stable traits which can be used to indicate a valid
generic receiver type, and thus it would have been impossible to
write code which could trigger this new error case.
It is however possible that this could break existing code which
uses either of the unstable `arbitrary_self_types` or
`receiver_trait` features. This breakage is intentional; as
we move arbitrary self types towards stabilization we don't want
to continue to support generic such types.
This PR adds lots of extra tests to arbitrary-self-from-method-substs.
Most of these are ways to trigger a "type mismatch" error which
https://github.com/rust-lang/rust/blob/9b82580c7347f800c2550e6719e4218a60a80b28/compiler/rustc_hir_typeck/src/method/confirm.rs#L519
hopes can be minimized by filtering out generics in this way.
We remove a FIXME from confirm.rs suggesting that we make this change.
It's still possible to cause type mismatch errors, and a subsequent
PR may be able to improve diagnostics in this area, but it's harder
to cause these errors without contrived uses of the turbofish.
This is a part of the arbitrary self types v2 project,
https://github.com/rust-lang/rfcs/pull/3519
https://github.com/rust-lang/rust/issues/44874
r? @wesleywiser
2024-09-02 12:52:39 +00:00
|
|
|
return Ok(());
|
Stabilize `Rc`, `Arc` and `Pin` as method receivers
This lets you write methods using `self: Rc<Self>`, `self: Arc<Self>`, `self: Pin<&mut Self>`, `self: Pin<Box<Self>`, and other combinations involving `Pin` and another stdlib receiver type, without needing the `arbitrary_self_types`. Other user-created receiver types can be used, but they still require the feature flag to use.
This is implemented by introducing a new trait, `Receiver`, which the method receiver's type must implement if the `arbitrary_self_types` feature is not enabled. To keep composed receiver types such as `&Arc<Self>` unstable, the receiver type is also required to implement `Deref<Target=Self>` when the feature flag is not enabled.
This lets you use `self: Rc<Self>` and `self: Arc<Self>` in stable Rust, which was not allowed previously. It was agreed that they would be stabilized in #55786. `self: Pin<&Self>` and other pinned receiver types do not require the `arbitrary_self_types` feature, but they cannot be used on stable because `Pin` still requires the `pin` feature.
2018-11-20 11:50:50 -05:00
|
|
|
}
|
|
|
|
|
|
2024-10-24 16:25:02 +00:00
|
|
|
confirm_type_is_not_a_method_generic_param(receiver_ty, method_generics)?;
|
Reject generic self types.
The RFC for arbitrary self types v2 declares that we should reject
"generic" self types. This commit does so.
The definition of "generic" was unclear in the RFC, but has been
explored in
https://github.com/rust-lang/rust/issues/129147
and the conclusion is that "generic" means any `self` type which
is a type parameter defined on the method itself, or references
to such a type.
This approach was chosen because other definitions of "generic"
don't work. Specifically,
* we can't filter out generic type _arguments_, because that would
filter out Rc<Self> and all the other types of smart pointer
we want to support;
* we can't filter out all type params, because Self itself is a
type param, and because existing Rust code depends on other
type params declared on the type (as opposed to the method).
This PR decides to make a new error code for this case, instead of
reusing the existing E0307 error. This makes the code a
bit more complex, but it seems we have an opportunity to provide
specific diagnostics for this case so we should do so.
This PR filters out generic self types whether or not the
'arbitrary self types' feature is enabled. However, it's believed
that it can't have any effect on code which uses stable Rust, since
there are no stable traits which can be used to indicate a valid
generic receiver type, and thus it would have been impossible to
write code which could trigger this new error case.
It is however possible that this could break existing code which
uses either of the unstable `arbitrary_self_types` or
`receiver_trait` features. This breakage is intentional; as
we move arbitrary self types towards stabilization we don't want
to continue to support generic such types.
This PR adds lots of extra tests to arbitrary-self-from-method-substs.
Most of these are ways to trigger a "type mismatch" error which
https://github.com/rust-lang/rust/blob/9b82580c7347f800c2550e6719e4218a60a80b28/compiler/rustc_hir_typeck/src/method/confirm.rs#L519
hopes can be minimized by filtering out generics in this way.
We remove a FIXME from confirm.rs suggesting that we make this change.
It's still possible to cause type mismatch errors, and a subsequent
PR may be able to improve diagnostics in this area, but it's harder
to cause these errors without contrived uses of the turbofish.
This is a part of the arbitrary self types v2 project,
https://github.com/rust-lang/rfcs/pull/3519
https://github.com/rust-lang/rust/issues/44874
r? @wesleywiser
2024-09-02 12:52:39 +00:00
|
|
|
|
2023-01-15 12:58:46 +01:00
|
|
|
let mut autoderef = Autoderef::new(infcx, wfcx.param_env, wfcx.body_def_id, span, receiver_ty);
|
Stabilize `Rc`, `Arc` and `Pin` as method receivers
This lets you write methods using `self: Rc<Self>`, `self: Arc<Self>`, `self: Pin<&mut Self>`, `self: Pin<Box<Self>`, and other combinations involving `Pin` and another stdlib receiver type, without needing the `arbitrary_self_types`. Other user-created receiver types can be used, but they still require the feature flag to use.
This is implemented by introducing a new trait, `Receiver`, which the method receiver's type must implement if the `arbitrary_self_types` feature is not enabled. To keep composed receiver types such as `&Arc<Self>` unstable, the receiver type is also required to implement `Deref<Target=Self>` when the feature flag is not enabled.
This lets you use `self: Rc<Self>` and `self: Arc<Self>` in stable Rust, which was not allowed previously. It was agreed that they would be stabilized in #55786. `self: Pin<&Self>` and other pinned receiver types do not require the `arbitrary_self_types` feature, but they cannot be used on stable because `Pin` still requires the `pin` feature.
2018-11-20 11:50:50 -05:00
|
|
|
|
2024-03-30 19:25:22 +00:00
|
|
|
// The `arbitrary_self_types_pointers` feature allows raw pointer receivers like `self: *const Self`.
|
2024-08-30 16:57:05 +00:00
|
|
|
if arbitrary_self_types_enabled == Some(ArbitrarySelfTypesLevel::WithPointers) {
|
Stabilize `Rc`, `Arc` and `Pin` as method receivers
This lets you write methods using `self: Rc<Self>`, `self: Arc<Self>`, `self: Pin<&mut Self>`, `self: Pin<Box<Self>`, and other combinations involving `Pin` and another stdlib receiver type, without needing the `arbitrary_self_types`. Other user-created receiver types can be used, but they still require the feature flag to use.
This is implemented by introducing a new trait, `Receiver`, which the method receiver's type must implement if the `arbitrary_self_types` feature is not enabled. To keep composed receiver types such as `&Arc<Self>` unstable, the receiver type is also required to implement `Deref<Target=Self>` when the feature flag is not enabled.
This lets you use `self: Rc<Self>` and `self: Arc<Self>` in stable Rust, which was not allowed previously. It was agreed that they would be stabilized in #55786. `self: Pin<&Self>` and other pinned receiver types do not require the `arbitrary_self_types` feature, but they cannot be used on stable because `Pin` still requires the `pin` feature.
2018-11-20 11:50:50 -05:00
|
|
|
autoderef = autoderef.include_raw_pointers();
|
|
|
|
|
}
|
|
|
|
|
|
2024-09-11 12:27:08 +00:00
|
|
|
let receiver_trait_def_id = tcx.require_lang_item(LangItem::LegacyReceiver, Some(span));
|
2019-09-09 15:27:33 -07:00
|
|
|
|
2019-02-28 22:43:53 +00:00
|
|
|
// Keep dereferencing `receiver_ty` until we get to `self_ty`.
|
2024-07-02 17:19:46 -04:00
|
|
|
while let Some((potential_self_ty, _)) = autoderef.next() {
|
|
|
|
|
debug!(
|
|
|
|
|
"receiver_is_valid: potential self type `{:?}` to match `{:?}`",
|
|
|
|
|
potential_self_ty, self_ty
|
|
|
|
|
);
|
2018-12-16 16:47:37 -05:00
|
|
|
|
2024-10-24 16:25:02 +00:00
|
|
|
confirm_type_is_not_a_method_generic_param(potential_self_ty, method_generics)?;
|
Reject generic self types.
The RFC for arbitrary self types v2 declares that we should reject
"generic" self types. This commit does so.
The definition of "generic" was unclear in the RFC, but has been
explored in
https://github.com/rust-lang/rust/issues/129147
and the conclusion is that "generic" means any `self` type which
is a type parameter defined on the method itself, or references
to such a type.
This approach was chosen because other definitions of "generic"
don't work. Specifically,
* we can't filter out generic type _arguments_, because that would
filter out Rc<Self> and all the other types of smart pointer
we want to support;
* we can't filter out all type params, because Self itself is a
type param, and because existing Rust code depends on other
type params declared on the type (as opposed to the method).
This PR decides to make a new error code for this case, instead of
reusing the existing E0307 error. This makes the code a
bit more complex, but it seems we have an opportunity to provide
specific diagnostics for this case so we should do so.
This PR filters out generic self types whether or not the
'arbitrary self types' feature is enabled. However, it's believed
that it can't have any effect on code which uses stable Rust, since
there are no stable traits which can be used to indicate a valid
generic receiver type, and thus it would have been impossible to
write code which could trigger this new error case.
It is however possible that this could break existing code which
uses either of the unstable `arbitrary_self_types` or
`receiver_trait` features. This breakage is intentional; as
we move arbitrary self types towards stabilization we don't want
to continue to support generic such types.
This PR adds lots of extra tests to arbitrary-self-from-method-substs.
Most of these are ways to trigger a "type mismatch" error which
https://github.com/rust-lang/rust/blob/9b82580c7347f800c2550e6719e4218a60a80b28/compiler/rustc_hir_typeck/src/method/confirm.rs#L519
hopes can be minimized by filtering out generics in this way.
We remove a FIXME from confirm.rs suggesting that we make this change.
It's still possible to cause type mismatch errors, and a subsequent
PR may be able to improve diagnostics in this area, but it's harder
to cause these errors without contrived uses of the turbofish.
This is a part of the arbitrary self types v2 project,
https://github.com/rust-lang/rfcs/pull/3519
https://github.com/rust-lang/rust/issues/44874
r? @wesleywiser
2024-09-02 12:52:39 +00:00
|
|
|
|
2024-07-02 17:19:46 -04:00
|
|
|
// Check if the self type unifies. If it does, then commit the result
|
|
|
|
|
// since it may have region side-effects.
|
|
|
|
|
if let Ok(()) = wfcx.infcx.commit_if_ok(|_| {
|
|
|
|
|
let ocx = ObligationCtxt::new(wfcx.infcx);
|
|
|
|
|
ocx.eq(&cause, wfcx.param_env, self_ty, potential_self_ty)?;
|
|
|
|
|
if ocx.select_all_or_error().is_empty() { Ok(()) } else { Err(NoSolution) }
|
|
|
|
|
}) {
|
|
|
|
|
wfcx.register_obligations(autoderef.into_obligations());
|
Reject generic self types.
The RFC for arbitrary self types v2 declares that we should reject
"generic" self types. This commit does so.
The definition of "generic" was unclear in the RFC, but has been
explored in
https://github.com/rust-lang/rust/issues/129147
and the conclusion is that "generic" means any `self` type which
is a type parameter defined on the method itself, or references
to such a type.
This approach was chosen because other definitions of "generic"
don't work. Specifically,
* we can't filter out generic type _arguments_, because that would
filter out Rc<Self> and all the other types of smart pointer
we want to support;
* we can't filter out all type params, because Self itself is a
type param, and because existing Rust code depends on other
type params declared on the type (as opposed to the method).
This PR decides to make a new error code for this case, instead of
reusing the existing E0307 error. This makes the code a
bit more complex, but it seems we have an opportunity to provide
specific diagnostics for this case so we should do so.
This PR filters out generic self types whether or not the
'arbitrary self types' feature is enabled. However, it's believed
that it can't have any effect on code which uses stable Rust, since
there are no stable traits which can be used to indicate a valid
generic receiver type, and thus it would have been impossible to
write code which could trigger this new error case.
It is however possible that this could break existing code which
uses either of the unstable `arbitrary_self_types` or
`receiver_trait` features. This breakage is intentional; as
we move arbitrary self types towards stabilization we don't want
to continue to support generic such types.
This PR adds lots of extra tests to arbitrary-self-from-method-substs.
Most of these are ways to trigger a "type mismatch" error which
https://github.com/rust-lang/rust/blob/9b82580c7347f800c2550e6719e4218a60a80b28/compiler/rustc_hir_typeck/src/method/confirm.rs#L519
hopes can be minimized by filtering out generics in this way.
We remove a FIXME from confirm.rs suggesting that we make this change.
It's still possible to cause type mismatch errors, and a subsequent
PR may be able to improve diagnostics in this area, but it's harder
to cause these errors without contrived uses of the turbofish.
This is a part of the arbitrary self types v2 project,
https://github.com/rust-lang/rfcs/pull/3519
https://github.com/rust-lang/rust/issues/44874
r? @wesleywiser
2024-09-02 12:52:39 +00:00
|
|
|
return Ok(());
|
2024-07-02 17:19:46 -04:00
|
|
|
}
|
2018-12-16 16:47:37 -05:00
|
|
|
|
2024-07-02 17:19:46 -04:00
|
|
|
// Without `feature(arbitrary_self_types)`, we require that each step in the
|
|
|
|
|
// deref chain implement `receiver`.
|
2024-08-30 16:57:05 +00:00
|
|
|
if arbitrary_self_types_enabled.is_none() {
|
2024-07-02 17:19:46 -04:00
|
|
|
if !receiver_is_implemented(
|
|
|
|
|
wfcx,
|
|
|
|
|
receiver_trait_def_id,
|
|
|
|
|
cause.clone(),
|
|
|
|
|
potential_self_ty,
|
|
|
|
|
) {
|
|
|
|
|
// We cannot proceed.
|
2019-12-24 17:38:22 -05:00
|
|
|
break;
|
Stabilize `Rc`, `Arc` and `Pin` as method receivers
This lets you write methods using `self: Rc<Self>`, `self: Arc<Self>`, `self: Pin<&mut Self>`, `self: Pin<Box<Self>`, and other combinations involving `Pin` and another stdlib receiver type, without needing the `arbitrary_self_types`. Other user-created receiver types can be used, but they still require the feature flag to use.
This is implemented by introducing a new trait, `Receiver`, which the method receiver's type must implement if the `arbitrary_self_types` feature is not enabled. To keep composed receiver types such as `&Arc<Self>` unstable, the receiver type is also required to implement `Deref<Target=Self>` when the feature flag is not enabled.
This lets you use `self: Rc<Self>` and `self: Arc<Self>` in stable Rust, which was not allowed previously. It was agreed that they would be stabilized in #55786. `self: Pin<&Self>` and other pinned receiver types do not require the `arbitrary_self_types` feature, but they cannot be used on stable because `Pin` still requires the `pin` feature.
2018-11-20 11:50:50 -05:00
|
|
|
}
|
|
|
|
|
|
2024-07-02 17:19:46 -04:00
|
|
|
// Register the bound, in case it has any region side-effects.
|
|
|
|
|
wfcx.register_bound(
|
|
|
|
|
cause.clone(),
|
|
|
|
|
wfcx.param_env,
|
|
|
|
|
potential_self_ty,
|
|
|
|
|
receiver_trait_def_id,
|
|
|
|
|
);
|
|
|
|
|
}
|
2019-09-09 15:27:33 -07:00
|
|
|
}
|
Stabilize `Rc`, `Arc` and `Pin` as method receivers
This lets you write methods using `self: Rc<Self>`, `self: Arc<Self>`, `self: Pin<&mut Self>`, `self: Pin<Box<Self>`, and other combinations involving `Pin` and another stdlib receiver type, without needing the `arbitrary_self_types`. Other user-created receiver types can be used, but they still require the feature flag to use.
This is implemented by introducing a new trait, `Receiver`, which the method receiver's type must implement if the `arbitrary_self_types` feature is not enabled. To keep composed receiver types such as `&Arc<Self>` unstable, the receiver type is also required to implement `Deref<Target=Self>` when the feature flag is not enabled.
This lets you use `self: Rc<Self>` and `self: Arc<Self>` in stable Rust, which was not allowed previously. It was agreed that they would be stabilized in #55786. `self: Pin<&Self>` and other pinned receiver types do not require the `arbitrary_self_types` feature, but they cannot be used on stable because `Pin` still requires the `pin` feature.
2018-11-20 11:50:50 -05:00
|
|
|
|
2024-07-02 17:19:46 -04:00
|
|
|
debug!("receiver_is_valid: type `{:?}` does not deref to `{:?}`", receiver_ty, self_ty);
|
Reject generic self types.
The RFC for arbitrary self types v2 declares that we should reject
"generic" self types. This commit does so.
The definition of "generic" was unclear in the RFC, but has been
explored in
https://github.com/rust-lang/rust/issues/129147
and the conclusion is that "generic" means any `self` type which
is a type parameter defined on the method itself, or references
to such a type.
This approach was chosen because other definitions of "generic"
don't work. Specifically,
* we can't filter out generic type _arguments_, because that would
filter out Rc<Self> and all the other types of smart pointer
we want to support;
* we can't filter out all type params, because Self itself is a
type param, and because existing Rust code depends on other
type params declared on the type (as opposed to the method).
This PR decides to make a new error code for this case, instead of
reusing the existing E0307 error. This makes the code a
bit more complex, but it seems we have an opportunity to provide
specific diagnostics for this case so we should do so.
This PR filters out generic self types whether or not the
'arbitrary self types' feature is enabled. However, it's believed
that it can't have any effect on code which uses stable Rust, since
there are no stable traits which can be used to indicate a valid
generic receiver type, and thus it would have been impossible to
write code which could trigger this new error case.
It is however possible that this could break existing code which
uses either of the unstable `arbitrary_self_types` or
`receiver_trait` features. This breakage is intentional; as
we move arbitrary self types towards stabilization we don't want
to continue to support generic such types.
This PR adds lots of extra tests to arbitrary-self-from-method-substs.
Most of these are ways to trigger a "type mismatch" error which
https://github.com/rust-lang/rust/blob/9b82580c7347f800c2550e6719e4218a60a80b28/compiler/rustc_hir_typeck/src/method/confirm.rs#L519
hopes can be minimized by filtering out generics in this way.
We remove a FIXME from confirm.rs suggesting that we make this change.
It's still possible to cause type mismatch errors, and a subsequent
PR may be able to improve diagnostics in this area, but it's harder
to cause these errors without contrived uses of the turbofish.
This is a part of the arbitrary self types v2 project,
https://github.com/rust-lang/rfcs/pull/3519
https://github.com/rust-lang/rust/issues/44874
r? @wesleywiser
2024-09-02 12:52:39 +00:00
|
|
|
Err(ReceiverValidityError::DoesNotDeref)
|
2019-09-09 15:27:33 -07:00
|
|
|
}
|
|
|
|
|
|
2021-12-13 21:45:08 -04:00
|
|
|
fn receiver_is_implemented<'tcx>(
|
2022-07-07 15:12:32 +02:00
|
|
|
wfcx: &WfCheckingCtxt<'_, 'tcx>,
|
2019-09-09 15:27:33 -07:00
|
|
|
receiver_trait_def_id: DefId,
|
|
|
|
|
cause: ObligationCause<'tcx>,
|
|
|
|
|
receiver_ty: Ty<'tcx>,
|
|
|
|
|
) -> bool {
|
2022-07-07 15:12:32 +02:00
|
|
|
let tcx = wfcx.tcx();
|
2023-04-25 16:45:08 +00:00
|
|
|
let trait_ref = ty::TraitRef::new(tcx, receiver_trait_def_id, [receiver_ty]);
|
Stabilize `Rc`, `Arc` and `Pin` as method receivers
This lets you write methods using `self: Rc<Self>`, `self: Arc<Self>`, `self: Pin<&mut Self>`, `self: Pin<Box<Self>`, and other combinations involving `Pin` and another stdlib receiver type, without needing the `arbitrary_self_types`. Other user-created receiver types can be used, but they still require the feature flag to use.
This is implemented by introducing a new trait, `Receiver`, which the method receiver's type must implement if the `arbitrary_self_types` feature is not enabled. To keep composed receiver types such as `&Arc<Self>` unstable, the receiver type is also required to implement `Deref<Target=Self>` when the feature flag is not enabled.
This lets you use `self: Rc<Self>` and `self: Arc<Self>` in stable Rust, which was not allowed previously. It was agreed that they would be stabilized in #55786. `self: Pin<&Self>` and other pinned receiver types do not require the `arbitrary_self_types` feature, but they cannot be used on stable because `Pin` still requires the `pin` feature.
2018-11-20 11:50:50 -05:00
|
|
|
|
2024-10-20 19:49:11 +00:00
|
|
|
let obligation = Obligation::new(tcx, cause, wfcx.param_env, trait_ref);
|
Stabilize `Rc`, `Arc` and `Pin` as method receivers
This lets you write methods using `self: Rc<Self>`, `self: Arc<Self>`, `self: Pin<&mut Self>`, `self: Pin<Box<Self>`, and other combinations involving `Pin` and another stdlib receiver type, without needing the `arbitrary_self_types`. Other user-created receiver types can be used, but they still require the feature flag to use.
This is implemented by introducing a new trait, `Receiver`, which the method receiver's type must implement if the `arbitrary_self_types` feature is not enabled. To keep composed receiver types such as `&Arc<Self>` unstable, the receiver type is also required to implement `Deref<Target=Self>` when the feature flag is not enabled.
This lets you use `self: Rc<Self>` and `self: Arc<Self>` in stable Rust, which was not allowed previously. It was agreed that they would be stabilized in #55786. `self: Pin<&Self>` and other pinned receiver types do not require the `arbitrary_self_types` feature, but they cannot be used on stable because `Pin` still requires the `pin` feature.
2018-11-20 11:50:50 -05:00
|
|
|
|
2022-07-07 15:12:32 +02:00
|
|
|
if wfcx.infcx.predicate_must_hold_modulo_regions(&obligation) {
|
2019-09-09 15:27:33 -07:00
|
|
|
true
|
|
|
|
|
} else {
|
2019-12-24 17:38:22 -05:00
|
|
|
debug!(
|
|
|
|
|
"receiver_is_implemented: type `{:?}` does not implement `Receiver` trait",
|
|
|
|
|
receiver_ty
|
|
|
|
|
);
|
2019-09-09 15:27:33 -07:00
|
|
|
false
|
Stabilize `Rc`, `Arc` and `Pin` as method receivers
This lets you write methods using `self: Rc<Self>`, `self: Arc<Self>`, `self: Pin<&mut Self>`, `self: Pin<Box<Self>`, and other combinations involving `Pin` and another stdlib receiver type, without needing the `arbitrary_self_types`. Other user-created receiver types can be used, but they still require the feature flag to use.
This is implemented by introducing a new trait, `Receiver`, which the method receiver's type must implement if the `arbitrary_self_types` feature is not enabled. To keep composed receiver types such as `&Arc<Self>` unstable, the receiver type is also required to implement `Deref<Target=Self>` when the feature flag is not enabled.
This lets you use `self: Rc<Self>` and `self: Arc<Self>` in stable Rust, which was not allowed previously. It was agreed that they would be stabilized in #55786. `self: Pin<&Self>` and other pinned receiver types do not require the `arbitrary_self_types` feature, but they cannot be used on stable because `Pin` still requires the `pin` feature.
2018-11-20 11:50:50 -05:00
|
|
|
}
|
2018-03-12 22:18:51 -04:00
|
|
|
}
|
2015-12-27 22:09:33 +02:00
|
|
|
|
2019-06-12 00:11:55 +03:00
|
|
|
fn check_variances_for_type_defn<'tcx>(
|
2019-06-14 00:48:52 +03:00
|
|
|
tcx: TyCtxt<'tcx>,
|
2024-07-17 15:56:16 -04:00
|
|
|
item: &'tcx hir::Item<'tcx>,
|
2023-02-01 14:23:51 +00:00
|
|
|
hir_generics: &hir::Generics<'tcx>,
|
2019-06-12 00:11:55 +03:00
|
|
|
) {
|
2023-08-03 01:03:31 +02:00
|
|
|
match item.kind {
|
|
|
|
|
ItemKind::Enum(..) | ItemKind::Struct(..) | ItemKind::Union(..) => {
|
2024-10-15 14:58:41 -04:00
|
|
|
// Ok
|
2023-08-03 01:03:31 +02:00
|
|
|
}
|
|
|
|
|
ItemKind::TyAlias(..) => {
|
2023-12-15 03:19:46 +00:00
|
|
|
assert!(
|
|
|
|
|
tcx.type_alias_is_lazy(item.owner_id),
|
|
|
|
|
"should not be computing variance of non-weak type alias"
|
|
|
|
|
);
|
2023-06-06 09:37:30 +02:00
|
|
|
}
|
2023-12-15 03:19:46 +00:00
|
|
|
kind => span_bug!(item.span, "cannot compute the variances of {kind:?}"),
|
2018-03-12 22:18:51 -04:00
|
|
|
}
|
2015-08-07 09:39:54 -04:00
|
|
|
|
2022-10-27 14:02:18 +11:00
|
|
|
let ty_predicates = tcx.predicates_of(item.owner_id);
|
2018-03-12 22:18:51 -04:00
|
|
|
assert_eq!(ty_predicates.parent, None);
|
2022-10-27 14:02:18 +11:00
|
|
|
let variances = tcx.variances_of(item.owner_id);
|
2015-08-07 09:39:54 -04:00
|
|
|
|
2019-12-24 17:38:22 -05:00
|
|
|
let mut constrained_parameters: FxHashSet<_> = variances
|
|
|
|
|
.iter()
|
|
|
|
|
.enumerate()
|
|
|
|
|
.filter(|&(_, &variance)| variance != ty::Bivariant)
|
|
|
|
|
.map(|(index, _)| Parameter(index as u32))
|
|
|
|
|
.collect();
|
|
|
|
|
|
|
|
|
|
identify_constrained_generic_params(tcx, ty_predicates, None, &mut constrained_parameters);
|
2015-08-07 09:39:54 -04:00
|
|
|
|
2022-02-25 05:44:33 +00:00
|
|
|
// Lazily calculated because it is only needed in case of an error.
|
2022-06-16 19:41:40 +04:00
|
|
|
let explicitly_bounded_params = LazyCell::new(|| {
|
2023-03-13 19:06:41 +00:00
|
|
|
let icx = crate::collect::ItemCtxt::new(tcx, item.owner_id.def_id);
|
2022-02-25 05:44:33 +00:00
|
|
|
hir_generics
|
|
|
|
|
.predicates
|
|
|
|
|
.iter()
|
2024-11-25 16:38:35 +08:00
|
|
|
.filter_map(|predicate| match predicate.kind {
|
|
|
|
|
hir::WherePredicateKind::BoundPredicate(predicate) => {
|
2024-03-15 03:21:55 +01:00
|
|
|
match icx.lower_ty(predicate.bounded_ty).kind() {
|
2022-02-25 05:44:33 +00:00
|
|
|
ty::Param(data) => Some(Parameter(data.index)),
|
|
|
|
|
_ => None,
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
_ => None,
|
|
|
|
|
})
|
|
|
|
|
.collect::<FxHashSet<_>>()
|
|
|
|
|
});
|
|
|
|
|
|
2023-09-21 17:14:58 -07:00
|
|
|
let ty_generics = tcx.generics_of(item.owner_id);
|
|
|
|
|
|
2018-03-12 22:18:51 -04:00
|
|
|
for (index, _) in variances.iter().enumerate() {
|
2022-02-25 05:44:33 +00:00
|
|
|
let parameter = Parameter(index as u32);
|
|
|
|
|
|
|
|
|
|
if constrained_parameters.contains(¶meter) {
|
2018-03-12 22:18:51 -04:00
|
|
|
continue;
|
2015-08-07 09:39:54 -04:00
|
|
|
}
|
2018-03-12 22:18:51 -04:00
|
|
|
|
2024-05-09 20:56:44 -04:00
|
|
|
let ty_param = &ty_generics.own_params[index];
|
2023-09-22 22:41:01 -07:00
|
|
|
let hir_param = &hir_generics.params[index];
|
2023-09-21 17:14:58 -07:00
|
|
|
|
2023-09-22 22:41:01 -07:00
|
|
|
if ty_param.def_id != hir_param.def_id.into() {
|
2024-02-14 15:17:15 +11:00
|
|
|
// Valid programs always have lifetimes before types in the generic parameter list.
|
2023-09-21 17:14:58 -07:00
|
|
|
// ty_generics are normalized to be in this required order, and variances are built
|
|
|
|
|
// from ty generics, not from hir generics. but we need hir generics to get
|
2024-02-14 15:17:15 +11:00
|
|
|
// a span out.
|
2023-09-21 17:14:58 -07:00
|
|
|
//
|
2024-02-14 15:17:15 +11:00
|
|
|
// If they aren't in the same order, then the user has written invalid code, and already
|
|
|
|
|
// got an error about it (or I'm wrong about this).
|
2023-12-18 22:21:37 +11:00
|
|
|
tcx.dcx().span_delayed_bug(
|
2023-11-30 15:01:11 +11:00
|
|
|
hir_param.span,
|
|
|
|
|
"hir generics and ty generics in different order",
|
|
|
|
|
);
|
2023-09-22 22:41:01 -07:00
|
|
|
continue;
|
2023-09-21 17:14:58 -07:00
|
|
|
}
|
2019-04-17 22:41:30 +01:00
|
|
|
|
2024-10-15 14:58:41 -04:00
|
|
|
// Look for `ErrorGuaranteed` deeply within this type.
|
|
|
|
|
if let ControlFlow::Break(ErrorGuaranteed { .. }) = tcx
|
|
|
|
|
.type_of(item.owner_id)
|
|
|
|
|
.instantiate_identity()
|
|
|
|
|
.visit_with(&mut HasErrorDeep { tcx, seen: Default::default() })
|
|
|
|
|
{
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
|
2023-09-21 17:14:58 -07:00
|
|
|
match hir_param.name {
|
2019-12-24 17:38:22 -05:00
|
|
|
hir::ParamName::Error => {}
|
2022-01-27 09:44:25 +00:00
|
|
|
_ => {
|
2022-02-07 22:58:30 +01:00
|
|
|
let has_explicit_bounds = explicitly_bounded_params.contains(¶meter);
|
2024-07-17 15:56:16 -04:00
|
|
|
report_bivariance(tcx, hir_param, has_explicit_bounds, item);
|
2022-01-27 09:44:25 +00:00
|
|
|
}
|
2018-10-11 15:51:44 -04:00
|
|
|
}
|
2015-08-07 09:39:54 -04:00
|
|
|
}
|
2018-03-12 22:18:51 -04:00
|
|
|
}
|
2015-08-07 09:39:54 -04:00
|
|
|
|
2024-10-15 14:58:41 -04:00
|
|
|
/// Look for `ErrorGuaranteed` deeply within structs' (unsubstituted) fields.
|
|
|
|
|
struct HasErrorDeep<'tcx> {
|
|
|
|
|
tcx: TyCtxt<'tcx>,
|
|
|
|
|
seen: FxHashSet<DefId>,
|
|
|
|
|
}
|
|
|
|
|
impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for HasErrorDeep<'tcx> {
|
|
|
|
|
type Result = ControlFlow<ErrorGuaranteed>;
|
|
|
|
|
|
|
|
|
|
fn visit_ty(&mut self, ty: Ty<'tcx>) -> Self::Result {
|
|
|
|
|
match *ty.kind() {
|
|
|
|
|
ty::Adt(def, _) => {
|
|
|
|
|
if self.seen.insert(def.did()) {
|
|
|
|
|
for field in def.all_fields() {
|
|
|
|
|
self.tcx.type_of(field.did).instantiate_identity().visit_with(self)?;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
ty::Error(guar) => return ControlFlow::Break(guar),
|
|
|
|
|
_ => {}
|
|
|
|
|
}
|
|
|
|
|
ty.super_visit_with(self)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn visit_region(&mut self, r: ty::Region<'tcx>) -> Self::Result {
|
|
|
|
|
if let Err(guar) = r.error_reported() {
|
|
|
|
|
ControlFlow::Break(guar)
|
|
|
|
|
} else {
|
|
|
|
|
ControlFlow::Continue(())
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn visit_const(&mut self, c: ty::Const<'tcx>) -> Self::Result {
|
|
|
|
|
if let Err(guar) = c.error_reported() {
|
|
|
|
|
ControlFlow::Break(guar)
|
|
|
|
|
} else {
|
|
|
|
|
ControlFlow::Continue(())
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2024-07-17 15:56:16 -04:00
|
|
|
fn report_bivariance<'tcx>(
|
|
|
|
|
tcx: TyCtxt<'tcx>,
|
|
|
|
|
param: &'tcx hir::GenericParam<'tcx>,
|
2022-02-25 05:44:33 +00:00
|
|
|
has_explicit_bounds: bool,
|
2024-07-17 15:56:16 -04:00
|
|
|
item: &'tcx hir::Item<'tcx>,
|
2022-01-23 12:34:26 -06:00
|
|
|
) -> ErrorGuaranteed {
|
2024-02-01 15:58:07 +01:00
|
|
|
let param_name = param.name.ident();
|
|
|
|
|
|
2024-07-17 15:56:16 -04:00
|
|
|
let help = match item.kind {
|
2024-02-01 15:58:07 +01:00
|
|
|
ItemKind::Enum(..) | ItemKind::Struct(..) | ItemKind::Union(..) => {
|
|
|
|
|
if let Some(def_id) = tcx.lang_items().phantom_data() {
|
|
|
|
|
errors::UnusedGenericParameterHelp::Adt {
|
|
|
|
|
param_name,
|
|
|
|
|
phantom_data: tcx.def_path_str(def_id),
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
errors::UnusedGenericParameterHelp::AdtNoPhantomData { param_name }
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
ItemKind::TyAlias(..) => errors::UnusedGenericParameterHelp::TyAlias { param_name },
|
|
|
|
|
item_kind => bug!("report_bivariance: unexpected item kind: {item_kind:?}"),
|
2019-09-30 13:35:26 -07:00
|
|
|
};
|
2021-05-01 04:39:50 +00:00
|
|
|
|
2024-07-17 15:56:16 -04:00
|
|
|
let mut usage_spans = vec![];
|
|
|
|
|
intravisit::walk_item(
|
|
|
|
|
&mut CollectUsageSpans { spans: &mut usage_spans, param_def_id: param.def_id.to_def_id() },
|
|
|
|
|
item,
|
|
|
|
|
);
|
2024-02-01 15:58:07 +01:00
|
|
|
|
2024-07-17 18:05:21 -04:00
|
|
|
if !usage_spans.is_empty() {
|
2024-07-19 18:53:40 +02:00
|
|
|
// First, check if the ADT/LTA is (probably) cyclical. We say probably here, since we're
|
|
|
|
|
// not actually looking into substitutions, just walking through fields / the "RHS".
|
|
|
|
|
// We don't recurse into the hidden types of opaques or anything else fancy.
|
2024-07-17 18:05:21 -04:00
|
|
|
let item_def_id = item.owner_id.to_def_id();
|
2024-07-19 18:53:40 +02:00
|
|
|
let is_probably_cyclical =
|
|
|
|
|
IsProbablyCyclical { tcx, item_def_id, seen: Default::default() }
|
|
|
|
|
.visit_def(item_def_id)
|
|
|
|
|
.is_break();
|
|
|
|
|
// If the ADT/LTA is cyclical, then if at least one usage of the type parameter or
|
|
|
|
|
// the `Self` alias is present in the, then it's probably a cyclical struct/ type
|
|
|
|
|
// alias, and we should call those parameter usages recursive rather than just saying
|
|
|
|
|
// they're unused...
|
2024-07-17 18:05:21 -04:00
|
|
|
//
|
|
|
|
|
// We currently report *all* of the parameter usages, since computing the exact
|
|
|
|
|
// subset is very involved, and the fact we're mentioning recursion at all is
|
|
|
|
|
// likely to guide the user in the right direction.
|
|
|
|
|
if is_probably_cyclical {
|
2024-07-19 18:53:40 +02:00
|
|
|
return tcx.dcx().emit_err(errors::RecursiveGenericParameter {
|
2024-07-17 18:05:21 -04:00
|
|
|
spans: usage_spans,
|
|
|
|
|
param_span: param.span,
|
|
|
|
|
param_name,
|
|
|
|
|
param_def_kind: tcx.def_descr(param.def_id.to_def_id()),
|
|
|
|
|
help,
|
|
|
|
|
note: (),
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
let const_param_help =
|
2024-08-21 00:57:58 -04:00
|
|
|
matches!(param.kind, hir::GenericParamKind::Type { .. } if !has_explicit_bounds);
|
2024-07-17 18:05:21 -04:00
|
|
|
|
|
|
|
|
let mut diag = tcx.dcx().create_err(errors::UnusedGenericParameter {
|
|
|
|
|
span: param.span,
|
|
|
|
|
param_name,
|
|
|
|
|
param_def_kind: tcx.def_descr(param.def_id.to_def_id()),
|
|
|
|
|
usage_spans,
|
|
|
|
|
help,
|
|
|
|
|
const_param_help,
|
|
|
|
|
});
|
|
|
|
|
diag.code(E0392);
|
|
|
|
|
diag.emit()
|
|
|
|
|
}
|
|
|
|
|
|
2024-07-19 18:53:40 +02:00
|
|
|
/// Detects cases where an ADT/LTA is trivially cyclical -- we want to detect this so
|
|
|
|
|
/// we only mention that its parameters are used cyclically if the ADT/LTA is truly
|
2024-07-17 18:05:21 -04:00
|
|
|
/// cyclical.
|
|
|
|
|
///
|
|
|
|
|
/// Notably, we don't consider substitutions here, so this may have false positives.
|
|
|
|
|
struct IsProbablyCyclical<'tcx> {
|
|
|
|
|
tcx: TyCtxt<'tcx>,
|
2024-07-19 18:53:40 +02:00
|
|
|
item_def_id: DefId,
|
2024-07-17 18:05:21 -04:00
|
|
|
seen: FxHashSet<DefId>,
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
impl<'tcx> IsProbablyCyclical<'tcx> {
|
2024-07-19 18:53:40 +02:00
|
|
|
fn visit_def(&mut self, def_id: DefId) -> ControlFlow<(), ()> {
|
|
|
|
|
match self.tcx.def_kind(def_id) {
|
|
|
|
|
DefKind::Struct | DefKind::Enum | DefKind::Union => {
|
|
|
|
|
self.tcx.adt_def(def_id).all_fields().try_for_each(|field| {
|
|
|
|
|
self.tcx.type_of(field.did).instantiate_identity().visit_with(self)
|
|
|
|
|
})
|
|
|
|
|
}
|
|
|
|
|
DefKind::TyAlias if self.tcx.type_alias_is_lazy(def_id) => {
|
|
|
|
|
self.tcx.type_of(def_id).instantiate_identity().visit_with(self)
|
|
|
|
|
}
|
|
|
|
|
_ => ControlFlow::Continue(()),
|
2024-07-17 18:05:21 -04:00
|
|
|
}
|
2024-07-17 15:56:16 -04:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2024-07-17 18:05:21 -04:00
|
|
|
impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for IsProbablyCyclical<'tcx> {
|
|
|
|
|
type Result = ControlFlow<(), ()>;
|
|
|
|
|
|
2024-07-19 18:53:40 +02:00
|
|
|
fn visit_ty(&mut self, ty: Ty<'tcx>) -> ControlFlow<(), ()> {
|
|
|
|
|
let def_id = match ty.kind() {
|
|
|
|
|
ty::Adt(adt_def, _) => Some(adt_def.did()),
|
|
|
|
|
ty::Alias(ty::Weak, alias_ty) => Some(alias_ty.def_id),
|
|
|
|
|
_ => None,
|
|
|
|
|
};
|
|
|
|
|
if let Some(def_id) = def_id {
|
|
|
|
|
if def_id == self.item_def_id {
|
2024-07-17 18:05:21 -04:00
|
|
|
return ControlFlow::Break(());
|
|
|
|
|
}
|
2024-07-19 18:53:40 +02:00
|
|
|
if self.seen.insert(def_id) {
|
|
|
|
|
self.visit_def(def_id)?;
|
2024-07-17 18:05:21 -04:00
|
|
|
}
|
|
|
|
|
}
|
2024-07-19 18:53:40 +02:00
|
|
|
ty.super_visit_with(self)
|
2024-07-17 18:05:21 -04:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// Collect usages of the `param_def_id` and `Res::SelfTyAlias` in the HIR.
|
|
|
|
|
///
|
|
|
|
|
/// This is used to report places where the user has used parameters in a
|
|
|
|
|
/// non-variance-constraining way for better bivariance errors.
|
2024-07-17 15:56:16 -04:00
|
|
|
struct CollectUsageSpans<'a> {
|
|
|
|
|
spans: &'a mut Vec<Span>,
|
|
|
|
|
param_def_id: DefId,
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
impl<'tcx> Visitor<'tcx> for CollectUsageSpans<'_> {
|
|
|
|
|
type Result = ();
|
|
|
|
|
|
|
|
|
|
fn visit_generics(&mut self, _g: &'tcx rustc_hir::Generics<'tcx>) -> Self::Result {
|
|
|
|
|
// Skip the generics. We only care about fields, not where clause/param bounds.
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn visit_ty(&mut self, t: &'tcx hir::Ty<'tcx>) -> Self::Result {
|
2024-07-17 16:36:21 -04:00
|
|
|
if let hir::TyKind::Path(hir::QPath::Resolved(None, qpath)) = t.kind {
|
|
|
|
|
if let Res::Def(DefKind::TyParam, def_id) = qpath.res
|
|
|
|
|
&& def_id == self.param_def_id
|
|
|
|
|
{
|
|
|
|
|
self.spans.push(t.span);
|
|
|
|
|
return;
|
|
|
|
|
} else if let Res::SelfTyAlias { .. } = qpath.res {
|
|
|
|
|
self.spans.push(t.span);
|
|
|
|
|
return;
|
|
|
|
|
}
|
2024-07-17 15:56:16 -04:00
|
|
|
}
|
|
|
|
|
intravisit::walk_ty(self, t);
|
|
|
|
|
}
|
2015-08-07 09:39:54 -04:00
|
|
|
}
|
|
|
|
|
|
2022-07-07 15:12:32 +02:00
|
|
|
impl<'tcx> WfCheckingCtxt<'_, 'tcx> {
|
|
|
|
|
/// Feature gates RFC 2056 -- trivial bounds, checking for global bounds that
|
|
|
|
|
/// aren't true.
|
2022-06-26 00:10:07 -04:00
|
|
|
#[instrument(level = "debug", skip(self))]
|
2022-07-07 15:12:32 +02:00
|
|
|
fn check_false_global_bounds(&mut self) {
|
|
|
|
|
let tcx = self.ocx.infcx.tcx;
|
|
|
|
|
let mut span = self.span;
|
|
|
|
|
let empty_env = ty::ParamEnv::empty();
|
|
|
|
|
|
2023-01-15 12:58:46 +01:00
|
|
|
let predicates_with_span = tcx.predicates_of(self.body_def_id).predicates.iter().copied();
|
2022-07-07 15:12:32 +02:00
|
|
|
// Check elaborated bounds.
|
2023-04-06 23:11:19 +00:00
|
|
|
let implied_obligations = traits::elaborate(tcx, predicates_with_span);
|
2022-07-07 15:12:32 +02:00
|
|
|
|
2023-03-26 20:33:54 +00:00
|
|
|
for (pred, obligation_span) in implied_obligations {
|
2022-07-07 15:12:32 +02:00
|
|
|
// We lower empty bounds like `Vec<dyn Copy>:` as
|
|
|
|
|
// `WellFormed(Vec<dyn Copy>)`, which will later get checked by
|
|
|
|
|
// regular WF checking
|
2023-06-22 18:17:13 +00:00
|
|
|
if let ty::ClauseKind::WellFormed(..) = pred.kind().skip_binder() {
|
2022-07-07 15:12:32 +02:00
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
// Match the existing behavior.
|
2023-11-06 15:46:17 +00:00
|
|
|
if pred.is_global() && !pred.has_type_flags(TypeFlags::HAS_BINDER_VARS) {
|
2022-07-07 15:12:32 +02:00
|
|
|
let pred = self.normalize(span, None, pred);
|
2021-11-13 23:56:22 +01:00
|
|
|
|
2022-07-07 15:12:32 +02:00
|
|
|
// only use the span of the predicate clause (#90869)
|
2024-03-14 21:05:06 +03:00
|
|
|
let hir_node = tcx.hir_node_by_def_id(self.body_def_id);
|
|
|
|
|
if let Some(hir::Generics { predicates, .. }) = hir_node.generics() {
|
2022-07-07 15:12:32 +02:00
|
|
|
span = predicates
|
|
|
|
|
.iter()
|
|
|
|
|
// There seems to be no better way to find out which predicate we are in
|
2024-11-25 16:38:35 +08:00
|
|
|
.find(|pred| pred.span.contains(obligation_span))
|
|
|
|
|
.map(|pred| pred.span)
|
2022-07-07 15:12:32 +02:00
|
|
|
.unwrap_or(obligation_span);
|
|
|
|
|
}
|
2021-11-13 23:56:22 +01:00
|
|
|
|
2024-10-20 19:49:11 +00:00
|
|
|
let obligation = Obligation::new(
|
2022-11-09 10:49:28 +00:00
|
|
|
tcx,
|
2024-05-09 20:05:59 -04:00
|
|
|
traits::ObligationCause::new(
|
|
|
|
|
span,
|
|
|
|
|
self.body_def_id,
|
|
|
|
|
ObligationCauseCode::TrivialBound,
|
|
|
|
|
),
|
2022-07-07 15:12:32 +02:00
|
|
|
empty_env,
|
|
|
|
|
pred,
|
|
|
|
|
);
|
|
|
|
|
self.ocx.register_obligation(obligation);
|
|
|
|
|
}
|
2018-05-06 22:50:35 +01:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2023-10-18 08:47:17 +00:00
|
|
|
fn check_mod_type_wf(tcx: TyCtxt<'_>, module: LocalModDefId) -> Result<(), ErrorGuaranteed> {
|
2021-05-10 12:18:55 +02:00
|
|
|
let items = tcx.hir_module_items(module);
|
2024-08-18 14:33:03 +00:00
|
|
|
let mut res = items.par_items(|item| tcx.ensure().check_well_formed(item.owner_id.def_id));
|
|
|
|
|
res =
|
|
|
|
|
res.and(items.par_impl_items(|item| tcx.ensure().check_well_formed(item.owner_id.def_id)));
|
|
|
|
|
res =
|
|
|
|
|
res.and(items.par_trait_items(|item| tcx.ensure().check_well_formed(item.owner_id.def_id)));
|
|
|
|
|
res = res
|
|
|
|
|
.and(items.par_foreign_items(|item| tcx.ensure().check_well_formed(item.owner_id.def_id)));
|
|
|
|
|
res = res.and(items.par_opaques(|item| tcx.ensure().check_well_formed(item)));
|
2023-10-30 15:12:45 +00:00
|
|
|
if module == LocalModDefId::CRATE_DEF_ID {
|
|
|
|
|
super::entry::check_for_entry_fn(tcx);
|
|
|
|
|
}
|
|
|
|
|
res
|
2015-08-07 09:39:54 -04:00
|
|
|
}
|
|
|
|
|
|
2023-11-29 02:41:31 +00:00
|
|
|
fn lint_redundant_lifetimes<'tcx>(
|
|
|
|
|
tcx: TyCtxt<'tcx>,
|
|
|
|
|
owner_id: LocalDefId,
|
|
|
|
|
outlives_env: &OutlivesEnvironment<'tcx>,
|
|
|
|
|
) {
|
|
|
|
|
let def_kind = tcx.def_kind(owner_id);
|
|
|
|
|
match def_kind {
|
|
|
|
|
DefKind::Struct
|
|
|
|
|
| DefKind::Union
|
|
|
|
|
| DefKind::Enum
|
|
|
|
|
| DefKind::Trait
|
|
|
|
|
| DefKind::TraitAlias
|
|
|
|
|
| DefKind::Fn
|
|
|
|
|
| DefKind::Const
|
2023-12-05 16:32:47 +00:00
|
|
|
| DefKind::Impl { of_trait: _ } => {
|
2023-11-29 02:41:31 +00:00
|
|
|
// Proceed
|
|
|
|
|
}
|
|
|
|
|
DefKind::AssocFn | DefKind::AssocTy | DefKind::AssocConst => {
|
|
|
|
|
let parent_def_id = tcx.local_parent(owner_id);
|
|
|
|
|
if matches!(tcx.def_kind(parent_def_id), DefKind::Impl { of_trait: true }) {
|
2023-12-05 16:32:47 +00:00
|
|
|
// Don't check for redundant lifetimes for associated items of trait
|
|
|
|
|
// implementations, since the signature is required to be compatible
|
|
|
|
|
// with the trait, even if the implementation implies some lifetimes
|
|
|
|
|
// are redundant.
|
2023-11-29 02:41:31 +00:00
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
}
|
2023-12-05 16:32:47 +00:00
|
|
|
DefKind::Mod
|
2023-11-29 02:41:31 +00:00
|
|
|
| DefKind::Variant
|
|
|
|
|
| DefKind::TyAlias
|
|
|
|
|
| DefKind::ForeignTy
|
|
|
|
|
| DefKind::TyParam
|
|
|
|
|
| DefKind::ConstParam
|
|
|
|
|
| DefKind::Static { .. }
|
|
|
|
|
| DefKind::Ctor(_, _)
|
|
|
|
|
| DefKind::Macro(_)
|
|
|
|
|
| DefKind::ExternCrate
|
|
|
|
|
| DefKind::Use
|
|
|
|
|
| DefKind::ForeignMod
|
|
|
|
|
| DefKind::AnonConst
|
|
|
|
|
| DefKind::InlineConst
|
|
|
|
|
| DefKind::OpaqueTy
|
|
|
|
|
| DefKind::Field
|
|
|
|
|
| DefKind::LifetimeParam
|
|
|
|
|
| DefKind::GlobalAsm
|
2024-08-01 13:05:17 -04:00
|
|
|
| DefKind::Closure
|
|
|
|
|
| DefKind::SyntheticCoroutineBody => return,
|
2023-11-29 02:41:31 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// The ordering of this lifetime map is a bit subtle.
|
|
|
|
|
//
|
|
|
|
|
// Specifically, we want to find a "candidate" lifetime that precedes a "victim" lifetime,
|
|
|
|
|
// where we can prove that `'candidate = 'victim`.
|
|
|
|
|
//
|
|
|
|
|
// `'static` must come first in this list because we can never replace `'static` with
|
|
|
|
|
// something else, but if we find some lifetime `'a` where `'a = 'static`, we want to
|
|
|
|
|
// suggest replacing `'a` with `'static`.
|
|
|
|
|
let mut lifetimes = vec![tcx.lifetimes.re_static];
|
|
|
|
|
lifetimes.extend(
|
|
|
|
|
ty::GenericArgs::identity_for_item(tcx, owner_id).iter().filter_map(|arg| arg.as_region()),
|
|
|
|
|
);
|
|
|
|
|
// If we are in a function, add its late-bound lifetimes too.
|
|
|
|
|
if matches!(def_kind, DefKind::Fn | DefKind::AssocFn) {
|
|
|
|
|
for var in tcx.fn_sig(owner_id).instantiate_identity().bound_vars() {
|
|
|
|
|
let ty::BoundVariableKind::Region(kind) = var else { continue };
|
|
|
|
|
lifetimes.push(ty::Region::new_late_param(tcx, owner_id.to_def_id(), kind));
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
lifetimes.retain(|candidate| candidate.has_name());
|
|
|
|
|
|
|
|
|
|
// Keep track of lifetimes which have already been replaced with other lifetimes.
|
|
|
|
|
// This makes sure that if `'a = 'b = 'c`, we don't say `'c` should be replaced by
|
|
|
|
|
// both `'a` and `'b`.
|
|
|
|
|
let mut shadowed = FxHashSet::default();
|
|
|
|
|
|
|
|
|
|
for (idx, &candidate) in lifetimes.iter().enumerate() {
|
2024-03-27 16:02:13 -04:00
|
|
|
// Don't suggest removing a lifetime twice. We only need to check this
|
|
|
|
|
// here and not up in the `victim` loop because equality is transitive,
|
|
|
|
|
// so if A = C and B = C, then A must = B, so it'll be shadowed too in
|
|
|
|
|
// A's victim loop.
|
2023-11-29 02:41:31 +00:00
|
|
|
if shadowed.contains(&candidate) {
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
for &victim in &lifetimes[(idx + 1)..] {
|
2024-05-23 23:53:56 +01:00
|
|
|
// All region parameters should have a `DefId` available as:
|
|
|
|
|
// - Late-bound parameters should be of the`BrNamed` variety,
|
|
|
|
|
// since we get these signatures straight from `hir_lowering`.
|
|
|
|
|
// - Early-bound parameters unconditionally have a `DefId` available.
|
|
|
|
|
//
|
|
|
|
|
// Any other regions (ReError/ReStatic/etc.) shouldn't matter, since we
|
2024-03-27 16:02:13 -04:00
|
|
|
// can't really suggest to remove them.
|
2024-05-23 23:53:56 +01:00
|
|
|
let Some(def_id) = victim.opt_param_def_id(tcx, owner_id.to_def_id()) else {
|
2023-11-29 02:41:31 +00:00
|
|
|
continue;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
// Do not rename lifetimes not local to this item since they'll overlap
|
|
|
|
|
// with the lint running on the parent. We still want to consider parent
|
|
|
|
|
// lifetimes which make child lifetimes redundant, otherwise we would
|
|
|
|
|
// have truncated the `identity_for_item` args above.
|
|
|
|
|
if tcx.parent(def_id) != owner_id.to_def_id() {
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
|
2024-03-27 16:02:13 -04:00
|
|
|
// If `candidate <: victim` and `victim <: candidate`, then they're equal.
|
2023-11-29 02:41:31 +00:00
|
|
|
if outlives_env.free_region_map().sub_free_regions(tcx, candidate, victim)
|
|
|
|
|
&& outlives_env.free_region_map().sub_free_regions(tcx, victim, candidate)
|
|
|
|
|
{
|
|
|
|
|
shadowed.insert(victim);
|
2023-12-16 01:58:26 +00:00
|
|
|
tcx.emit_node_span_lint(
|
|
|
|
|
rustc_lint_defs::builtin::REDUNDANT_LIFETIMES,
|
2023-11-29 02:41:31 +00:00
|
|
|
tcx.local_def_id_to_hir_id(def_id.expect_local()),
|
|
|
|
|
tcx.def_span(def_id),
|
|
|
|
|
RedundantLifetimeArgsLint { candidate, victim },
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#[derive(LintDiagnostic)]
|
|
|
|
|
#[diag(hir_analysis_redundant_lifetime_args)]
|
|
|
|
|
#[note]
|
|
|
|
|
struct RedundantLifetimeArgsLint<'tcx> {
|
|
|
|
|
/// The lifetime we have found to be redundant.
|
|
|
|
|
victim: ty::Region<'tcx>,
|
|
|
|
|
// The lifetime we can replace the victim with.
|
|
|
|
|
candidate: ty::Region<'tcx>,
|
|
|
|
|
}
|
|
|
|
|
|
2021-05-10 12:18:55 +02:00
|
|
|
pub fn provide(providers: &mut Providers) {
|
|
|
|
|
*providers = Providers { check_mod_type_wf, check_well_formed, ..*providers };
|
|
|
|
|
}
|