2022-12-27 00:39:36 +00:00
|
|
|
use crate::autoderef::Autoderef;
|
2019-03-29 00:28:07 +00:00
|
|
|
use crate::constrained_generic_params::{identify_constrained_generic_params, Parameter};
|
2022-12-27 00:39:36 +00:00
|
|
|
|
2020-04-27 23:26:11 +05:30
|
|
|
use rustc_ast as ast;
|
2022-10-28 23:32:41 +02:00
|
|
|
use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexSet};
|
2022-07-27 10:09:06 +09:00
|
|
|
use rustc_errors::{pluralize, struct_span_err, Applicability, DiagnosticBuilder, ErrorGuaranteed};
|
2020-03-11 12:49:08 +01:00
|
|
|
use rustc_hir as hir;
|
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;
|
2020-01-05 02:37:57 +01:00
|
|
|
use rustc_hir::ItemKind;
|
2022-07-25 18:31:13 +02:00
|
|
|
use rustc_infer::infer::outlives::env::{OutlivesEnvironment, RegionBoundPairs};
|
2021-10-16 02:29:59 -04:00
|
|
|
use rustc_infer::infer::outlives::obligations::TypeOutlives;
|
2022-06-13 01:11:16 -04:00
|
|
|
use rustc_infer::infer::{self, InferCtxt, TyCtxtInferExt};
|
2022-09-16 16:44:18 -04:00
|
|
|
use rustc_middle::mir::ConstraintCategory;
|
2023-05-15 06:24:45 +02:00
|
|
|
use rustc_middle::query::Providers;
|
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::{
|
2023-06-22 18:17:13 +00:00
|
|
|
self, AdtKind, GenericParamDefKind, ToPredicate, Ty, TyCtxt, TypeFoldable, TypeSuperVisitable,
|
2023-02-22 02:18:40 +00:00
|
|
|
TypeVisitable, TypeVisitableExt, TypeVisitor,
|
2021-10-08 12:09:34 -04:00
|
|
|
};
|
2023-07-11 22:35:29 +01:00
|
|
|
use rustc_middle::ty::{GenericArgKind, GenericArgs};
|
2020-03-11 12:49:08 +01:00
|
|
|
use rustc_session::parse::feature_err;
|
2020-06-13 19:37:25 +01:00
|
|
|
use rustc_span::symbol::{sym, Ident, Symbol};
|
2021-10-16 02:29:59 -04:00
|
|
|
use rustc_span::{Span, DUMMY_SP};
|
2022-07-30 03:41:53 +00:00
|
|
|
use rustc_target::spec::abi::Abi;
|
2022-09-09 15:08:06 -05:00
|
|
|
use rustc_trait_selection::traits::error_reporting::TypeErrCtxtExt;
|
2023-09-28 20:51:48 +00:00
|
|
|
use rustc_trait_selection::traits::misc::{
|
|
|
|
|
type_allowed_to_implement_const_param_ty, ConstParamTyImplementationError,
|
|
|
|
|
};
|
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::{
|
|
|
|
|
self, ObligationCause, ObligationCauseCode, ObligationCtxt, WellFormedLoc,
|
|
|
|
|
};
|
2023-11-06 15:46:17 +00:00
|
|
|
use rustc_type_ir::TypeFlags;
|
2016-06-21 18:08:13 -04:00
|
|
|
|
2022-06-16 19:41:40 +04:00
|
|
|
use std::cell::LazyCell;
|
2022-07-07 15:12:32 +02:00
|
|
|
use std::ops::{ControlFlow, Deref};
|
2020-10-21 14:26:34 +02:00
|
|
|
|
2022-07-07 15:12:32 +02:00
|
|
|
pub(super) struct WfCheckingCtxt<'a, 'tcx> {
|
|
|
|
|
pub(super) ocx: ObligationCtxt<'a, '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> {
|
|
|
|
|
type Target = ObligationCtxt<'a, 'tcx>;
|
|
|
|
|
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),
|
|
|
|
|
);
|
2022-07-07 15:12:32 +02:00
|
|
|
self.ocx.register_obligation(traits::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);
|
|
|
|
|
let infcx = &tcx.infer_ctxt().build();
|
|
|
|
|
let ocx = ObligationCtxt::new(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
|
|
|
|
|
|
|
|
if !tcx.features().trivial_bounds {
|
|
|
|
|
wfcx.check_false_global_bounds()
|
|
|
|
|
}
|
2023-10-30 15:54:08 +00:00
|
|
|
f(&mut wfcx)?;
|
2023-01-08 03:14:27 +00:00
|
|
|
|
2023-10-18 08:47:17 +00:00
|
|
|
let assumed_wf_types = wfcx.ocx.assumed_wf_types_and_report_errors(param_env, body_def_id)?;
|
2023-06-27 23:13:39 +02:00
|
|
|
|
2023-01-15 12:58:46 +01:00
|
|
|
let implied_bounds = infcx.implied_bounds_tys(param_env, body_def_id, assumed_wf_types);
|
2023-01-08 03:14:27 +00:00
|
|
|
|
2022-07-07 15:12:32 +02:00
|
|
|
let errors = wfcx.select_all_or_error();
|
|
|
|
|
if !errors.is_empty() {
|
2023-10-18 08:47:17 +00:00
|
|
|
let err = infcx.err_ctxt().report_fulfillment_errors(errors);
|
|
|
|
|
if tcx.sess.err_count() > 0 {
|
|
|
|
|
return Err(err);
|
|
|
|
|
} else {
|
|
|
|
|
// HACK(oli-obk): tests/ui/specialization/min_specialization/specialize_on_type_error.rs causes an
|
|
|
|
|
// error (delay_span_bug) during normalization, without reporting an error, so we need to act as if
|
|
|
|
|
// no error happened, in order to let our callers continue and report an error later in
|
|
|
|
|
// check_impl_items_against_trait.
|
|
|
|
|
return Ok(());
|
|
|
|
|
}
|
2022-07-07 15:12:32 +02:00
|
|
|
}
|
|
|
|
|
|
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-10-18 08:47:17 +00:00
|
|
|
wfcx.ocx.resolve_regions_and_report_errors(body_def_id, &outlives_env)?;
|
|
|
|
|
infcx.tainted_by_errors().error_reported()
|
2022-07-07 15:12:32 +02:00
|
|
|
}
|
|
|
|
|
|
2023-10-18 08:47:17 +00:00
|
|
|
fn check_well_formed(tcx: TyCtxt<'_>, def_id: hir::OwnerId) -> Result<(), ErrorGuaranteed> {
|
2022-10-25 15:07:56 +00:00
|
|
|
let node = tcx.hir().owner(def_id);
|
2023-10-18 08:47:17 +00:00
|
|
|
let mut res = match node {
|
|
|
|
|
hir::OwnerNode::Crate(_) => bug!("check_well_formed cannot be applied to the crate root"),
|
2022-06-12 00:47:21 +02:00
|
|
|
hir::OwnerNode::Item(item) => check_item(tcx, item),
|
|
|
|
|
hir::OwnerNode::TraitItem(item) => check_trait_item(tcx, item),
|
|
|
|
|
hir::OwnerNode::ImplItem(item) => check_impl_item(tcx, item),
|
|
|
|
|
hir::OwnerNode::ForeignItem(item) => check_foreign_item(tcx, item),
|
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
|
|
|
}
|
|
|
|
|
}
|
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
|
|
|
);
|
2018-03-12 22:18:51 -04:00
|
|
|
|
2019-09-26 17:51:36 +01:00
|
|
|
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_) => {
|
2019-12-24 17:38:22 -05:00
|
|
|
let is_auto = tcx
|
2023-01-10 14:57:22 -07:00
|
|
|
.impl_trait_ref(def_id)
|
2023-05-24 14:19:22 +00:00
|
|
|
.is_some_and(|trait_ref| tcx.trait_is_auto(trait_ref.skip_binder().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);
|
2020-03-02 15:26:00 -08:00
|
|
|
let mut err =
|
|
|
|
|
tcx.sess.struct_span_err(sp, "impls of auto traits cannot be default");
|
2020-11-22 17:46:21 -05:00
|
|
|
err.span_labels(impl_.defaultness_span, "default because of this");
|
2020-03-02 15:26:00 -08:00
|
|
|
err.span_label(sp, "auto trait");
|
2023-10-18 08:47:17 +00:00
|
|
|
res = Err(err.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.
|
2020-11-22 17:46:21 -05:00
|
|
|
match (tcx.impl_polarity(def_id), impl_.polarity) {
|
2020-03-02 15:26:00 -08:00
|
|
|
(ty::ImplPolarity::Positive, _) => {
|
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
|
|
|
}
|
2020-03-02 15:26:00 -08:00
|
|
|
(ty::ImplPolarity::Negative, ast::ImplPolarity::Negative(span)) => {
|
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);
|
2023-10-18 08:47:17 +00:00
|
|
|
res = Err(struct_span_err!(
|
2019-12-24 17:38:22 -05:00
|
|
|
tcx.sess,
|
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
|
|
|
}
|
|
|
|
|
}
|
2020-03-02 15:26:00 -08:00
|
|
|
(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
|
|
|
}
|
2020-03-02 15:26:00 -08:00
|
|
|
_ => unreachable!(),
|
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
|
|
|
}
|
2023-01-09 16:30:40 +00:00
|
|
|
hir::ItemKind::Struct(_, ast_generics) => {
|
2023-10-18 08:47:17 +00:00
|
|
|
let res = check_type_defn(tcx, item, false);
|
2018-03-12 22:18:51 -04:00
|
|
|
check_variances_for_type_defn(tcx, item, ast_generics);
|
2023-10-18 08:47:17 +00:00
|
|
|
res
|
2018-03-12 22:18:51 -04:00
|
|
|
}
|
2023-01-09 16:30:40 +00:00
|
|
|
hir::ItemKind::Union(_, ast_generics) => {
|
2023-10-18 08:47:17 +00:00
|
|
|
let res = check_type_defn(tcx, item, true);
|
2018-03-12 22:18:51 -04:00
|
|
|
check_variances_for_type_defn(tcx, item, ast_generics);
|
2023-10-18 08:47:17 +00:00
|
|
|
res
|
2018-03-12 22:18:51 -04:00
|
|
|
}
|
2023-01-09 16:30:40 +00:00
|
|
|
hir::ItemKind::Enum(_, ast_generics) => {
|
2023-10-18 08:47:17 +00:00
|
|
|
let res = check_type_defn(tcx, item, true);
|
2018-03-12 22:18:51 -04:00
|
|
|
check_variances_for_type_defn(tcx, item, ast_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(()),
|
2023-08-03 01:03:31 +02:00
|
|
|
hir::ItemKind::TyAlias(hir_ty, ast_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);
|
2023-08-03 01:03:31 +02:00
|
|
|
check_variances_for_type_defn(tcx, item, ast_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(()),
|
2015-08-07 09:39:54 -04:00
|
|
|
}
|
2018-03-12 22:18:51 -04:00
|
|
|
}
|
2015-08-07 09:39:54 -04:00
|
|
|
|
2023-10-18 08:47:17 +00:00
|
|
|
fn check_foreign_item(tcx: TyCtxt<'_>, item: &hir::ForeignItem<'_>) -> 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
|
|
|
|
|
|
|
|
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 {
|
|
|
|
|
hir::ForeignItemKind::Fn(decl, ..) => {
|
2022-09-20 14:11:23 +09:00
|
|
|
check_item_fn(tcx, def_id, item.ident, item.span, 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
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2023-10-18 08:47:17 +00:00
|
|
|
fn check_trait_item(
|
|
|
|
|
tcx: TyCtxt<'_>,
|
|
|
|
|
trait_item: &hir::TraitItem<'_>,
|
|
|
|
|
) -> 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
|
|
|
|
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
|
|
|
};
|
2021-09-30 19:38:50 +02:00
|
|
|
check_object_unsafe_self_trait_by_name(tcx, trait_item);
|
2023-10-18 08:47:17 +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.
|
2022-02-11 00:08:17 -08:00
|
|
|
let mut required_bounds_by_item = FxHashMap::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
|
2022-02-11 00:17:22 -08:00
|
|
|
if gat_generics.params.is_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.
|
2023-06-22 18:17:13 +00:00
|
|
|
let mut new_required_bounds: Option<FxHashSet<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)
|
2023-07-11 22:35:29 +01:00
|
|
|
.instantiate_identity_iter_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
|
|
|
|
2022-02-11 00:08:17 -08:00
|
|
|
let mut 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();
|
|
|
|
|
|
|
|
|
|
// We sort so that order is predictable
|
2022-02-11 00:08:17 -08:00
|
|
|
unsatisfied_bounds.sort();
|
2021-12-13 01:10:39 -05:00
|
|
|
|
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 mut err = tcx.sess.struct_span_err(
|
2022-02-11 00:08:17 -08:00
|
|
|
gat_item_hir.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!("missing required bound{} on `{}`", plural, gat_item_hir.ident),
|
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
|
|
|
);
|
|
|
|
|
err.span_suggestion(
|
2022-02-05 15:48:02 +01:00
|
|
|
gat_item_hir.generics.tail_span_for_predicate_suggestion(),
|
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!("add the required where clause{plural}"),
|
2021-12-13 01:10:39 -05:00
|
|
|
suggestion,
|
|
|
|
|
Applicability::MachineApplicable,
|
|
|
|
|
);
|
|
|
|
|
|
2022-02-11 00:08:17 -08:00
|
|
|
let bound =
|
|
|
|
|
if unsatisfied_bounds.len() > 1 { "these bounds are" } else { "this bound is" };
|
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
|
|
|
err.note(format!(
|
2023-07-25 23:17:39 +02:00
|
|
|
"{bound} currently required to ensure that impls have maximum flexibility"
|
2021-12-13 10:06:57 -05:00
|
|
|
));
|
2021-12-13 01:10:39 -05:00
|
|
|
err.note(
|
2021-12-13 10:06:57 -05:00
|
|
|
"we are soliciting feedback, see issue #87479 \
|
2021-12-13 01:10:39 -05:00
|
|
|
<https://github.com/rust-lang/rust/issues/87479> \
|
|
|
|
|
for more information",
|
|
|
|
|
);
|
|
|
|
|
|
2022-01-27 09:44:25 +00:00
|
|
|
err.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>,
|
2023-06-22 18:17:13 +00:00
|
|
|
new_predicates: Option<&FxHashSet<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
|
2023-07-27 15:50:42 +00:00
|
|
|
ty::ParamEnv::new(bounds, param_env.reveal())
|
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,
|
2023-06-22 18:17:13 +00:00
|
|
|
) -> Option<FxHashSet<ty::Clause<'tcx>>> {
|
2022-02-12 14:55:53 -08:00
|
|
|
// The bounds we that we would require from `to_check`
|
2022-02-10 23:36:37 -08:00
|
|
|
let mut bounds = FxHashSet::default();
|
|
|
|
|
|
2022-06-18 04:11:47 +01:00
|
|
|
let (regions, types) = GATSubstCollector::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-10-16 15:39:07 +00: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);
|
2023-11-14 13:13:27 +00:00
|
|
|
let region_param = ty::Region::new_early_param(
|
2023-05-29 17:54:53 +00:00
|
|
|
tcx,
|
2023-11-14 13:13:27 +00:00
|
|
|
ty::EarlyParamRegion {
|
2023-05-29 17:54:53 +00:00
|
|
|
def_id: region_param.def_id,
|
|
|
|
|
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))
|
|
|
|
|
.to_predicate(tcx),
|
|
|
|
|
);
|
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-10-16 15:39:07 +00: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);
|
2023-11-14 13:13:27 +00:00
|
|
|
let region_a_param = ty::Region::new_early_param(
|
2023-05-29 17:54:53 +00:00
|
|
|
tcx,
|
2023-11-14 13:13:27 +00:00
|
|
|
ty::EarlyParamRegion {
|
2023-05-29 17:54:53 +00:00
|
|
|
def_id: region_a_param.def_id,
|
|
|
|
|
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);
|
2023-11-14 13:13:27 +00:00
|
|
|
let region_b_param = ty::Region::new_early_param(
|
2023-05-29 17:54:53 +00:00
|
|
|
tcx,
|
2023-11-14 13:13:27 +00:00
|
|
|
ty::EarlyParamRegion {
|
2023-05-29 17:54:53 +00:00
|
|
|
def_id: region_b_param.def_id,
|
|
|
|
|
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,
|
|
|
|
|
))
|
|
|
|
|
.to_predicate(tcx),
|
|
|
|
|
);
|
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 {
|
2022-01-13 15:07:12 -05:00
|
|
|
resolve_regions_with_wf_tys(tcx, id, param_env, &wf_tys, |infcx, region_bound_pairs| {
|
|
|
|
|
let origin = infer::RelateParamBound(DUMMY_SP, ty, None);
|
2022-06-27 15:48:54 +02:00
|
|
|
let outlives = &mut TypeOutlives::new(infcx, tcx, region_bound_pairs, None, param_env);
|
2022-09-16 16:44:18 -04:00
|
|
|
outlives.type_must_outlive(origin, ty, region, ConstraintCategory::BoringNoLocation);
|
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 {
|
|
|
|
|
resolve_regions_with_wf_tys(tcx, id, param_env, &wf_tys, |mut infcx, _| {
|
|
|
|
|
use rustc_infer::infer::outlives::obligations::TypeOutlivesDelegate;
|
|
|
|
|
let origin = infer::RelateRegionParamBound(DUMMY_SP);
|
|
|
|
|
// `region_a: region_b` -> `region_b <= region_a`
|
2022-09-16 16:44:18 -04:00
|
|
|
infcx.push_sub_region_constraint(
|
|
|
|
|
origin,
|
|
|
|
|
region_b,
|
|
|
|
|
region_a,
|
|
|
|
|
ConstraintCategory::BoringNoLocation,
|
|
|
|
|
);
|
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
|
|
|
|
|
fn resolve_regions_with_wf_tys<'tcx>(
|
|
|
|
|
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>>,
|
2022-09-09 13:01:06 -05:00
|
|
|
add_constraints: impl for<'a> FnOnce(&'a InferCtxt<'tcx>, &'a RegionBoundPairs<'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.
|
|
|
|
|
let infcx = tcx.infer_ctxt().build();
|
2022-07-29 15:08:50 +08:00
|
|
|
let outlives_environment = OutlivesEnvironment::with_bounds(
|
|
|
|
|
param_env,
|
2022-08-01 10:23:09 +08:00
|
|
|
infcx.implied_bounds_tys(param_env, id, wf_tys.clone()),
|
2022-07-29 15:08:50 +08:00
|
|
|
);
|
2022-06-29 18:04:58 +02:00
|
|
|
let region_bound_pairs = outlives_environment.region_bound_pairs();
|
2021-10-31 23:04:42 -04:00
|
|
|
|
2022-01-13 15:07:12 -05:00
|
|
|
add_constraints(&infcx, region_bound_pairs);
|
2021-10-31 23:04:42 -04:00
|
|
|
|
2022-06-27 17:18:49 +02:00
|
|
|
let errors = infcx.resolve_regions(&outlives_environment);
|
2021-10-31 23:04:42 -04:00
|
|
|
debug!(?errors, "errors");
|
|
|
|
|
|
|
|
|
|
// 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 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`.
|
2021-10-08 12:09:34 -04:00
|
|
|
struct GATSubstCollector<'tcx> {
|
2021-10-07 17:00:39 -04:00
|
|
|
gat: DefId,
|
2022-03-30 15:14:15 -04:00
|
|
|
// Which region appears and which parameter index its substituted for
|
2021-10-07 17:00:39 -04:00
|
|
|
regions: FxHashSet<(ty::Region<'tcx>, usize)>,
|
2022-03-30 15:14:15 -04:00
|
|
|
// Which params appears and which parameter index its substituted for
|
2021-10-16 02:29:59 -04:00
|
|
|
types: FxHashSet<(Ty<'tcx>, usize)>,
|
2021-10-07 17:00:39 -04:00
|
|
|
}
|
|
|
|
|
|
2021-11-05 21:33:14 -04:00
|
|
|
impl<'tcx> GATSubstCollector<'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,
|
|
|
|
|
) -> (FxHashSet<(ty::Region<'tcx>, usize)>, FxHashSet<(Ty<'tcx>, usize)>) {
|
2022-06-18 04:11:47 +01:00
|
|
|
let mut visitor =
|
|
|
|
|
GATSubstCollector { gat, regions: FxHashSet::default(), types: FxHashSet::default() };
|
2021-11-05 21:33:14 -04:00
|
|
|
t.visit_with(&mut visitor);
|
|
|
|
|
(visitor.regions, visitor.types)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2023-02-09 19:38:07 +00:00
|
|
|
impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for GATSubstCollector<'tcx> {
|
2021-10-07 17:00:39 -04:00
|
|
|
type BreakTy = !;
|
|
|
|
|
|
|
|
|
|
fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow<Self::BreakTy> {
|
|
|
|
|
match t.kind() {
|
2022-11-26 21:51:55 +00:00
|
|
|
ty::Alias(ty::Projection, p) if p.def_id == self.gat => {
|
2023-07-11 22:35:29 +01:00
|
|
|
for (idx, subst) in p.args.iter().enumerate() {
|
2021-10-07 17:00:39 -04:00
|
|
|
match subst.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 {
|
2020-01-30 19:35:48 -08: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,
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// Detect when an object unsafe trait is referring to itself in one of its associated items.
|
|
|
|
|
/// When this is done, suggest using `Self` instead.
|
2020-01-25 14:28:23 -08:00
|
|
|
fn check_object_unsafe_self_trait_by_name(tcx: TyCtxt<'_>, item: &hir::TraitItem<'_>) {
|
2021-10-21 19:41:47 +02:00
|
|
|
let (trait_name, trait_def_id) =
|
2022-09-20 14:11:23 +09:00
|
|
|
match tcx.hir().get_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() {
|
2023-01-28 15:07:21 +00:00
|
|
|
if tcx.check_is_object_safe(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();
|
2020-01-25 14:28:23 -08:00
|
|
|
tcx.sess
|
|
|
|
|
.struct_span_err(
|
|
|
|
|
trait_should_be_self,
|
|
|
|
|
"associated item referring to unboxed trait object for its own trait",
|
|
|
|
|
)
|
|
|
|
|
.span_label(trait_name.span, "in this trait")
|
|
|
|
|
.multipart_suggestion(
|
|
|
|
|
"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
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2023-10-18 08:47:17 +00:00
|
|
|
fn check_impl_item(tcx: TyCtxt<'_>, impl_item: &hir::ImplItem<'_>) -> Result<(), ErrorGuaranteed> {
|
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
|
|
|
};
|
2019-10-05 08:21:30 -07:00
|
|
|
|
2023-10-18 08:47:17 +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.
|
|
|
|
|
hir::GenericParamKind::Const { ty: hir_ty, default: _ } => {
|
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
|
|
|
|
2022-04-08 19:10:07 +01:00
|
|
|
if tcx.features().adt_const_params {
|
2023-05-16 19:58:54 +01:00
|
|
|
enter_wf_checking_ctxt(tcx, hir_ty.span, param.def_id, |wfcx| {
|
|
|
|
|
let trait_def_id =
|
|
|
|
|
tcx.require_lang_item(LangItem::ConstParamTy, Some(hir_ty.span));
|
|
|
|
|
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,
|
|
|
|
|
trait_def_id,
|
|
|
|
|
);
|
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(()),
|
|
|
|
|
ty::FnPtr(_) => tcx.sess.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
|
|
|
),
|
|
|
|
|
ty::RawPtr(_) => tcx.sess.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
|
|
|
),
|
|
|
|
|
_ => tcx.sess.struct_span_err(
|
2023-09-28 20:51:48 +00:00
|
|
|
hir_ty.span,
|
|
|
|
|
format!("`{}` is forbidden as the type of a const generic parameter", ty),
|
2023-10-18 08:47:17 +00:00
|
|
|
),
|
2022-04-08 19:10:07 +01:00
|
|
|
};
|
|
|
|
|
|
2023-10-18 08:47:17 +00: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);
|
|
|
|
|
let may_suggest_feature = match type_allowed_to_implement_const_param_ty(
|
|
|
|
|
tcx,
|
|
|
|
|
tcx.param_env(param.def_id),
|
|
|
|
|
ty,
|
|
|
|
|
cause,
|
|
|
|
|
) {
|
|
|
|
|
// Can never implement `ConstParamTy`, don't suggest anything.
|
|
|
|
|
Err(ConstParamTyImplementationError::NotAnAdtOrBuiltinAllowed) => false,
|
|
|
|
|
// 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
|
|
|
|
|
|
|
|
ty_is_local(ty)
|
|
|
|
|
}
|
|
|
|
|
// Implments `ConstParamTy`, suggest adding the feature to enable.
|
|
|
|
|
Ok(..) => true,
|
|
|
|
|
};
|
|
|
|
|
if may_suggest_feature && tcx.sess.is_nightly_build() {
|
|
|
|
|
diag.help(
|
2023-09-28 20:51:48 +00:00
|
|
|
"add `#![feature(adt_const_params)]` to the crate attributes to enable more complex and user defined types",
|
|
|
|
|
);
|
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
|
|
|
|
2022-08-17 12:22:32 +02:00
|
|
|
let self_ty = match item.container {
|
|
|
|
|
ty::TraitContainer => tcx.types.self_param,
|
2023-07-11 22:35:29 +01:00
|
|
|
ty::ImplContainer => 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
|
|
|
);
|
2023-10-30 15:54:08 +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 => {
|
2022-03-13 00:52:25 +01:00
|
|
|
if let ty::AssocItemContainer::TraitContainer = 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
|
|
|
|
2019-12-24 05:12:01 +01:00
|
|
|
fn item_adt_kind(kind: &ItemKind<'_>) -> Option<AdtKind> {
|
|
|
|
|
match kind {
|
|
|
|
|
ItemKind::Struct(..) => Some(AdtKind::Struct),
|
|
|
|
|
ItemKind::Union(..) => Some(AdtKind::Union),
|
|
|
|
|
ItemKind::Enum(..) => Some(AdtKind::Enum),
|
|
|
|
|
_ => None,
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
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, .. } =
|
|
|
|
|
tcx.hir().get_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);
|
2023-04-27 08:34:11 +01:00
|
|
|
if ty.has_infer() {
|
2021-05-07 12:15:38 +02:00
|
|
|
tcx.sess
|
2023-07-25 23:17:39 +02:00
|
|
|
.delay_span_bug(item.span, format!("inference variables in {ty:?}"));
|
2019-12-24 17:38:22 -05:00
|
|
|
// Just treat unresolved type expression as if it needs drop.
|
|
|
|
|
true
|
2019-05-31 10:23:22 +02:00
|
|
|
} else {
|
2022-10-27 14:02:18 +11:00
|
|
|
ty.needs_drop(tcx, tcx.param_env(item.owner_id))
|
2019-05-31 10:23:22 +02:00
|
|
|
}
|
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, .. } =
|
|
|
|
|
tcx.hir().get_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,
|
2018-08-14 12:50:01 +02:00
|
|
|
traits::FieldSized {
|
2019-12-24 05:12:01 +01:00
|
|
|
adt_kind: match item_adt_kind(&item.kind) {
|
2018-08-14 12:50:01 +02:00
|
|
|
Some(i) => i,
|
|
|
|
|
None => bug!(),
|
|
|
|
|
},
|
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 {
|
2020-04-06 00:13:57 +03:00
|
|
|
let cause = traits::ObligationCause::new(
|
2021-05-07 12:15:38 +02:00
|
|
|
tcx.def_span(discr_def_id),
|
2023-01-15 12:58:46 +01:00
|
|
|
wfcx.body_def_id,
|
2020-04-06 00:13:57 +03:00
|
|
|
traits::MiscObligation,
|
|
|
|
|
);
|
2022-07-07 15:12:32 +02:00
|
|
|
wfcx.register_obligation(traits::Obligation::new(
|
2022-11-09 10:49:28 +00:00
|
|
|
tcx,
|
2020-04-06 00:13:57 +03:00
|
|
|
cause,
|
2022-07-07 15:12:32 +02:00
|
|
|
wfcx.param_env,
|
2023-06-16 05:59:42 +00:00
|
|
|
ty::Binder::dummy(ty::PredicateKind::Clause(ty::ClauseKind::ConstEvaluatable(
|
2022-10-30 07:57:23 +00:00
|
|
|
ty::Const::from_anon_const(tcx, discr_def_id.expect_local()),
|
2023-06-15 18:35:52 +00:00
|
|
|
))),
|
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) {
|
2018-09-03 02:17:20 -07:00
|
|
|
struct_span_err!(
|
|
|
|
|
tcx.sess,
|
|
|
|
|
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);
|
2023-07-11 22:35:29 +01:00
|
|
|
let wf_obligations =
|
|
|
|
|
bounds.instantiate_identity_iter_copied().flat_map(|(bound, bound_span)| {
|
|
|
|
|
let normalized_bound = wfcx.normalize(span, None, bound);
|
2023-09-29 11:34:50 +02:00
|
|
|
traits::wf::clause_obligations(
|
2023-07-11 22:35:29 +01:00
|
|
|
wfcx.infcx,
|
|
|
|
|
wfcx.param_env,
|
|
|
|
|
wfcx.body_def_id,
|
2023-09-29 11:34:50 +02:00
|
|
|
normalized_bound,
|
2023-07-11 22:35:29 +01:00
|
|
|
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 => {
|
|
|
|
|
let tail = tcx.struct_tail_erasing_lifetimes(item_ty, wfcx.param_env);
|
|
|
|
|
!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(
|
2023-01-15 12:58:46 +01:00
|
|
|
traits::ObligationCause::new(ty_span, wfcx.body_def_id, traits::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(
|
2023-01-15 12:58:46 +01:00
|
|
|
traits::ObligationCause::new(ty_span, wfcx.body_def_id, traits::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
|
|
|
|
2022-08-31 13:01:10 +00:00
|
|
|
#[instrument(level = "debug", skip(tcx, ast_self_ty, ast_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>,
|
2019-12-01 16:08:58 +01:00
|
|
|
ast_self_ty: &hir::Ty<'_>,
|
|
|
|
|
ast_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| {
|
2023-01-09 16:30:40 +00:00
|
|
|
match ast_trait_ref {
|
|
|
|
|
Some(ast_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();
|
2023-01-12 18:51:09 +00:00
|
|
|
let trait_ref = wfcx.normalize(
|
|
|
|
|
ast_trait_ref.path.span,
|
|
|
|
|
Some(WellFormedLoc::Ty(item.hir_id().expect_owner().def_id)),
|
|
|
|
|
trait_ref,
|
|
|
|
|
);
|
2023-07-29 08:20:25 +00:00
|
|
|
let trait_pred =
|
|
|
|
|
ty::TraitPredicate { trait_ref, polarity: ty::ImplPolarity::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,
|
2023-01-12 20:28:57 +00:00
|
|
|
ast_trait_ref.path.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 {
|
|
|
|
|
if let Some(pred) = obligation.predicate.to_opt_poly_trait_pred()
|
|
|
|
|
&& pred.self_ty().skip_binder() == trait_ref.self_ty()
|
|
|
|
|
{
|
|
|
|
|
obligation.cause.span = ast_self_ty.span;
|
|
|
|
|
}
|
|
|
|
|
}
|
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(
|
2019-12-24 17:38:22 -05:00
|
|
|
ast_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
|
|
|
|
2019-12-24 17:38:22 -05:00
|
|
|
let is_our_default = |def: &ty::GenericParamDef| match def.kind {
|
2020-12-30 15:34:53 +00:00
|
|
|
GenericParamDefKind::Type { has_default, .. }
|
2023-09-11 13:18:36 +00:00
|
|
|
| GenericParamDefKind::Const { has_default, .. } => {
|
2019-12-24 17:38:22 -05:00
|
|
|
has_default && def.index >= generics.parent_count as u32
|
2018-05-11 00:29:38 +01:00
|
|
|
}
|
2020-12-30 15:34:53 +00:00
|
|
|
GenericParamDefKind::Lifetime => unreachable!(),
|
2018-04-14 19:20:51 +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.
|
2018-05-10 23:02:41 +01:00
|
|
|
for param in &generics.params {
|
2021-04-18 15:14:17 +02:00
|
|
|
match param.kind {
|
|
|
|
|
GenericParamDefKind::Type { .. } => {
|
2021-09-30 19:38:50 +02:00
|
|
|
if is_our_default(param) {
|
2023-07-11 22:35:29 +01:00
|
|
|
let ty = tcx.type_of(param.def_id).instantiate_identity();
|
2021-04-18 15:14:17 +02:00
|
|
|
// 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.
|
2023-04-27 07:52:17 +01:00
|
|
|
if !ty.has_param() {
|
2022-08-30 06:19:48 +00:00
|
|
|
wfcx.register_wf_obligation(
|
|
|
|
|
tcx.def_span(param.def_id),
|
|
|
|
|
Some(WellFormedLoc::Ty(param.def_id.expect_local())),
|
|
|
|
|
ty.into(),
|
|
|
|
|
);
|
2021-04-18 15:14:17 +02:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
GenericParamDefKind::Const { .. } => {
|
2021-09-30 19:38:50 +02:00
|
|
|
if is_our_default(param) {
|
2021-07-08 22:57:10 +02:00
|
|
|
// FIXME(const_generics_defaults): This
|
2023-07-11 22:35:29 +01:00
|
|
|
// is incorrect when dealing with unused args, for example
|
2021-07-08 22:57:10 +02:00
|
|
|
// for `struct Foo<const N: usize, const M: usize = { 1 - 2 }>`
|
|
|
|
|
// we should eagerly error.
|
2023-07-11 22:35:29 +01:00
|
|
|
let default_ct = tcx.const_param_default(param.def_id).instantiate_identity();
|
2023-04-27 07:52:17 +01:00
|
|
|
if !default_ct.has_param() {
|
2022-07-07 15:12:32 +02:00
|
|
|
wfcx.register_wf_obligation(
|
2021-07-08 22:57:10 +02:00
|
|
|
tcx.def_span(param.def_id),
|
2022-07-07 15:12:32 +02:00
|
|
|
None,
|
|
|
|
|
default_ct.into(),
|
2021-07-08 22:57:10 +02:00
|
|
|
);
|
|
|
|
|
}
|
2018-05-10 23:02:41 +01:00
|
|
|
}
|
2018-04-14 19:20:51 +01:00
|
|
|
}
|
2021-04-18 15:14:17 +02:00
|
|
|
// Doesn't have defaults.
|
|
|
|
|
GenericParamDefKind::Lifetime => {}
|
2018-04-14 19:20:51 +01:00
|
|
|
}
|
2018-03-12 22:18:51 -04:00
|
|
|
}
|
2018-01-20 13:33:44 -02:00
|
|
|
|
2018-03-12 22:18:51 -04:00
|
|
|
// Check that trait predicates are WF when params are substituted by their defaults.
|
|
|
|
|
// 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
|
|
|
|
|
// with a concrete default is WF with that default substituted.
|
|
|
|
|
// For more examples see tests `defaults-well-formedness.rs` and `type-check-defaults.rs`.
|
|
|
|
|
//
|
|
|
|
|
// First we build the defaulted substitution.
|
2023-07-11 22:35:29 +01:00
|
|
|
let args = GenericArgs::for_item(tcx, def_id.to_def_id(), |param, _| {
|
2018-05-14 18:27:13 +01:00
|
|
|
match param.kind {
|
|
|
|
|
GenericParamDefKind::Lifetime => {
|
|
|
|
|
// All regions are identity.
|
2021-05-07 12:15:38 +02:00
|
|
|
tcx.mk_param_from_def(param)
|
2018-05-14 18:27:13 +01:00
|
|
|
}
|
2019-05-03 14:42:32 +01:00
|
|
|
|
2021-03-01 12:50:09 +01:00
|
|
|
GenericParamDefKind::Type { .. } => {
|
2019-02-28 22:43:53 +00:00
|
|
|
// If the param has a default, ...
|
2018-05-14 18:27:13 +01:00
|
|
|
if is_our_default(param) {
|
2023-07-11 22:35:29 +01:00
|
|
|
let default_ty = tcx.type_of(param.def_id).instantiate_identity();
|
2019-02-28 22:43:53 +00:00
|
|
|
// ... and it's not a dependent default, ...
|
2023-04-27 07:52:17 +01:00
|
|
|
if !default_ty.has_param() {
|
2019-02-28 22:43:53 +00:00
|
|
|
// ... then substitute it with the default.
|
2018-05-15 13:15:49 +01:00
|
|
|
return default_ty.into();
|
2018-05-14 18:27:13 +01:00
|
|
|
}
|
2018-01-21 12:09:06 -02:00
|
|
|
}
|
2020-04-06 19:03:54 -05:00
|
|
|
|
2021-05-07 12:15:38 +02:00
|
|
|
tcx.mk_param_from_def(param)
|
2018-03-12 22:18:51 -04:00
|
|
|
}
|
2021-03-01 12:50:09 +01:00
|
|
|
GenericParamDefKind::Const { .. } => {
|
2021-04-18 15:14:17 +02:00
|
|
|
// If the param has a default, ...
|
2021-03-01 12:50:09 +01:00
|
|
|
if is_our_default(param) {
|
2023-07-11 22:35:29 +01:00
|
|
|
let default_ct = tcx.const_param_default(param.def_id).instantiate_identity();
|
2021-04-18 15:14:17 +02:00
|
|
|
// ... and it's not a dependent default, ...
|
2023-04-27 07:52:17 +01:00
|
|
|
if !default_ct.has_param() {
|
2021-04-18 15:14:17 +02:00
|
|
|
// ... then substitute it with the default.
|
|
|
|
|
return default_ct.into();
|
|
|
|
|
}
|
2021-03-01 12:50:09 +01:00
|
|
|
}
|
2021-04-18 15:14:17 +02:00
|
|
|
|
2021-05-07 12:15:38 +02:00
|
|
|
tcx.mk_param_from_def(param)
|
2021-03-01 12:50:09 +01:00
|
|
|
}
|
2018-05-14 18:27:13 +01:00
|
|
|
}
|
|
|
|
|
});
|
2019-05-03 14:42:32 +01:00
|
|
|
|
2018-03-12 22:18:51 -04:00
|
|
|
// Now we build the substituted 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 {
|
2020-11-14 21:46:39 +01:00
|
|
|
type BreakTy = ();
|
|
|
|
|
|
2020-11-05 17:30:39 +01:00
|
|
|
fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow<Self::BreakTy> {
|
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
|
|
|
|
2020-11-05 17:30:39 +01:00
|
|
|
fn visit_region(&mut self, _: ty::Region<'tcx>) -> ControlFlow<Self::BreakTy> {
|
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
|
|
|
|
2022-02-02 14:24:45 +11:00
|
|
|
fn visit_const(&mut self, c: ty::Const<'tcx>) -> ControlFlow<Self::BreakTy> {
|
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();
|
2023-07-11 22:35:29 +01:00
|
|
|
let substituted_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.
|
2022-10-04 09:43:34 +00:00
|
|
|
if substituted_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
|
2023-01-03 05:01:17 +00:00
|
|
|
} else if predicates.predicates.iter().any(|&(p, _)| p == substituted_pred) {
|
2019-12-24 17:38:22 -05:00
|
|
|
// Avoid duplication of predicates that contain no parameters, for example.
|
|
|
|
|
None
|
|
|
|
|
} else {
|
|
|
|
|
Some((substituted_pred, sp))
|
|
|
|
|
}
|
|
|
|
|
})
|
|
|
|
|
.map(|(pred, sp)| {
|
|
|
|
|
// Convert each of those into an obligation. So if you have
|
|
|
|
|
// something like `struct Foo<T: Copy = String>`, we would
|
|
|
|
|
// take that predicate `T: Copy`, substitute to `String: Copy`
|
|
|
|
|
// (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,
|
2022-04-01 13:38:43 +02:00
|
|
|
traits::ItemObligation(def_id.to_def_id()),
|
|
|
|
|
);
|
2022-11-09 10:49:28 +00:00
|
|
|
traits::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.
|
|
|
|
|
param_idx: idx.try_into().unwrap(),
|
|
|
|
|
}),
|
|
|
|
|
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),
|
|
|
|
|
Some(WellFormedLoc::Param { function: def_id, param_idx: idx.try_into().unwrap() }),
|
|
|
|
|
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
|
|
|
|
2022-07-30 03:41:53 +00:00
|
|
|
if sig.abi == Abi::RustCall {
|
|
|
|
|
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 {
|
2022-07-30 05:37:48 +00:00
|
|
|
tcx.sess.span_err(
|
|
|
|
|
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() {
|
2022-07-30 05:37:48 +00:00
|
|
|
tcx.sess.span_err(
|
|
|
|
|
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
|
|
|
}
|
|
|
|
|
|
2019-12-24 17:38:22 -05:00
|
|
|
const HELP_FOR_SELF_TYPE: &str = "consider changing to `self`, `&self`, `&mut self`, `self: Box<Self>`, \
|
2019-09-02 18:21:58 -07:00
|
|
|
`self: Rc<Self>`, `self: Arc<Self>`, or `self: Pin<P>` (where P is one \
|
|
|
|
|
of the previous types except `Self`)";
|
|
|
|
|
|
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
|
|
|
|
2022-07-07 15:12:32 +02:00
|
|
|
if tcx.features().arbitrary_self_types {
|
|
|
|
|
if !receiver_is_valid(wfcx, span, receiver_ty, self_ty, true) {
|
2019-02-28 22:43:53 +00:00
|
|
|
// Report error; `arbitrary_self_types` was enabled.
|
2023-10-30 15:54:08 +00:00
|
|
|
return Err(e0307(tcx, span, receiver_ty));
|
2017-11-02 07:58:21 -04: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
|
|
|
} else {
|
2022-07-07 15:12:32 +02:00
|
|
|
if !receiver_is_valid(wfcx, span, receiver_ty, self_ty, false) {
|
2023-10-30 15:54:08 +00:00
|
|
|
return Err(if receiver_is_valid(wfcx, span, receiver_ty, self_ty, true) {
|
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(
|
2022-07-07 15:12:32 +02:00
|
|
|
&tcx.sess.parse_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 \
|
2020-01-08 06:39:38 -05: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
|
|
|
)
|
|
|
|
|
.help(HELP_FOR_SELF_TYPE)
|
2023-10-30 15:54:08 +00:00
|
|
|
.emit()
|
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 {
|
2019-02-28 22:43:53 +00:00
|
|
|
// Report error; would not have worked with `arbitrary_self_types`.
|
2023-10-30 15:54:08 +00:00
|
|
|
e0307(tcx, 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
|
|
|
}
|
|
|
|
|
}
|
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
|
|
|
|
2023-10-30 15:54:08 +00:00
|
|
|
fn e0307(tcx: TyCtxt<'_>, span: Span, receiver_ty: Ty<'_>) -> ErrorGuaranteed {
|
2019-11-11 23:34:57 +01:00
|
|
|
struct_span_err!(
|
2022-07-07 15:12:32 +02:00
|
|
|
tcx.sess.diagnostic(),
|
2019-09-02 18:21:58 -07:00
|
|
|
span,
|
2019-11-11 23:34:57 +01:00
|
|
|
E0307,
|
2022-04-15 15:56:32 +09:00
|
|
|
"invalid `self` parameter type: {receiver_ty}"
|
2019-12-24 17:38:22 -05:00
|
|
|
)
|
|
|
|
|
.note("type of `self` must be `Self` or a type that dereferences to it")
|
2019-09-02 18:21:58 -07:00
|
|
|
.help(HELP_FOR_SELF_TYPE)
|
2023-10-30 15:54:08 +00:00
|
|
|
.emit()
|
2019-09-02 18:21:58 -07:00
|
|
|
}
|
|
|
|
|
|
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
|
|
|
|
|
/// through a `*const/mut T` raw pointer. If the feature is not enabled, the requirements are more
|
2019-02-28 22:43:53 +00:00
|
|
|
/// 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>,
|
|
|
|
|
arbitrary_self_types_enabled: bool,
|
|
|
|
|
) -> bool {
|
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
|
|
|
|
2023-02-13 19:28:10 +00:00
|
|
|
let can_eq_self = |ty| infcx.can_eq(wfcx.param_env, self_ty, 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
|
|
|
|
2019-02-28 22:43:53 +00:00
|
|
|
// `self: Self` is always valid.
|
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
|
|
|
if can_eq_self(receiver_ty) {
|
2022-10-27 15:41:50 +00:00
|
|
|
if let Err(err) = wfcx.eq(&cause, wfcx.param_env, self_ty, receiver_ty) {
|
2022-09-09 15:08:06 -05:00
|
|
|
infcx.err_ctxt().report_mismatched_types(&cause, self_ty, receiver_ty, err).emit();
|
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-12-24 17:38:22 -05:00
|
|
|
return true;
|
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-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
|
|
|
|
2019-02-28 22:43:53 +00:00
|
|
|
// The `arbitrary_self_types` feature allows raw pointer receivers like `self: *const Self`.
|
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
|
|
|
if arbitrary_self_types_enabled {
|
|
|
|
|
autoderef = autoderef.include_raw_pointers();
|
|
|
|
|
}
|
|
|
|
|
|
2019-02-28 22:43:53 +00:00
|
|
|
// The first type is `receiver_ty`, which we know its not equal to `self_ty`; skip it.
|
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.next();
|
|
|
|
|
|
2022-11-17 14:39:19 +00:00
|
|
|
let receiver_trait_def_id = tcx.require_lang_item(LangItem::Receiver, 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`.
|
2018-12-16 16:47:37 -05:00
|
|
|
loop {
|
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
|
|
|
if let Some((potential_self_ty, _)) = autoderef.next() {
|
2019-12-24 17:38:22 -05:00
|
|
|
debug!(
|
|
|
|
|
"receiver_is_valid: potential self type `{:?}` to match `{:?}`",
|
|
|
|
|
potential_self_ty, self_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
|
|
|
|
|
|
|
|
if can_eq_self(potential_self_ty) {
|
2022-07-07 15:12:32 +02:00
|
|
|
wfcx.register_obligations(autoderef.into_obligations());
|
2018-12-16 16:47:37 -05:00
|
|
|
|
2022-10-27 15:41:50 +00:00
|
|
|
if let Err(err) = wfcx.eq(&cause, wfcx.param_env, self_ty, potential_self_ty) {
|
2022-09-09 15:08:06 -05:00
|
|
|
infcx
|
|
|
|
|
.err_ctxt()
|
|
|
|
|
.report_mismatched_types(&cause, self_ty, potential_self_ty, err)
|
|
|
|
|
.emit();
|
2018-12-16 16:47:37 -05:00
|
|
|
}
|
|
|
|
|
|
2019-12-24 17:38:22 -05:00
|
|
|
break;
|
2019-09-09 15:27:33 -07:00
|
|
|
} else {
|
|
|
|
|
// Without `feature(arbitrary_self_types)`, we require that each step in the
|
|
|
|
|
// deref chain implement `receiver`
|
|
|
|
|
if !arbitrary_self_types_enabled
|
|
|
|
|
&& !receiver_is_implemented(
|
2022-07-07 15:12:32 +02:00
|
|
|
wfcx,
|
2019-09-09 15:27:33 -07:00
|
|
|
receiver_trait_def_id,
|
|
|
|
|
cause.clone(),
|
|
|
|
|
potential_self_ty,
|
|
|
|
|
)
|
|
|
|
|
{
|
2019-12-24 17:38:22 -05:00
|
|
|
return false;
|
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
|
|
|
}
|
|
|
|
|
} else {
|
2019-12-24 17:38:22 -05:00
|
|
|
debug!("receiver_is_valid: type `{:?}` does not deref to `{:?}`", receiver_ty, self_ty);
|
2022-04-07 08:51:59 +01:00
|
|
|
// If the receiver already has errors reported due to it, consider it valid to avoid
|
2019-11-26 22:19:54 -05:00
|
|
|
// unnecessary errors (#58712).
|
2019-03-04 21:30:07 -08:00
|
|
|
return receiver_ty.references_error();
|
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-12-16 16:47:37 -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
|
|
|
|
2019-02-28 22:43:53 +00:00
|
|
|
// Without `feature(arbitrary_self_types)`, we require that `receiver_ty` implements `Receiver`.
|
2019-09-09 15:27:33 -07:00
|
|
|
if !arbitrary_self_types_enabled
|
2022-07-07 15:12:32 +02:00
|
|
|
&& !receiver_is_implemented(wfcx, receiver_trait_def_id, cause.clone(), receiver_ty)
|
2019-09-09 15:27:33 -07:00
|
|
|
{
|
2019-12-24 17:38:22 -05:00
|
|
|
return false;
|
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
|
|
|
|
2019-09-09 15:27:33 -07:00
|
|
|
true
|
|
|
|
|
}
|
|
|
|
|
|
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
|
|
|
|
2022-11-18 21:29:26 +00:00
|
|
|
let obligation = traits::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>,
|
2019-11-28 19:28:50 +01:00
|
|
|
item: &hir::Item<'tcx>,
|
2019-12-01 16:08:58 +01:00
|
|
|
hir_generics: &hir::Generics<'_>,
|
2019-06-12 00:11:55 +03:00
|
|
|
) {
|
2023-07-11 22:35:29 +01:00
|
|
|
let identity_args = ty::GenericArgs::identity_for_item(tcx, item.owner_id);
|
2023-08-03 01:03:31 +02:00
|
|
|
|
|
|
|
|
match item.kind {
|
|
|
|
|
ItemKind::Enum(..) | ItemKind::Struct(..) | ItemKind::Union(..) => {
|
|
|
|
|
for field in tcx.adt_def(item.owner_id).all_fields() {
|
|
|
|
|
if field.ty(tcx, identity_args).references_error() {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
ItemKind::TyAlias(..) => {
|
2023-09-26 02:15:32 +00:00
|
|
|
if tcx.type_alias_is_lazy(item.owner_id) {
|
|
|
|
|
if tcx.type_of(item.owner_id).skip_binder().references_error() {
|
2023-08-03 01:03:31 +02:00
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
bug!();
|
|
|
|
|
}
|
2023-06-06 09:37:30 +02:00
|
|
|
}
|
2023-08-03 01:03:31 +02:00
|
|
|
_ => bug!(),
|
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()
|
|
|
|
|
.filter_map(|predicate| match predicate {
|
|
|
|
|
hir::WherePredicate::BoundPredicate(predicate) => {
|
|
|
|
|
match icx.to_ty(predicate.bounded_ty).kind() {
|
|
|
|
|
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
|
|
|
|
2023-09-21 17:14:58 -07:00
|
|
|
let ty_param = &ty_generics.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() {
|
2023-09-21 17:14:58 -07:00
|
|
|
// valid programs always have lifetimes before types in the generic parameter list
|
|
|
|
|
// 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
|
|
|
|
|
// a span out
|
|
|
|
|
//
|
|
|
|
|
// 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)
|
|
|
|
|
tcx.sess
|
|
|
|
|
.delay_span_bug(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
|
|
|
|
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);
|
2023-09-21 17:14:58 -07:00
|
|
|
report_bivariance(tcx, hir_param, has_explicit_bounds);
|
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
|
|
|
|
2022-02-25 05:44:33 +00:00
|
|
|
fn report_bivariance(
|
|
|
|
|
tcx: TyCtxt<'_>,
|
|
|
|
|
param: &rustc_hir::GenericParam<'_>,
|
|
|
|
|
has_explicit_bounds: bool,
|
2022-01-23 12:34:26 -06:00
|
|
|
) -> ErrorGuaranteed {
|
2021-05-01 04:39:50 +00:00
|
|
|
let span = param.span;
|
|
|
|
|
let param_name = param.name.ident().name;
|
2018-03-12 22:18:51 -04:00
|
|
|
let mut err = error_392(tcx, span, param_name);
|
|
|
|
|
|
|
|
|
|
let suggested_marker_id = tcx.lang_items().phantom_data();
|
2019-02-28 22:43:53 +00:00
|
|
|
// Help is available only in presence of lang items.
|
2019-09-30 13:35:26 -07:00
|
|
|
let msg = if let Some(def_id) = suggested_marker_id {
|
|
|
|
|
format!(
|
2019-10-03 09:21:15 -04:00
|
|
|
"consider removing `{}`, referring to it in a field, or using a marker such as `{}`",
|
2019-09-30 13:35:26 -07:00
|
|
|
param_name,
|
|
|
|
|
tcx.def_path_str(def_id),
|
|
|
|
|
)
|
|
|
|
|
} else {
|
2022-04-15 15:56:32 +09:00
|
|
|
format!("consider removing `{param_name}` or referring to it in a field")
|
2019-09-30 13:35:26 -07:00
|
|
|
};
|
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
|
|
|
err.help(msg);
|
2021-05-01 04:39:50 +00:00
|
|
|
|
2022-02-25 05:44:33 +00:00
|
|
|
if matches!(param.kind, hir::GenericParamKind::Type { .. }) && !has_explicit_bounds {
|
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
|
|
|
err.help(format!(
|
2023-07-25 23:17:39 +02:00
|
|
|
"if you intended `{param_name}` to be a const parameter, use `const {param_name}: usize` instead"
|
2021-05-01 04:39:50 +00:00
|
|
|
));
|
|
|
|
|
}
|
|
|
|
|
err.emit()
|
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);
|
2023-01-15 12:58:46 +01:00
|
|
|
let hir_node = tcx.hir().find_by_def_id(self.body_def_id);
|
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)
|
2021-11-13 23:56:22 +01:00
|
|
|
|
2022-07-07 15:12:32 +02:00
|
|
|
if let Some(hir::Generics { predicates, .. }) =
|
|
|
|
|
hir_node.and_then(|node| node.generics())
|
|
|
|
|
{
|
|
|
|
|
span = predicates
|
|
|
|
|
.iter()
|
|
|
|
|
// There seems to be no better way to find out which predicate we are in
|
|
|
|
|
.find(|pred| pred.span().contains(obligation_span))
|
|
|
|
|
.map(|pred| pred.span())
|
|
|
|
|
.unwrap_or(obligation_span);
|
|
|
|
|
}
|
2021-11-13 23:56:22 +01:00
|
|
|
|
2022-07-07 15:12:32 +02:00
|
|
|
let obligation = traits::Obligation::new(
|
2022-11-09 10:49:28 +00:00
|
|
|
tcx,
|
2023-01-15 12:58:46 +01:00
|
|
|
traits::ObligationCause::new(span, self.body_def_id, traits::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);
|
2023-10-18 15:53:06 +00:00
|
|
|
let mut res = items.par_items(|item| tcx.ensure().check_well_formed(item.owner_id));
|
|
|
|
|
res = res.and(items.par_impl_items(|item| tcx.ensure().check_well_formed(item.owner_id)));
|
|
|
|
|
res = res.and(items.par_trait_items(|item| tcx.ensure().check_well_formed(item.owner_id)));
|
|
|
|
|
res.and(items.par_foreign_items(|item| tcx.ensure().check_well_formed(item.owner_id)))
|
2015-08-07 09:39:54 -04:00
|
|
|
}
|
|
|
|
|
|
2022-01-27 09:44:25 +00:00
|
|
|
fn error_392(
|
|
|
|
|
tcx: TyCtxt<'_>,
|
|
|
|
|
span: Span,
|
|
|
|
|
param_name: Symbol,
|
2022-01-23 12:34:26 -06:00
|
|
|
) -> DiagnosticBuilder<'_, ErrorGuaranteed> {
|
2022-04-15 15:56:32 +09:00
|
|
|
let mut err = struct_span_err!(tcx.sess, span, E0392, "parameter `{param_name}` is never used");
|
2019-04-17 22:41:30 +01:00
|
|
|
err.span_label(span, "unused parameter");
|
2016-08-15 00:12:42 +03:00
|
|
|
err
|
2015-08-07 09:39:54 -04:00
|
|
|
}
|
2021-05-10 12:18:55 +02:00
|
|
|
|
|
|
|
|
pub fn provide(providers: &mut Providers) {
|
|
|
|
|
*providers = Providers { check_mod_type_wf, check_well_formed, ..*providers };
|
|
|
|
|
}
|