2017-09-19 08:43:15 -04:00
|
|
|
//! "Collection" is the process of determining the type and other external
|
|
|
|
|
//! details of each item in Rust. Collection is specifically concerned
|
2019-02-28 22:43:53 +00:00
|
|
|
//! with *inter-procedural* things -- for example, for a function
|
2017-09-19 08:43:15 -04:00
|
|
|
//! definition, collection will figure out the type and signature of the
|
|
|
|
|
//! function, but it will not visit the *body* of the function in any way,
|
|
|
|
|
//! nor examine type annotations on local variables (that's the job of
|
|
|
|
|
//! type *checking*).
|
|
|
|
|
//!
|
|
|
|
|
//! Collecting is ultimately defined by a bundle of queries that
|
|
|
|
|
//! inquire after various facts about the items in the crate (e.g.,
|
|
|
|
|
//! `type_of`, `generics_of`, `predicates_of`, etc). See the `provide` function
|
|
|
|
|
//! for the full set.
|
|
|
|
|
//!
|
|
|
|
|
//! At present, however, we do run collection across all items in the
|
|
|
|
|
//! crate as a kind of pass. This should eventually be factored away.
|
2015-02-11 10:25:52 -05:00
|
|
|
|
2025-04-07 18:06:21 +00:00
|
|
|
use std::assert_matches::assert_matches;
|
2024-01-10 10:31:06 +00:00
|
|
|
use std::cell::Cell;
|
2021-03-08 15:32:41 -08:00
|
|
|
use std::iter;
|
2023-08-27 21:04:34 +00:00
|
|
|
use std::ops::Bound;
|
2024-07-29 08:13:50 +10:00
|
|
|
|
2024-11-02 19:32:56 -07:00
|
|
|
use rustc_abi::ExternAbi;
|
2024-05-09 18:44:40 +10:00
|
|
|
use rustc_ast::Recovered;
|
2024-02-11 19:50:50 +08:00
|
|
|
use rustc_data_structures::fx::{FxHashSet, FxIndexMap};
|
2023-12-21 10:52:27 +01:00
|
|
|
use rustc_data_structures::unord::UnordMap;
|
2024-07-05 09:16:00 +00:00
|
|
|
use rustc_errors::{
|
|
|
|
|
Applicability, Diag, DiagCtxtHandle, E0228, ErrorGuaranteed, StashKey, struct_span_code_err,
|
|
|
|
|
};
|
2023-10-04 23:08:05 +00:00
|
|
|
use rustc_hir::def::DefKind;
|
2024-02-23 11:45:44 +00:00
|
|
|
use rustc_hir::def_id::{DefId, LocalDefId};
|
2025-06-05 10:52:24 +00:00
|
|
|
use rustc_hir::intravisit::{InferKind, Visitor, VisitorExt, walk_generics};
|
2025-03-02 18:06:06 +09:00
|
|
|
use rustc_hir::{self as hir, GenericParamKind, HirId, Node, PreciseCapturingArgKind};
|
2023-01-22 05:11:24 +00:00
|
|
|
use rustc_infer::infer::{InferCtxt, TyCtxtInferExt};
|
2025-05-26 10:38:02 +00:00
|
|
|
use rustc_infer::traits::{DynCompatibilityViolation, ObligationCause};
|
2023-05-15 06:24:45 +02:00
|
|
|
use rustc_middle::query::Providers;
|
2022-09-29 09:31:46 +00:00
|
|
|
use rustc_middle::ty::util::{Discr, IntTypeExt};
|
2025-04-24 10:49:06 +01:00
|
|
|
use rustc_middle::ty::{
|
|
|
|
|
self, AdtKind, Const, IsSuggestable, Ty, TyCtxt, TypeVisitableExt, TypingMode, fold_regions,
|
|
|
|
|
};
|
2024-05-08 16:40:46 +10:00
|
|
|
use rustc_middle::{bug, span_bug};
|
2024-12-13 10:29:23 +11:00
|
|
|
use rustc_span::{DUMMY_SP, Ident, Span, Symbol, kw, sym};
|
2024-07-08 15:36:57 -04:00
|
|
|
use rustc_trait_selection::error_reporting::traits::suggestions::NextTypeParamName;
|
2022-12-26 17:44:16 -08:00
|
|
|
use rustc_trait_selection::infer::InferCtxtExt;
|
2025-04-24 10:49:06 +01:00
|
|
|
use rustc_trait_selection::traits::{
|
|
|
|
|
FulfillmentError, ObligationCtxt, hir_ty_lowering_dyn_compatibility_violations,
|
|
|
|
|
};
|
2024-08-30 09:02:58 +10:00
|
|
|
use tracing::{debug, instrument};
|
2016-06-21 18:08:13 -04:00
|
|
|
|
2023-10-04 23:08:05 +00:00
|
|
|
use crate::errors;
|
2025-04-24 10:49:06 +01:00
|
|
|
use crate::hir_ty_lowering::{
|
|
|
|
|
FeedConstTy, HirTyLowerer, InherentAssocCandidate, RegionInferReason,
|
|
|
|
|
};
|
2023-10-04 23:08:05 +00:00
|
|
|
|
2024-06-19 13:11:18 +02:00
|
|
|
pub(crate) mod dump;
|
2022-09-29 09:31:46 +00:00
|
|
|
mod generics_of;
|
2020-06-23 18:18:06 +01:00
|
|
|
mod item_bounds;
|
2022-09-29 09:31:46 +00:00
|
|
|
mod predicates_of;
|
2023-02-06 18:38:52 +00:00
|
|
|
mod resolve_bound_vars;
|
2020-01-17 21:15:03 +00:00
|
|
|
mod type_of;
|
|
|
|
|
|
2014-08-27 21:46:52 -04:00
|
|
|
///////////////////////////////////////////////////////////////////////////
|
2012-05-15 19:36:04 -07:00
|
|
|
|
2025-01-29 10:52:24 +11:00
|
|
|
pub(crate) fn provide(providers: &mut Providers) {
|
2023-02-06 18:38:52 +00:00
|
|
|
resolve_bound_vars::provide(providers);
|
2017-02-14 01:11:24 +02:00
|
|
|
*providers = Providers {
|
2020-01-17 21:15:03 +00:00
|
|
|
type_of: type_of::type_of,
|
2023-08-27 22:02:54 +00:00
|
|
|
type_of_opaque: type_of::type_of_opaque,
|
2025-04-01 23:48:41 +02:00
|
|
|
type_of_opaque_hir_typeck: type_of::type_of_opaque_hir_typeck,
|
2023-09-26 02:15:32 +00:00
|
|
|
type_alias_is_lazy: type_of::type_alias_is_lazy,
|
2020-06-23 18:18:06 +01:00
|
|
|
item_bounds: item_bounds::item_bounds,
|
2020-06-24 19:13:44 +01:00
|
|
|
explicit_item_bounds: item_bounds::explicit_item_bounds,
|
2025-01-22 21:07:54 +00:00
|
|
|
item_self_bounds: item_bounds::item_self_bounds,
|
|
|
|
|
explicit_item_self_bounds: item_bounds::explicit_item_self_bounds,
|
|
|
|
|
item_non_self_bounds: item_bounds::item_non_self_bounds,
|
2024-08-06 13:33:32 -04:00
|
|
|
impl_super_outlives: item_bounds::impl_super_outlives,
|
2022-09-29 09:31:46 +00:00
|
|
|
generics_of: generics_of::generics_of,
|
|
|
|
|
predicates_of: predicates_of::predicates_of,
|
|
|
|
|
explicit_predicates_of: predicates_of::explicit_predicates_of,
|
2024-06-27 12:01:49 -04:00
|
|
|
explicit_super_predicates_of: predicates_of::explicit_super_predicates_of,
|
|
|
|
|
explicit_implied_predicates_of: predicates_of::explicit_implied_predicates_of,
|
|
|
|
|
explicit_supertraits_containing_assoc_item:
|
|
|
|
|
predicates_of::explicit_supertraits_containing_assoc_item,
|
2022-09-29 09:31:46 +00:00
|
|
|
trait_explicit_predicates_and_bounds: predicates_of::trait_explicit_predicates_and_bounds,
|
2024-10-20 19:49:11 +00:00
|
|
|
const_conditions: predicates_of::const_conditions,
|
2024-11-19 20:30:58 +00:00
|
|
|
explicit_implied_const_bounds: predicates_of::explicit_implied_const_bounds,
|
2022-09-29 09:31:46 +00:00
|
|
|
type_param_predicates: predicates_of::type_param_predicates,
|
2017-02-14 01:11:24 +02:00
|
|
|
trait_def,
|
|
|
|
|
adt_def,
|
2017-05-13 17:11:52 +03:00
|
|
|
fn_sig,
|
2024-02-10 21:26:48 +00:00
|
|
|
impl_trait_header,
|
2023-10-19 21:46:28 +00:00
|
|
|
coroutine_kind,
|
2024-01-24 22:27:25 +00:00
|
|
|
coroutine_for_closure,
|
2024-10-02 23:16:31 -04:00
|
|
|
opaque_ty_origin,
|
2024-07-12 13:07:16 -04:00
|
|
|
rendered_precise_capturing_args,
|
2024-11-19 05:01:59 +00:00
|
|
|
const_param_default,
|
2025-03-12 11:23:20 +00:00
|
|
|
anon_const_kind,
|
2017-02-14 01:11:24 +02:00
|
|
|
..*providers
|
|
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
|
2015-01-05 04:24:00 -05:00
|
|
|
///////////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
2024-02-11 09:22:52 +01:00
|
|
|
/// Context specific to some particular item. This is what implements [`HirTyLowerer`].
|
2022-08-07 19:11:47 -07:00
|
|
|
///
|
2022-08-07 21:16:47 -07:00
|
|
|
/// # `ItemCtxt` vs `FnCtxt`
|
2022-08-07 19:11:47 -07:00
|
|
|
///
|
2022-08-07 21:16:47 -07:00
|
|
|
/// `ItemCtxt` is primarily used to type-check item signatures and lower them
|
2024-02-11 09:22:52 +01:00
|
|
|
/// from HIR to their [`ty::Ty`] representation, which is exposed using [`HirTyLowerer`].
|
2022-08-07 21:16:47 -07:00
|
|
|
/// It's also used for the bodies of items like structs where the body (the fields)
|
|
|
|
|
/// are just signatures.
|
|
|
|
|
///
|
2022-10-20 23:47:49 +02:00
|
|
|
/// This is in contrast to `FnCtxt`, which is used to type-check bodies of
|
2022-08-07 21:16:47 -07:00
|
|
|
/// functions, closures, and `const`s -- anywhere that expressions and statements show up.
|
|
|
|
|
///
|
|
|
|
|
/// An important thing to note is that `ItemCtxt` does no inference -- it has no [`InferCtxt`] --
|
|
|
|
|
/// while `FnCtxt` does do inference.
|
|
|
|
|
///
|
|
|
|
|
/// [`InferCtxt`]: rustc_infer::infer::InferCtxt
|
|
|
|
|
///
|
|
|
|
|
/// # Trait predicates
|
|
|
|
|
///
|
|
|
|
|
/// `ItemCtxt` has information about the predicates that are defined
|
2015-02-17 20:46:26 -05:00
|
|
|
/// on the trait. Unfortunately, this predicate information is
|
|
|
|
|
/// available in various different forms at various points in the
|
2024-02-11 09:22:52 +01:00
|
|
|
/// process. So we can't just store a pointer to e.g., the HIR or the
|
2015-02-18 10:39:39 -05:00
|
|
|
/// parsed ty form, we have to be more flexible. To this end, the
|
2017-02-02 14:18:13 +02:00
|
|
|
/// `ItemCtxt` is parameterized by a `DefId` that it uses to satisfy
|
2024-02-11 09:22:52 +01:00
|
|
|
/// `probe_ty_param_bounds` requests, drawing the information from
|
|
|
|
|
/// the HIR (`hir::Generics`), recursively.
|
2025-01-29 10:52:24 +11:00
|
|
|
pub(crate) struct ItemCtxt<'tcx> {
|
2019-06-14 00:48:52 +03:00
|
|
|
tcx: TyCtxt<'tcx>,
|
2023-03-13 19:06:41 +00:00
|
|
|
item_def_id: LocalDefId,
|
2024-01-10 10:31:06 +00:00
|
|
|
tainted_by_errors: Cell<Option<ErrorGuaranteed>>,
|
2015-02-16 15:48:31 -05:00
|
|
|
}
|
|
|
|
|
|
2014-08-27 21:46:52 -04:00
|
|
|
///////////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
2019-12-30 11:45:48 -08:00
|
|
|
#[derive(Default)]
|
2025-01-02 19:08:12 +00:00
|
|
|
pub(crate) struct HirPlaceholderCollector {
|
|
|
|
|
pub spans: Vec<Span>,
|
|
|
|
|
// If any of the spans points to a const infer var, then suppress any messages
|
|
|
|
|
// that may try to turn that const infer into a type parameter.
|
|
|
|
|
pub may_contain_const_infer: bool,
|
|
|
|
|
}
|
2019-12-24 13:18:09 -08:00
|
|
|
|
2022-01-05 11:43:21 +01:00
|
|
|
impl<'v> Visitor<'v> for HirPlaceholderCollector {
|
2025-01-11 18:55:32 +00:00
|
|
|
fn visit_infer(&mut self, _inf_id: HirId, inf_span: Span, kind: InferKind<'v>) -> Self::Result {
|
|
|
|
|
self.spans.push(inf_span);
|
|
|
|
|
|
|
|
|
|
if let InferKind::Const(_) | InferKind::Ambig(_) = kind {
|
2025-01-02 19:08:12 +00:00
|
|
|
self.may_contain_const_infer = true;
|
2022-01-05 11:43:21 +01:00
|
|
|
}
|
|
|
|
|
}
|
2019-12-24 13:18:09 -08:00
|
|
|
}
|
|
|
|
|
|
2019-12-30 11:45:48 -08:00
|
|
|
/// If there are any placeholder types (`_`), emit an error explaining that this is not allowed
|
|
|
|
|
/// and suggest adding type parameters in the appropriate place, taking into consideration any and
|
|
|
|
|
/// all already existing generic type parameters to avoid suggesting a name that is already in use.
|
2022-05-20 19:51:09 -04:00
|
|
|
pub(crate) fn placeholder_type_error<'tcx>(
|
2024-07-05 10:05:58 +00:00
|
|
|
cx: &dyn HirTyLowerer<'tcx>,
|
2022-02-07 22:58:30 +01:00
|
|
|
generics: Option<&hir::Generics<'_>>,
|
2019-12-24 13:18:09 -08:00
|
|
|
placeholder_types: Vec<Span>,
|
|
|
|
|
suggest: bool,
|
2021-02-10 15:49:23 +00:00
|
|
|
hir_ty: Option<&hir::Ty<'_>>,
|
2021-06-19 07:01:37 +08:00
|
|
|
kind: &'static str,
|
2019-12-24 13:18:09 -08:00
|
|
|
) {
|
2019-12-26 14:01:45 -08:00
|
|
|
if placeholder_types.is_empty() {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
2024-07-05 10:05:58 +00:00
|
|
|
placeholder_type_error_diag(cx, generics, placeholder_types, vec![], suggest, hir_ty, kind)
|
2022-02-07 22:58:30 +01:00
|
|
|
.emit();
|
2022-03-27 19:43:05 -07:00
|
|
|
}
|
|
|
|
|
|
2024-07-05 10:05:58 +00:00
|
|
|
pub(crate) fn placeholder_type_error_diag<'cx, 'tcx>(
|
|
|
|
|
cx: &'cx dyn HirTyLowerer<'tcx>,
|
2022-02-07 22:58:30 +01:00
|
|
|
generics: Option<&hir::Generics<'_>>,
|
2022-03-27 19:43:05 -07:00
|
|
|
placeholder_types: Vec<Span>,
|
|
|
|
|
additional_spans: Vec<Span>,
|
|
|
|
|
suggest: bool,
|
|
|
|
|
hir_ty: Option<&hir::Ty<'_>>,
|
|
|
|
|
kind: &'static str,
|
2024-07-05 10:05:58 +00:00
|
|
|
) -> Diag<'cx> {
|
2022-03-27 19:43:05 -07:00
|
|
|
if placeholder_types.is_empty() {
|
2024-07-05 10:05:58 +00:00
|
|
|
return bad_placeholder(cx, additional_spans, kind);
|
2022-03-27 19:43:05 -07:00
|
|
|
}
|
|
|
|
|
|
2022-02-07 22:58:30 +01:00
|
|
|
let params = generics.map(|g| g.params).unwrap_or_default();
|
|
|
|
|
let type_name = params.next_type_param_name(None);
|
2019-12-26 14:01:45 -08:00
|
|
|
let mut sugg: Vec<_> =
|
2020-03-05 14:29:58 +01:00
|
|
|
placeholder_types.iter().map(|sp| (*sp, (*type_name).to_string())).collect();
|
2020-07-12 16:40:22 +01:00
|
|
|
|
2022-02-07 22:58:30 +01:00
|
|
|
if let Some(generics) = generics {
|
2024-12-13 12:32:35 +01:00
|
|
|
if let Some(span) = params.iter().find_map(|arg| match arg.name {
|
|
|
|
|
hir::ParamName::Plain(Ident { name: kw::Underscore, span }) => Some(span),
|
|
|
|
|
_ => None,
|
2022-02-07 22:58:30 +01:00
|
|
|
}) {
|
|
|
|
|
// Account for `_` already present in cases like `struct S<_>(_);` and suggest
|
|
|
|
|
// `struct S<T>(T);` instead of `struct S<_, T>(T);`.
|
2024-12-13 12:32:35 +01:00
|
|
|
sugg.push((span, (*type_name).to_string()));
|
2022-02-07 22:58:30 +01:00
|
|
|
} else if let Some(span) = generics.span_for_param_suggestion() {
|
|
|
|
|
// Account for bounds, we want `fn foo<T: E, K>(_: K)` not `fn foo<T, K: E>(_: K)`.
|
2023-07-25 23:17:39 +02:00
|
|
|
sugg.push((span, format!(", {type_name}")));
|
2022-02-07 22:58:30 +01:00
|
|
|
} else {
|
2023-07-25 23:17:39 +02:00
|
|
|
sugg.push((generics.span, format!("<{type_name}>")));
|
2020-07-12 16:40:22 +01:00
|
|
|
}
|
2019-12-26 14:01:45 -08:00
|
|
|
}
|
2020-07-12 16:40:22 +01:00
|
|
|
|
2022-03-27 19:43:05 -07:00
|
|
|
let mut err =
|
2024-07-05 10:05:58 +00:00
|
|
|
bad_placeholder(cx, placeholder_types.into_iter().chain(additional_spans).collect(), kind);
|
2021-02-09 08:42:08 +00:00
|
|
|
|
2021-02-10 15:49:23 +00:00
|
|
|
// Suggest, but only if it is not a function in const or static
|
2019-12-26 14:01:45 -08:00
|
|
|
if suggest {
|
2021-02-10 15:49:23 +00:00
|
|
|
let mut is_fn = false;
|
2021-06-16 18:47:26 +09:00
|
|
|
let mut is_const_or_static = false;
|
2021-02-10 15:49:23 +00:00
|
|
|
|
2022-02-26 07:43:47 -03:00
|
|
|
if let Some(hir_ty) = hir_ty
|
|
|
|
|
&& let hir::TyKind::BareFn(_) = hir_ty.kind
|
|
|
|
|
{
|
|
|
|
|
is_fn = true;
|
|
|
|
|
|
|
|
|
|
// Check if parent is const or static
|
|
|
|
|
is_const_or_static = matches!(
|
2024-07-05 10:05:58 +00:00
|
|
|
cx.tcx().parent_hir_node(hir_ty.hir_id),
|
2022-02-26 07:43:47 -03:00
|
|
|
Node::Item(&hir::Item {
|
|
|
|
|
kind: hir::ItemKind::Const(..) | hir::ItemKind::Static(..),
|
|
|
|
|
..
|
|
|
|
|
}) | Node::TraitItem(&hir::TraitItem { kind: hir::TraitItemKind::Const(..), .. })
|
|
|
|
|
| Node::ImplItem(&hir::ImplItem { kind: hir::ImplItemKind::Const(..), .. })
|
|
|
|
|
);
|
2021-02-10 15:49:23 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// if function is wrapped around a const or static,
|
|
|
|
|
// then don't show the suggestion
|
2021-06-16 18:47:26 +09:00
|
|
|
if !(is_fn && is_const_or_static) {
|
2021-02-10 15:49:23 +00:00
|
|
|
err.multipart_suggestion(
|
|
|
|
|
"use type parameters instead",
|
|
|
|
|
sugg,
|
|
|
|
|
Applicability::HasPlaceholders,
|
|
|
|
|
);
|
|
|
|
|
}
|
2019-12-24 13:18:09 -08:00
|
|
|
}
|
2022-03-27 19:43:05 -07:00
|
|
|
|
|
|
|
|
err
|
2019-12-24 13:18:09 -08:00
|
|
|
}
|
|
|
|
|
|
2025-06-05 10:52:24 +00:00
|
|
|
pub(super) fn reject_placeholder_type_signatures_in_item<'tcx>(
|
2021-12-14 09:26:57 -04:00
|
|
|
tcx: TyCtxt<'tcx>,
|
|
|
|
|
item: &'tcx hir::Item<'tcx>,
|
|
|
|
|
) {
|
2019-12-24 13:18:09 -08:00
|
|
|
let (generics, suggest) = match &item.kind {
|
2025-05-28 15:18:48 +10:00
|
|
|
hir::ItemKind::Union(_, generics, _)
|
|
|
|
|
| hir::ItemKind::Enum(_, generics, _)
|
Move `hir::Item::ident` into `hir::ItemKind`.
`hir::Item` has an `ident` field.
- It's always non-empty for these item kinds: `ExternCrate`, `Static`,
`Const`, `Fn`, `Macro`, `Mod`, `TyAlias`, `Enum`, `Struct`, `Union`,
Trait`, TraitAalis`.
- It's always empty for these item kinds: `ForeignMod`, `GlobalAsm`,
`Impl`.
- For `Use`, it is non-empty for `UseKind::Single` and empty for
`UseKind::{Glob,ListStem}`.
All of this is quite non-obvious; the only documentation is a single
comment saying "The name might be a dummy name in case of anonymous
items". Some sites that handle items check for an empty ident, some
don't. This is a very C-like way of doing things, but this is Rust, we
have sum types, we can do this properly and never forget to check for
the exceptional case and never YOLO possibly empty identifiers (or
possibly dummy spans) around and hope that things will work out.
The commit is large but it's mostly obvious plumbing work. Some notable
things.
- A similar transformation makes sense for `ast::Item`, but this is
already a big change. That can be done later.
- Lots of assertions are added to item lowering to ensure that
identifiers are empty/non-empty as expected. These will be removable
when `ast::Item` is done later.
- `ItemKind::Use` doesn't get an `Ident`, but `UseKind::Single` does.
- `lower_use_tree` is significantly simpler. No more confusing `&mut
Ident` to deal with.
- `ItemKind::ident` is a new method, it returns an `Option<Ident>`. It's
used with `unwrap` in a few places; sometimes it's hard to tell
exactly which item kinds might occur. None of these unwraps fail on
the test suite. It's conceivable that some might fail on alternative
input. We can deal with those if/when they happen.
- In `trait_path` the `find_map`/`if let` is replaced with a loop, and
things end up much clearer that way.
- `named_span` no longer checks for an empty name; instead the call site
now checks for a missing identifier if necessary.
- `maybe_inline_local` doesn't need the `glob` argument, it can be
computed in-function from the `renamed` argument.
- `arbitrary_source_item_ordering::check_mod` had a big `if` statement
that was just getting the ident from the item kinds that had one. It
could be mostly replaced by a single call to the new `ItemKind::ident`
method.
- `ItemKind` grows from 56 to 64 bytes, but `Item` stays the same size,
and that's what matters, because `ItemKind` only occurs within `Item`.
2025-03-06 19:07:36 +11:00
|
|
|
| hir::ItemKind::TraitAlias(_, generics, _)
|
|
|
|
|
| hir::ItemKind::Trait(_, _, _, generics, ..)
|
2020-11-22 17:46:21 -05:00
|
|
|
| hir::ItemKind::Impl(hir::Impl { generics, .. })
|
2025-05-28 15:18:48 +10:00
|
|
|
| hir::ItemKind::Struct(_, generics, _) => (generics, true),
|
|
|
|
|
hir::ItemKind::TyAlias(_, generics, _) => (generics, false),
|
2019-12-27 15:45:39 -08:00
|
|
|
// `static`, `fn` and `const` are handled elsewhere to suggest appropriate type.
|
2019-12-24 13:18:09 -08:00
|
|
|
_ => return,
|
|
|
|
|
};
|
|
|
|
|
|
2022-01-05 11:43:21 +01:00
|
|
|
let mut visitor = HirPlaceholderCollector::default();
|
2019-12-24 13:18:09 -08:00
|
|
|
visitor.visit_item(item);
|
|
|
|
|
|
2024-07-05 10:05:58 +00:00
|
|
|
let icx = ItemCtxt::new(tcx, item.owner_id.def_id);
|
|
|
|
|
|
|
|
|
|
placeholder_type_error(
|
|
|
|
|
icx.lowerer(),
|
|
|
|
|
Some(generics),
|
2025-01-02 19:08:12 +00:00
|
|
|
visitor.spans,
|
|
|
|
|
suggest && !visitor.may_contain_const_infer,
|
2024-07-05 10:05:58 +00:00
|
|
|
None,
|
|
|
|
|
item.kind.descr(),
|
|
|
|
|
);
|
2019-12-24 13:18:09 -08:00
|
|
|
}
|
|
|
|
|
|
2014-08-27 21:46:52 -04:00
|
|
|
///////////////////////////////////////////////////////////////////////////
|
|
|
|
|
// Utility types and common code for the above passes.
|
|
|
|
|
|
2024-07-05 10:05:58 +00:00
|
|
|
fn bad_placeholder<'cx, 'tcx>(
|
|
|
|
|
cx: &'cx dyn HirTyLowerer<'tcx>,
|
2019-12-27 04:15:48 -08:00
|
|
|
mut spans: Vec<Span>,
|
2021-06-19 07:01:37 +08:00
|
|
|
kind: &'static str,
|
2024-07-05 10:05:58 +00:00
|
|
|
) -> Diag<'cx> {
|
2023-07-25 23:17:39 +02:00
|
|
|
let kind = if kind.ends_with('s') { format!("{kind}es") } else { format!("{kind}s") };
|
2021-06-19 07:01:37 +08:00
|
|
|
|
2019-12-27 04:15:48 -08:00
|
|
|
spans.sort();
|
2024-07-05 10:05:58 +00:00
|
|
|
cx.dcx().create_err(errors::PlaceholderNotAllowedItemSignatures { spans, kind })
|
2019-07-17 09:55:15 +03:00
|
|
|
}
|
|
|
|
|
|
2021-12-13 21:45:08 -04:00
|
|
|
impl<'tcx> ItemCtxt<'tcx> {
|
2025-01-29 10:52:24 +11:00
|
|
|
pub(crate) fn new(tcx: TyCtxt<'tcx>, item_def_id: LocalDefId) -> ItemCtxt<'tcx> {
|
2024-01-10 10:31:06 +00:00
|
|
|
ItemCtxt { tcx, item_def_id, tainted_by_errors: Cell::new(None) }
|
2015-02-16 15:48:31 -05:00
|
|
|
}
|
|
|
|
|
|
2025-01-29 10:52:24 +11:00
|
|
|
pub(crate) fn lower_ty(&self, hir_ty: &hir::Ty<'tcx>) -> Ty<'tcx> {
|
2024-02-11 09:24:35 +01:00
|
|
|
self.lowerer().lower_ty(hir_ty)
|
2012-05-15 19:36:04 -07:00
|
|
|
}
|
2020-02-10 19:14:31 -08:00
|
|
|
|
2025-01-29 10:52:24 +11:00
|
|
|
pub(crate) fn hir_id(&self) -> hir::HirId {
|
2023-11-24 19:28:19 +03:00
|
|
|
self.tcx.local_def_id_to_hir_id(self.item_def_id)
|
2020-02-10 19:14:31 -08:00
|
|
|
}
|
|
|
|
|
|
2025-01-29 10:52:24 +11:00
|
|
|
pub(crate) fn node(&self) -> hir::Node<'tcx> {
|
2023-12-01 05:28:34 -08:00
|
|
|
self.tcx.hir_node(self.hir_id())
|
2020-02-10 19:14:31 -08:00
|
|
|
}
|
2024-01-10 10:31:06 +00:00
|
|
|
|
|
|
|
|
fn check_tainted_by_errors(&self) -> Result<(), ErrorGuaranteed> {
|
|
|
|
|
match self.tainted_by_errors.get() {
|
|
|
|
|
Some(err) => Err(err),
|
|
|
|
|
None => Ok(()),
|
|
|
|
|
}
|
|
|
|
|
}
|
2012-05-15 19:36:04 -07:00
|
|
|
}
|
|
|
|
|
|
2024-03-15 03:21:55 +01:00
|
|
|
impl<'tcx> HirTyLowerer<'tcx> for ItemCtxt<'tcx> {
|
2019-06-14 00:48:52 +03:00
|
|
|
fn tcx(&self) -> TyCtxt<'tcx> {
|
2018-08-19 12:34:21 -04:00
|
|
|
self.tcx
|
|
|
|
|
}
|
2012-05-15 19:36:04 -07:00
|
|
|
|
2024-07-05 09:16:00 +00:00
|
|
|
fn dcx(&self) -> DiagCtxtHandle<'_> {
|
|
|
|
|
self.tcx.dcx().taintable_handle(&self.tainted_by_errors)
|
|
|
|
|
}
|
|
|
|
|
|
2024-05-29 10:13:28 +00:00
|
|
|
fn item_def_id(&self) -> LocalDefId {
|
|
|
|
|
self.item_def_id
|
2019-11-01 13:50:36 +01:00
|
|
|
}
|
|
|
|
|
|
2024-06-04 13:36:28 +00:00
|
|
|
fn re_infer(&self, span: Span, reason: RegionInferReason<'_>) -> ty::Region<'tcx> {
|
2024-08-24 14:55:31 -04:00
|
|
|
if let RegionInferReason::ObjectLifetimeDefault = reason {
|
2024-05-31 13:09:18 +00:00
|
|
|
let e = struct_span_code_err!(
|
2024-07-05 10:05:58 +00:00
|
|
|
self.dcx(),
|
2024-05-31 13:09:18 +00:00
|
|
|
span,
|
|
|
|
|
E0228,
|
|
|
|
|
"the lifetime bound for this object type cannot be deduced \
|
|
|
|
|
from context; please supply an explicit bound"
|
|
|
|
|
)
|
|
|
|
|
.emit();
|
|
|
|
|
ty::Region::new_error(self.tcx(), e)
|
|
|
|
|
} else {
|
|
|
|
|
// This indicates an illegal lifetime in a non-assoc-trait position
|
|
|
|
|
ty::Region::new_error_with_message(self.tcx(), span, "unelided lifetime in signature")
|
|
|
|
|
}
|
2017-01-13 15:09:56 +02:00
|
|
|
}
|
|
|
|
|
|
2019-06-06 01:55:34 +01:00
|
|
|
fn ty_infer(&self, _: Option<&ty::GenericParamDef>, span: Span) -> Ty<'tcx> {
|
2023-07-05 20:13:26 +01:00
|
|
|
Ty::new_error_with_message(self.tcx(), span, "bad placeholder type")
|
2012-05-15 19:36:04 -07:00
|
|
|
}
|
2014-08-05 19:44:21 -07:00
|
|
|
|
2024-06-03 01:10:24 +01:00
|
|
|
fn ct_infer(&self, _: Option<&ty::GenericParamDef>, span: Span) -> Const<'tcx> {
|
|
|
|
|
ty::Const::new_error_with_message(self.tcx(), span, "bad placeholder constant")
|
2019-06-06 01:55:09 +01:00
|
|
|
}
|
|
|
|
|
|
2024-12-11 22:18:39 +00:00
|
|
|
fn register_trait_ascription_bounds(
|
|
|
|
|
&self,
|
|
|
|
|
_: Vec<(ty::Clause<'tcx>, Span)>,
|
|
|
|
|
_: HirId,
|
|
|
|
|
span: Span,
|
|
|
|
|
) {
|
|
|
|
|
self.dcx().span_delayed_bug(span, "trait ascription type not allowed here");
|
|
|
|
|
}
|
|
|
|
|
|
2024-03-22 05:47:11 +01:00
|
|
|
fn probe_ty_param_bounds(
|
|
|
|
|
&self,
|
|
|
|
|
span: Span,
|
|
|
|
|
def_id: LocalDefId,
|
2025-04-08 12:23:07 +10:00
|
|
|
assoc_ident: Ident,
|
2024-08-29 00:17:40 -04:00
|
|
|
) -> ty::EarlyBinder<'tcx, &'tcx [(ty::Clause<'tcx>, Span)]> {
|
2025-04-08 12:23:07 +10:00
|
|
|
self.tcx.at(span).type_param_predicates((self.item_def_id, def_id, assoc_ident))
|
2024-03-22 05:47:11 +01:00
|
|
|
}
|
|
|
|
|
|
2025-04-24 10:49:06 +01:00
|
|
|
#[instrument(level = "debug", skip(self, _span), ret)]
|
|
|
|
|
fn select_inherent_assoc_candidates(
|
|
|
|
|
&self,
|
|
|
|
|
_span: Span,
|
|
|
|
|
self_ty: Ty<'tcx>,
|
|
|
|
|
candidates: Vec<InherentAssocCandidate>,
|
|
|
|
|
) -> (Vec<InherentAssocCandidate>, Vec<FulfillmentError<'tcx>>) {
|
|
|
|
|
assert!(!self_ty.has_infer());
|
|
|
|
|
|
|
|
|
|
// We don't just call the normal normalization routine here as we can't provide the
|
2025-06-17 14:45:47 +01:00
|
|
|
// correct `ParamEnv` and it would be wrong to invoke arbitrary trait solving under
|
2025-04-24 10:49:06 +01:00
|
|
|
// the wrong `ParamEnv`. Expanding free aliases doesn't need a `ParamEnv` so we do
|
|
|
|
|
// this just to make resolution a little bit smarter.
|
|
|
|
|
let self_ty = self.tcx.expand_free_alias_tys(self_ty);
|
|
|
|
|
debug!("select_inherent_assoc_candidates: self_ty={:?}", self_ty);
|
|
|
|
|
|
2025-06-17 14:45:47 +01:00
|
|
|
let candidates = candidates
|
|
|
|
|
.into_iter()
|
|
|
|
|
.filter(|&InherentAssocCandidate { impl_, .. }| {
|
|
|
|
|
let impl_ty = self.tcx().type_of(impl_).instantiate_identity();
|
|
|
|
|
|
|
|
|
|
// See comment on doing this operation for `self_ty`
|
|
|
|
|
let impl_ty = self.tcx.expand_free_alias_tys(impl_ty);
|
|
|
|
|
debug!("select_inherent_assoc_candidates: impl_ty={:?}", impl_ty);
|
|
|
|
|
|
|
|
|
|
// We treat parameters in the self ty as rigid and parameters in the impl ty as infers
|
|
|
|
|
// because it allows `impl<T> Foo<T>` to unify with `Foo<u8>::IAT`, while also disallowing
|
|
|
|
|
// `Foo<T>::IAT` from unifying with `impl Foo<u8>`.
|
|
|
|
|
//
|
|
|
|
|
// We don't really care about a depth limit here because we're only working with user-written
|
|
|
|
|
// types and if they wrote a type that would take hours to walk then that's kind of on them. On
|
|
|
|
|
// the other hand the default depth limit is relatively low and could realistically be hit by
|
|
|
|
|
// users in normal cases.
|
|
|
|
|
//
|
|
|
|
|
// `DeepRejectCtxt` leads to slightly worse IAT resolution than real type equality in cases
|
|
|
|
|
// where the `impl_ty` has repeated uses of generic parameters. E.g. `impl<T> Foo<T, T>` would
|
|
|
|
|
// be considered a valid candidate when resolving `Foo<u8, u16>::IAT`.
|
|
|
|
|
//
|
|
|
|
|
// Not replacing escaping bound vars in `self_ty` with placeholders also leads to slightly worse
|
|
|
|
|
// resolution, but it probably won't come up in practice and it would be backwards compatible
|
|
|
|
|
// to switch over to doing that.
|
|
|
|
|
ty::DeepRejectCtxt::relate_rigid_infer(self.tcx).types_may_unify_with_depth(
|
|
|
|
|
self_ty,
|
|
|
|
|
impl_ty,
|
|
|
|
|
usize::MAX,
|
|
|
|
|
)
|
|
|
|
|
})
|
|
|
|
|
.collect();
|
2025-04-24 10:49:06 +01:00
|
|
|
|
|
|
|
|
(candidates, vec![])
|
|
|
|
|
}
|
|
|
|
|
|
2025-04-23 15:58:20 +02:00
|
|
|
fn lower_assoc_item_path(
|
2018-08-19 12:34:21 -04:00
|
|
|
&self,
|
|
|
|
|
span: Span,
|
|
|
|
|
item_def_id: DefId,
|
2025-01-06 21:15:56 -08:00
|
|
|
item_segment: &rustc_hir::PathSegment<'tcx>,
|
2018-08-19 12:34:21 -04:00
|
|
|
poly_trait_ref: ty::PolyTraitRef<'tcx>,
|
2025-01-06 21:15:56 -08:00
|
|
|
) -> Result<(DefId, ty::GenericArgsRef<'tcx>), ErrorGuaranteed> {
|
2018-10-24 22:30:34 +02:00
|
|
|
if let Some(trait_ref) = poly_trait_ref.no_bound_vars() {
|
2024-03-15 03:21:55 +01:00
|
|
|
let item_args = self.lowerer().lower_generic_args_of_assoc_item(
|
2019-12-08 17:04:17 +00:00
|
|
|
span,
|
|
|
|
|
item_def_id,
|
|
|
|
|
item_segment,
|
2023-07-11 22:35:29 +01:00
|
|
|
trait_ref.args,
|
2019-12-08 17:04:17 +00:00
|
|
|
);
|
2025-01-06 21:15:56 -08:00
|
|
|
Ok((item_def_id, item_args))
|
2016-05-03 05:23:22 +03:00
|
|
|
} else {
|
2019-06-17 23:40:24 +01:00
|
|
|
// There are no late-bound regions; we can just ignore the binder.
|
2023-04-07 02:04:42 +03:00
|
|
|
let (mut mpart_sugg, mut inferred_sugg) = (None, None);
|
|
|
|
|
let mut bound = String::new();
|
2020-02-10 19:14:31 -08:00
|
|
|
|
|
|
|
|
match self.node() {
|
2020-02-11 12:37:12 -08:00
|
|
|
hir::Node::Field(_) | hir::Node::Ctor(_) | hir::Node::Variant(_) => {
|
2022-09-20 14:11:23 +09:00
|
|
|
let item = self
|
|
|
|
|
.tcx
|
2025-02-21 18:33:05 +11:00
|
|
|
.hir_expect_item(self.tcx.hir_get_parent_item(self.hir_id()).def_id);
|
2020-02-11 12:37:12 -08:00
|
|
|
match &item.kind {
|
2025-05-28 15:18:48 +10:00
|
|
|
hir::ItemKind::Enum(_, generics, _)
|
|
|
|
|
| hir::ItemKind::Struct(_, generics, _)
|
|
|
|
|
| hir::ItemKind::Union(_, generics, _) => {
|
2020-02-13 22:45:48 -08:00
|
|
|
let lt_name = get_new_lifetime_name(self.tcx, poly_trait_ref, generics);
|
2021-02-16 00:30:06 +01:00
|
|
|
let (lt_sp, sugg) = match generics.params {
|
2023-07-25 23:17:39 +02:00
|
|
|
[] => (generics.span, format!("<{lt_name}>")),
|
|
|
|
|
[bound, ..] => (bound.span.shrink_to_lo(), format!("{lt_name}, ")),
|
2020-02-11 12:37:12 -08:00
|
|
|
};
|
2024-08-26 16:31:06 -04:00
|
|
|
mpart_sugg = Some(errors::AssociatedItemTraitUninferredGenericParamsMultipartSuggestion {
|
2023-04-07 02:04:42 +03:00
|
|
|
fspan: lt_sp,
|
|
|
|
|
first: sugg,
|
|
|
|
|
sspan: span.with_hi(item_segment.ident.span.lo()),
|
|
|
|
|
second: format!(
|
|
|
|
|
"{}::",
|
|
|
|
|
// Replace the existing lifetimes with a new named lifetime.
|
2023-11-17 09:29:48 +00:00
|
|
|
self.tcx.instantiate_bound_regions_uncached(
|
2023-04-07 02:04:42 +03:00
|
|
|
poly_trait_ref,
|
|
|
|
|
|_| {
|
2023-11-14 13:13:27 +00:00
|
|
|
ty::Region::new_early_param(self.tcx, ty::EarlyParamRegion {
|
2023-04-07 02:04:42 +03:00
|
|
|
index: 0,
|
|
|
|
|
name: Symbol::intern(<_name),
|
|
|
|
|
})
|
|
|
|
|
}
|
2020-02-11 12:37:12 -08:00
|
|
|
),
|
|
|
|
|
),
|
2023-04-07 02:04:42 +03:00
|
|
|
});
|
2020-02-11 12:37:12 -08:00
|
|
|
}
|
|
|
|
|
_ => {}
|
|
|
|
|
}
|
2020-02-10 19:14:31 -08:00
|
|
|
}
|
2020-04-16 17:38:52 -07:00
|
|
|
hir::Node::Item(hir::Item {
|
|
|
|
|
kind:
|
|
|
|
|
hir::ItemKind::Struct(..) | hir::ItemKind::Enum(..) | hir::ItemKind::Union(..),
|
|
|
|
|
..
|
|
|
|
|
}) => {}
|
2020-02-10 19:14:31 -08:00
|
|
|
hir::Node::Item(_)
|
|
|
|
|
| hir::Node::ForeignItem(_)
|
|
|
|
|
| hir::Node::TraitItem(_)
|
|
|
|
|
| hir::Node::ImplItem(_) => {
|
2023-04-07 02:04:42 +03:00
|
|
|
inferred_sugg = Some(span.with_hi(item_segment.ident.span.lo()));
|
|
|
|
|
bound = format!(
|
|
|
|
|
"{}::",
|
|
|
|
|
// Erase named lt, we want `<A as B<'_>::C`, not `<A as B<'a>::C`.
|
|
|
|
|
self.tcx.anonymize_bound_vars(poly_trait_ref).skip_binder(),
|
2020-02-10 19:14:31 -08:00
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
_ => {}
|
|
|
|
|
}
|
2025-01-06 21:15:56 -08:00
|
|
|
|
|
|
|
|
Err(self.tcx().dcx().emit_err(errors::AssociatedItemTraitUninferredGenericParams {
|
|
|
|
|
span,
|
|
|
|
|
inferred_sugg,
|
|
|
|
|
bound,
|
|
|
|
|
mpart_sugg,
|
2025-04-22 19:17:28 +02:00
|
|
|
what: self.tcx.def_descr(item_def_id),
|
2025-01-06 21:15:56 -08:00
|
|
|
}))
|
2016-05-03 05:23:22 +03:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2022-10-29 16:19:57 +03:00
|
|
|
fn probe_adt(&self, _span: Span, ty: Ty<'tcx>) -> Option<ty::AdtDef<'tcx>> {
|
|
|
|
|
// FIXME(#103640): Should we handle the case where `ty` is a projection?
|
|
|
|
|
ty.ty_adt_def()
|
|
|
|
|
}
|
|
|
|
|
|
2017-09-16 02:33:41 +03:00
|
|
|
fn record_ty(&self, _hir_id: hir::HirId, _ty: Ty<'tcx>, _span: Span) {
|
2019-06-17 23:40:24 +01:00
|
|
|
// There's no place to record types from signatures?
|
2017-09-16 02:33:41 +03:00
|
|
|
}
|
2023-01-22 05:11:24 +00:00
|
|
|
|
|
|
|
|
fn infcx(&self) -> Option<&InferCtxt<'tcx>> {
|
|
|
|
|
None
|
|
|
|
|
}
|
2024-03-22 05:47:11 +01:00
|
|
|
|
2024-05-31 13:36:27 +00:00
|
|
|
fn lower_fn_sig(
|
|
|
|
|
&self,
|
|
|
|
|
decl: &hir::FnDecl<'tcx>,
|
|
|
|
|
generics: Option<&hir::Generics<'_>>,
|
|
|
|
|
hir_id: rustc_hir::HirId,
|
|
|
|
|
hir_ty: Option<&hir::Ty<'_>>,
|
|
|
|
|
) -> (Vec<Ty<'tcx>>, Ty<'tcx>) {
|
|
|
|
|
let tcx = self.tcx();
|
|
|
|
|
// We proactively collect all the inferred type params to emit a single error per fn def.
|
|
|
|
|
let mut visitor = HirPlaceholderCollector::default();
|
|
|
|
|
let mut infer_replacements = vec![];
|
|
|
|
|
|
|
|
|
|
if let Some(generics) = generics {
|
|
|
|
|
walk_generics(&mut visitor, generics);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
let input_tys = decl
|
|
|
|
|
.inputs
|
|
|
|
|
.iter()
|
|
|
|
|
.enumerate()
|
|
|
|
|
.map(|(i, a)| {
|
2025-01-11 19:12:36 +00:00
|
|
|
if let hir::TyKind::Infer(()) = a.kind {
|
2024-05-31 13:36:27 +00:00
|
|
|
if let Some(suggested_ty) =
|
|
|
|
|
self.lowerer().suggest_trait_fn_ty_for_impl_fn_infer(hir_id, Some(i))
|
|
|
|
|
{
|
|
|
|
|
infer_replacements.push((a.span, suggested_ty.to_string()));
|
|
|
|
|
return Ty::new_error_with_message(tcx, a.span, suggested_ty.to_string());
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Only visit the type looking for `_` if we didn't fix the type above
|
2025-01-18 22:45:41 +00:00
|
|
|
visitor.visit_ty_unambig(a);
|
2025-06-12 15:03:34 +00:00
|
|
|
self.lowerer().lower_ty(a)
|
2024-05-31 13:36:27 +00:00
|
|
|
})
|
|
|
|
|
.collect();
|
|
|
|
|
|
|
|
|
|
let output_ty = match decl.output {
|
|
|
|
|
hir::FnRetTy::Return(output) => {
|
2025-01-11 19:12:36 +00:00
|
|
|
if let hir::TyKind::Infer(()) = output.kind
|
2024-05-31 13:36:27 +00:00
|
|
|
&& let Some(suggested_ty) =
|
|
|
|
|
self.lowerer().suggest_trait_fn_ty_for_impl_fn_infer(hir_id, None)
|
|
|
|
|
{
|
|
|
|
|
infer_replacements.push((output.span, suggested_ty.to_string()));
|
|
|
|
|
Ty::new_error_with_message(tcx, output.span, suggested_ty.to_string())
|
|
|
|
|
} else {
|
2025-01-18 22:45:41 +00:00
|
|
|
visitor.visit_ty_unambig(output);
|
2024-05-31 13:36:27 +00:00
|
|
|
self.lower_ty(output)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
hir::FnRetTy::DefaultReturn(..) => tcx.types.unit,
|
|
|
|
|
};
|
|
|
|
|
|
2025-01-02 19:08:12 +00:00
|
|
|
if !(visitor.spans.is_empty() && infer_replacements.is_empty()) {
|
2024-05-31 13:36:27 +00:00
|
|
|
// We check for the presence of
|
|
|
|
|
// `ident_span` to not emit an error twice when we have `fn foo(_: fn() -> _)`.
|
|
|
|
|
|
|
|
|
|
let mut diag = crate::collect::placeholder_type_error_diag(
|
2024-07-05 10:05:58 +00:00
|
|
|
self,
|
2024-05-31 13:36:27 +00:00
|
|
|
generics,
|
2025-01-02 19:08:12 +00:00
|
|
|
visitor.spans,
|
2024-05-31 13:36:27 +00:00
|
|
|
infer_replacements.iter().map(|(s, _)| *s).collect(),
|
2025-01-02 19:08:12 +00:00
|
|
|
!visitor.may_contain_const_infer,
|
2024-05-31 13:36:27 +00:00
|
|
|
hir_ty,
|
|
|
|
|
"function",
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
if !infer_replacements.is_empty() {
|
|
|
|
|
diag.multipart_suggestion(
|
|
|
|
|
format!(
|
2024-12-31 18:51:36 +00:00
|
|
|
"try replacing `_` with the type{} in the corresponding trait method \
|
|
|
|
|
signature",
|
|
|
|
|
rustc_errors::pluralize!(infer_replacements.len()),
|
|
|
|
|
),
|
2024-05-31 13:36:27 +00:00
|
|
|
infer_replacements,
|
|
|
|
|
Applicability::MachineApplicable,
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
|
2024-07-05 10:05:58 +00:00
|
|
|
diag.emit();
|
2024-05-31 13:36:27 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
(input_tys, output_ty)
|
|
|
|
|
}
|
2025-05-26 10:38:02 +00:00
|
|
|
|
|
|
|
|
fn dyn_compatibility_violations(&self, trait_def_id: DefId) -> Vec<DynCompatibilityViolation> {
|
|
|
|
|
hir_ty_lowering_dyn_compatibility_violations(self.tcx, trait_def_id)
|
|
|
|
|
}
|
2012-05-15 19:36:04 -07:00
|
|
|
}
|
|
|
|
|
|
2020-02-13 22:45:48 -08:00
|
|
|
/// Synthesize a new lifetime name that doesn't clash with any of the lifetimes already present.
|
|
|
|
|
fn get_new_lifetime_name<'tcx>(
|
|
|
|
|
tcx: TyCtxt<'tcx>,
|
|
|
|
|
poly_trait_ref: ty::PolyTraitRef<'tcx>,
|
|
|
|
|
generics: &hir::Generics<'tcx>,
|
|
|
|
|
) -> String {
|
|
|
|
|
let existing_lifetimes = tcx
|
2024-02-20 13:50:39 +01:00
|
|
|
.collect_referenced_late_bound_regions(poly_trait_ref)
|
2020-02-13 22:45:48 -08:00
|
|
|
.into_iter()
|
|
|
|
|
.filter_map(|lt| {
|
2024-11-03 22:06:03 +00:00
|
|
|
if let ty::BoundRegionKind::Named(_, name) = lt {
|
2020-02-13 22:45:48 -08:00
|
|
|
Some(name.as_str().to_string())
|
|
|
|
|
} else {
|
|
|
|
|
None
|
|
|
|
|
}
|
|
|
|
|
})
|
|
|
|
|
.chain(generics.params.iter().filter_map(|param| {
|
|
|
|
|
if let hir::GenericParamKind::Lifetime { .. } = ¶m.kind {
|
|
|
|
|
Some(param.name.ident().as_str().to_string())
|
|
|
|
|
} else {
|
|
|
|
|
None
|
|
|
|
|
}
|
|
|
|
|
}))
|
|
|
|
|
.collect::<FxHashSet<String>>();
|
|
|
|
|
|
|
|
|
|
let a_to_z_repeat_n = |n| {
|
|
|
|
|
(b'a'..=b'z').map(move |c| {
|
2020-02-29 00:35:24 +01:00
|
|
|
let mut s = '\''.to_string();
|
2020-02-13 22:45:48 -08:00
|
|
|
s.extend(std::iter::repeat(char::from(c)).take(n));
|
|
|
|
|
s
|
|
|
|
|
})
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
// If all single char lifetime names are present, we wrap around and double the chars.
|
|
|
|
|
(1..).flat_map(a_to_z_repeat_n).find(|lt| !existing_lifetimes.contains(lt.as_str())).unwrap()
|
|
|
|
|
}
|
|
|
|
|
|
2024-02-11 09:24:35 +01:00
|
|
|
#[instrument(level = "debug", skip_all)]
|
2025-06-05 10:52:24 +00:00
|
|
|
pub(super) fn lower_item(tcx: TyCtxt<'_>, item_id: hir::ItemId) {
|
2025-02-03 10:45:49 +11:00
|
|
|
let it = tcx.hir_item(item_id);
|
Move `hir::Item::ident` into `hir::ItemKind`.
`hir::Item` has an `ident` field.
- It's always non-empty for these item kinds: `ExternCrate`, `Static`,
`Const`, `Fn`, `Macro`, `Mod`, `TyAlias`, `Enum`, `Struct`, `Union`,
Trait`, TraitAalis`.
- It's always empty for these item kinds: `ForeignMod`, `GlobalAsm`,
`Impl`.
- For `Use`, it is non-empty for `UseKind::Single` and empty for
`UseKind::{Glob,ListStem}`.
All of this is quite non-obvious; the only documentation is a single
comment saying "The name might be a dummy name in case of anonymous
items". Some sites that handle items check for an empty ident, some
don't. This is a very C-like way of doing things, but this is Rust, we
have sum types, we can do this properly and never forget to check for
the exceptional case and never YOLO possibly empty identifiers (or
possibly dummy spans) around and hope that things will work out.
The commit is large but it's mostly obvious plumbing work. Some notable
things.
- A similar transformation makes sense for `ast::Item`, but this is
already a big change. That can be done later.
- Lots of assertions are added to item lowering to ensure that
identifiers are empty/non-empty as expected. These will be removable
when `ast::Item` is done later.
- `ItemKind::Use` doesn't get an `Ident`, but `UseKind::Single` does.
- `lower_use_tree` is significantly simpler. No more confusing `&mut
Ident` to deal with.
- `ItemKind::ident` is a new method, it returns an `Option<Ident>`. It's
used with `unwrap` in a few places; sometimes it's hard to tell
exactly which item kinds might occur. None of these unwraps fail on
the test suite. It's conceivable that some might fail on alternative
input. We can deal with those if/when they happen.
- In `trait_path` the `find_map`/`if let` is replaced with a loop, and
things end up much clearer that way.
- `named_span` no longer checks for an empty name; instead the call site
now checks for a missing identifier if necessary.
- `maybe_inline_local` doesn't need the `glob` argument, it can be
computed in-function from the `renamed` argument.
- `arbitrary_source_item_ordering::check_mod` had a big `if` statement
that was just getting the ident from the item kinds that had one. It
could be mostly replaced by a single call to the new `ItemKind::ident`
method.
- `ItemKind` grows from 56 to 64 bytes, but `Item` stays the same size,
and that's what matters, because `ItemKind` only occurs within `Item`.
2025-03-06 19:07:36 +11:00
|
|
|
debug!(item = ?it.kind.ident(), id = %it.hir_id());
|
2022-10-27 14:02:18 +11:00
|
|
|
let def_id = item_id.owner_id.def_id;
|
2024-07-05 10:05:58 +00:00
|
|
|
let icx = ItemCtxt::new(tcx, def_id);
|
2021-02-10 15:49:23 +00:00
|
|
|
|
2023-01-09 16:30:40 +00:00
|
|
|
match &it.kind {
|
2014-02-17 18:52:11 +13:00
|
|
|
// These don't define types.
|
Move `hir::Item::ident` into `hir::ItemKind`.
`hir::Item` has an `ident` field.
- It's always non-empty for these item kinds: `ExternCrate`, `Static`,
`Const`, `Fn`, `Macro`, `Mod`, `TyAlias`, `Enum`, `Struct`, `Union`,
Trait`, TraitAalis`.
- It's always empty for these item kinds: `ForeignMod`, `GlobalAsm`,
`Impl`.
- For `Use`, it is non-empty for `UseKind::Single` and empty for
`UseKind::{Glob,ListStem}`.
All of this is quite non-obvious; the only documentation is a single
comment saying "The name might be a dummy name in case of anonymous
items". Some sites that handle items check for an empty ident, some
don't. This is a very C-like way of doing things, but this is Rust, we
have sum types, we can do this properly and never forget to check for
the exceptional case and never YOLO possibly empty identifiers (or
possibly dummy spans) around and hope that things will work out.
The commit is large but it's mostly obvious plumbing work. Some notable
things.
- A similar transformation makes sense for `ast::Item`, but this is
already a big change. That can be done later.
- Lots of assertions are added to item lowering to ensure that
identifiers are empty/non-empty as expected. These will be removable
when `ast::Item` is done later.
- `ItemKind::Use` doesn't get an `Ident`, but `UseKind::Single` does.
- `lower_use_tree` is significantly simpler. No more confusing `&mut
Ident` to deal with.
- `ItemKind::ident` is a new method, it returns an `Option<Ident>`. It's
used with `unwrap` in a few places; sometimes it's hard to tell
exactly which item kinds might occur. None of these unwraps fail on
the test suite. It's conceivable that some might fail on alternative
input. We can deal with those if/when they happen.
- In `trait_path` the `find_map`/`if let` is replaced with a loop, and
things end up much clearer that way.
- `named_span` no longer checks for an empty name; instead the call site
now checks for a missing identifier if necessary.
- `maybe_inline_local` doesn't need the `glob` argument, it can be
computed in-function from the `renamed` argument.
- `arbitrary_source_item_ordering::check_mod` had a big `if` statement
that was just getting the ident from the item kinds that had one. It
could be mostly replaced by a single call to the new `ItemKind::ident`
method.
- `ItemKind` grows from 56 to 64 bytes, but `Item` stays the same size,
and that's what matters, because `ItemKind` only occurs within `Item`.
2025-03-06 19:07:36 +11:00
|
|
|
hir::ItemKind::ExternCrate(..)
|
2018-08-19 12:34:21 -04:00
|
|
|
| hir::ItemKind::Use(..)
|
2021-12-11 19:52:23 +08:00
|
|
|
| hir::ItemKind::Macro(..)
|
Move `hir::Item::ident` into `hir::ItemKind`.
`hir::Item` has an `ident` field.
- It's always non-empty for these item kinds: `ExternCrate`, `Static`,
`Const`, `Fn`, `Macro`, `Mod`, `TyAlias`, `Enum`, `Struct`, `Union`,
Trait`, TraitAalis`.
- It's always empty for these item kinds: `ForeignMod`, `GlobalAsm`,
`Impl`.
- For `Use`, it is non-empty for `UseKind::Single` and empty for
`UseKind::{Glob,ListStem}`.
All of this is quite non-obvious; the only documentation is a single
comment saying "The name might be a dummy name in case of anonymous
items". Some sites that handle items check for an empty ident, some
don't. This is a very C-like way of doing things, but this is Rust, we
have sum types, we can do this properly and never forget to check for
the exceptional case and never YOLO possibly empty identifiers (or
possibly dummy spans) around and hope that things will work out.
The commit is large but it's mostly obvious plumbing work. Some notable
things.
- A similar transformation makes sense for `ast::Item`, but this is
already a big change. That can be done later.
- Lots of assertions are added to item lowering to ensure that
identifiers are empty/non-empty as expected. These will be removable
when `ast::Item` is done later.
- `ItemKind::Use` doesn't get an `Ident`, but `UseKind::Single` does.
- `lower_use_tree` is significantly simpler. No more confusing `&mut
Ident` to deal with.
- `ItemKind::ident` is a new method, it returns an `Option<Ident>`. It's
used with `unwrap` in a few places; sometimes it's hard to tell
exactly which item kinds might occur. None of these unwraps fail on
the test suite. It's conceivable that some might fail on alternative
input. We can deal with those if/when they happen.
- In `trait_path` the `find_map`/`if let` is replaced with a loop, and
things end up much clearer that way.
- `named_span` no longer checks for an empty name; instead the call site
now checks for a missing identifier if necessary.
- `maybe_inline_local` doesn't need the `glob` argument, it can be
computed in-function from the `renamed` argument.
- `arbitrary_source_item_ordering::check_mod` had a big `if` statement
that was just getting the ident from the item kinds that had one. It
could be mostly replaced by a single call to the new `ItemKind::ident`
method.
- `ItemKind` grows from 56 to 64 bytes, but `Item` stays the same size,
and that's what matters, because `ItemKind` only occurs within `Item`.
2025-03-06 19:07:36 +11:00
|
|
|
| hir::ItemKind::Mod(..)
|
2025-02-17 05:33:06 +00:00
|
|
|
| hir::ItemKind::GlobalAsm { .. } => {}
|
2020-11-11 22:40:09 +01:00
|
|
|
hir::ItemKind::ForeignMod { items, .. } => {
|
2023-01-09 16:30:40 +00:00
|
|
|
for item in *items {
|
2025-02-03 10:45:49 +11:00
|
|
|
let item = tcx.hir_foreign_item(item.id);
|
2025-01-30 16:20:09 +11:00
|
|
|
tcx.ensure_ok().generics_of(item.owner_id);
|
|
|
|
|
tcx.ensure_ok().type_of(item.owner_id);
|
|
|
|
|
tcx.ensure_ok().predicates_of(item.owner_id);
|
2024-11-19 20:29:01 +00:00
|
|
|
if tcx.is_conditionally_const(def_id) {
|
2025-01-30 16:20:09 +11:00
|
|
|
tcx.ensure_ok().explicit_implied_const_bounds(def_id);
|
|
|
|
|
tcx.ensure_ok().const_conditions(def_id);
|
2024-11-19 20:29:01 +00:00
|
|
|
}
|
2021-04-01 10:45:42 +09:00
|
|
|
match item.kind {
|
2022-11-06 16:28:07 +00:00
|
|
|
hir::ForeignItemKind::Fn(..) => {
|
2025-01-30 16:20:09 +11:00
|
|
|
tcx.ensure_ok().codegen_fn_attrs(item.owner_id);
|
|
|
|
|
tcx.ensure_ok().fn_sig(item.owner_id)
|
2022-11-06 16:28:07 +00:00
|
|
|
}
|
2021-04-01 10:45:42 +09:00
|
|
|
hir::ForeignItemKind::Static(..) => {
|
2025-01-30 16:20:09 +11:00
|
|
|
tcx.ensure_ok().codegen_fn_attrs(item.owner_id);
|
2022-01-05 11:43:21 +01:00
|
|
|
let mut visitor = HirPlaceholderCollector::default();
|
2021-04-01 10:45:42 +09:00
|
|
|
visitor.visit_foreign_item(item);
|
2021-06-19 07:01:37 +08:00
|
|
|
placeholder_type_error(
|
2024-07-05 10:05:58 +00:00
|
|
|
icx.lowerer(),
|
2021-06-19 07:01:37 +08:00
|
|
|
None,
|
2025-01-02 19:08:12 +00:00
|
|
|
visitor.spans,
|
2021-06-19 07:01:37 +08:00
|
|
|
false,
|
|
|
|
|
None,
|
|
|
|
|
"static variable",
|
|
|
|
|
);
|
2021-04-01 10:45:42 +09:00
|
|
|
}
|
|
|
|
|
_ => (),
|
2017-05-13 17:11:52 +03:00
|
|
|
}
|
2015-12-22 16:35:02 -05:00
|
|
|
}
|
2015-02-11 10:25:52 -05:00
|
|
|
}
|
2022-10-30 09:17:16 +00:00
|
|
|
hir::ItemKind::Enum(..) => {
|
2025-01-30 16:20:09 +11:00
|
|
|
tcx.ensure_ok().generics_of(def_id);
|
|
|
|
|
tcx.ensure_ok().type_of(def_id);
|
|
|
|
|
tcx.ensure_ok().predicates_of(def_id);
|
2024-03-15 03:21:55 +01:00
|
|
|
lower_enum_variant_types(tcx, def_id.to_def_id());
|
2018-08-19 12:34:21 -04:00
|
|
|
}
|
2020-01-17 16:14:29 -08:00
|
|
|
hir::ItemKind::Impl { .. } => {
|
2025-01-30 16:20:09 +11:00
|
|
|
tcx.ensure_ok().generics_of(def_id);
|
|
|
|
|
tcx.ensure_ok().type_of(def_id);
|
|
|
|
|
tcx.ensure_ok().impl_trait_header(def_id);
|
|
|
|
|
tcx.ensure_ok().predicates_of(def_id);
|
|
|
|
|
tcx.ensure_ok().associated_items(def_id);
|
2018-08-19 12:34:21 -04:00
|
|
|
}
|
2018-07-11 23:36:06 +08:00
|
|
|
hir::ItemKind::Trait(..) => {
|
2025-01-30 16:20:09 +11:00
|
|
|
tcx.ensure_ok().generics_of(def_id);
|
|
|
|
|
tcx.ensure_ok().trait_def(def_id);
|
2024-06-27 12:01:49 -04:00
|
|
|
tcx.at(it.span).explicit_super_predicates_of(def_id);
|
2025-01-30 16:20:09 +11:00
|
|
|
tcx.ensure_ok().predicates_of(def_id);
|
|
|
|
|
tcx.ensure_ok().associated_items(def_id);
|
2018-08-19 12:34:21 -04:00
|
|
|
}
|
2018-07-11 23:36:06 +08:00
|
|
|
hir::ItemKind::TraitAlias(..) => {
|
2025-01-30 16:20:09 +11:00
|
|
|
tcx.ensure_ok().generics_of(def_id);
|
2024-06-27 12:01:49 -04:00
|
|
|
tcx.at(it.span).explicit_implied_predicates_of(def_id);
|
|
|
|
|
tcx.at(it.span).explicit_super_predicates_of(def_id);
|
2025-01-30 16:20:09 +11:00
|
|
|
tcx.ensure_ok().predicates_of(def_id);
|
2018-08-19 12:34:21 -04:00
|
|
|
}
|
2025-05-28 15:18:48 +10:00
|
|
|
hir::ItemKind::Struct(_, _, struct_def) | hir::ItemKind::Union(_, _, struct_def) => {
|
2025-01-30 16:20:09 +11:00
|
|
|
tcx.ensure_ok().generics_of(def_id);
|
|
|
|
|
tcx.ensure_ok().type_of(def_id);
|
|
|
|
|
tcx.ensure_ok().predicates_of(def_id);
|
2017-02-14 11:32:00 +02:00
|
|
|
|
|
|
|
|
for f in struct_def.fields() {
|
2025-01-30 16:20:09 +11:00
|
|
|
tcx.ensure_ok().generics_of(f.def_id);
|
|
|
|
|
tcx.ensure_ok().type_of(f.def_id);
|
|
|
|
|
tcx.ensure_ok().predicates_of(f.def_id);
|
2015-08-06 01:29:52 +03:00
|
|
|
}
|
|
|
|
|
|
2022-11-06 19:46:55 +00:00
|
|
|
if let Some(ctor_def_id) = struct_def.ctor_def_id() {
|
2024-03-15 03:21:55 +01:00
|
|
|
lower_variant_ctor(tcx, ctor_def_id);
|
2015-07-22 21:53:52 +03:00
|
|
|
}
|
2018-08-19 12:34:21 -04:00
|
|
|
}
|
2018-07-03 19:38:14 +02:00
|
|
|
|
2022-11-11 10:29:27 +00:00
|
|
|
hir::ItemKind::TyAlias(..) => {
|
2025-01-30 16:20:09 +11:00
|
|
|
tcx.ensure_ok().generics_of(def_id);
|
|
|
|
|
tcx.ensure_ok().type_of(def_id);
|
|
|
|
|
tcx.ensure_ok().predicates_of(def_id);
|
2022-11-11 10:29:27 +00:00
|
|
|
}
|
|
|
|
|
|
2025-05-28 15:18:48 +10:00
|
|
|
hir::ItemKind::Static(_, _, ty, _) | hir::ItemKind::Const(_, _, ty, _) => {
|
2025-01-30 16:20:09 +11:00
|
|
|
tcx.ensure_ok().generics_of(def_id);
|
|
|
|
|
tcx.ensure_ok().type_of(def_id);
|
|
|
|
|
tcx.ensure_ok().predicates_of(def_id);
|
2024-01-09 18:12:56 +00:00
|
|
|
if !ty.is_suggestable_infer_ty() {
|
2022-11-11 10:29:27 +00:00
|
|
|
let mut visitor = HirPlaceholderCollector::default();
|
|
|
|
|
visitor.visit_item(it);
|
2024-07-05 10:05:58 +00:00
|
|
|
placeholder_type_error(
|
|
|
|
|
icx.lowerer(),
|
|
|
|
|
None,
|
2025-01-02 19:08:12 +00:00
|
|
|
visitor.spans,
|
2024-07-05 10:05:58 +00:00
|
|
|
false,
|
|
|
|
|
None,
|
|
|
|
|
it.kind.descr(),
|
|
|
|
|
);
|
2017-05-13 17:11:52 +03:00
|
|
|
}
|
2017-03-16 22:16:40 -05:00
|
|
|
}
|
2022-11-11 10:29:27 +00:00
|
|
|
|
2025-01-04 11:30:31 +01:00
|
|
|
hir::ItemKind::Fn { .. } => {
|
2025-01-30 16:20:09 +11:00
|
|
|
tcx.ensure_ok().generics_of(def_id);
|
|
|
|
|
tcx.ensure_ok().type_of(def_id);
|
|
|
|
|
tcx.ensure_ok().predicates_of(def_id);
|
|
|
|
|
tcx.ensure_ok().fn_sig(def_id);
|
|
|
|
|
tcx.ensure_ok().codegen_fn_attrs(def_id);
|
2022-11-11 10:29:27 +00:00
|
|
|
}
|
2012-05-15 08:29:22 -07:00
|
|
|
}
|
|
|
|
|
}
|
2012-08-07 16:46:19 -07:00
|
|
|
|
2025-06-05 10:52:24 +00:00
|
|
|
pub(crate) fn lower_trait_item(tcx: TyCtxt<'_>, trait_item_id: hir::TraitItemId) {
|
2025-02-03 10:45:49 +11:00
|
|
|
let trait_item = tcx.hir_trait_item(trait_item_id);
|
2022-10-27 14:02:18 +11:00
|
|
|
let def_id = trait_item_id.owner_id;
|
2025-01-30 16:20:09 +11:00
|
|
|
tcx.ensure_ok().generics_of(def_id);
|
2024-07-05 10:05:58 +00:00
|
|
|
let icx = ItemCtxt::new(tcx, def_id.def_id);
|
2017-02-14 11:32:00 +02:00
|
|
|
|
2019-09-26 17:07:54 +01:00
|
|
|
match trait_item.kind {
|
2020-03-03 12:46:22 -06:00
|
|
|
hir::TraitItemKind::Fn(..) => {
|
2025-01-30 16:20:09 +11:00
|
|
|
tcx.ensure_ok().codegen_fn_attrs(def_id);
|
|
|
|
|
tcx.ensure_ok().type_of(def_id);
|
|
|
|
|
tcx.ensure_ok().fn_sig(def_id);
|
2020-02-17 12:07:50 -08:00
|
|
|
}
|
|
|
|
|
|
2023-06-10 21:50:36 +00:00
|
|
|
hir::TraitItemKind::Const(ty, body_id) => {
|
2025-01-30 16:20:09 +11:00
|
|
|
tcx.ensure_ok().type_of(def_id);
|
2023-12-18 22:21:37 +11:00
|
|
|
if !tcx.dcx().has_stashed_diagnostic(ty.span, StashKey::ItemNoType)
|
2024-01-09 18:12:56 +00:00
|
|
|
&& !(ty.is_suggestable_infer_ty() && body_id.is_some())
|
2023-06-10 21:50:36 +00:00
|
|
|
{
|
|
|
|
|
// Account for `const C: _;`.
|
|
|
|
|
let mut visitor = HirPlaceholderCollector::default();
|
|
|
|
|
visitor.visit_trait_item(trait_item);
|
2024-07-05 10:05:58 +00:00
|
|
|
placeholder_type_error(
|
|
|
|
|
icx.lowerer(),
|
|
|
|
|
None,
|
2025-01-02 19:08:12 +00:00
|
|
|
visitor.spans,
|
2024-07-05 10:05:58 +00:00
|
|
|
false,
|
|
|
|
|
None,
|
|
|
|
|
"associated constant",
|
|
|
|
|
);
|
2022-09-16 11:24:14 +09:00
|
|
|
}
|
2020-06-27 21:36:35 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
hir::TraitItemKind::Type(_, Some(_)) => {
|
2025-01-30 16:20:09 +11:00
|
|
|
tcx.ensure_ok().item_bounds(def_id);
|
|
|
|
|
tcx.ensure_ok().item_self_bounds(def_id);
|
|
|
|
|
tcx.ensure_ok().type_of(def_id);
|
2020-06-27 21:36:35 +01:00
|
|
|
// Account for `type T = _;`.
|
2022-01-05 11:43:21 +01:00
|
|
|
let mut visitor = HirPlaceholderCollector::default();
|
2020-02-17 12:07:50 -08:00
|
|
|
visitor.visit_trait_item(trait_item);
|
2025-01-02 19:08:12 +00:00
|
|
|
placeholder_type_error(
|
|
|
|
|
icx.lowerer(),
|
|
|
|
|
None,
|
|
|
|
|
visitor.spans,
|
|
|
|
|
false,
|
|
|
|
|
None,
|
|
|
|
|
"associated type",
|
|
|
|
|
);
|
2016-12-04 04:21:06 +02:00
|
|
|
}
|
|
|
|
|
|
2020-07-22 14:42:45 +09:00
|
|
|
hir::TraitItemKind::Type(_, None) => {
|
2025-01-30 16:20:09 +11:00
|
|
|
tcx.ensure_ok().item_bounds(def_id);
|
|
|
|
|
tcx.ensure_ok().item_self_bounds(def_id);
|
2020-07-22 14:42:45 +09:00
|
|
|
// #74612: Visit and try to find bad placeholders
|
|
|
|
|
// even if there is no concrete type.
|
2022-01-05 11:43:21 +01:00
|
|
|
let mut visitor = HirPlaceholderCollector::default();
|
2020-07-22 14:42:45 +09:00
|
|
|
visitor.visit_trait_item(trait_item);
|
2021-02-10 15:49:23 +00:00
|
|
|
|
2025-01-02 19:08:12 +00:00
|
|
|
placeholder_type_error(
|
|
|
|
|
icx.lowerer(),
|
|
|
|
|
None,
|
|
|
|
|
visitor.spans,
|
|
|
|
|
false,
|
|
|
|
|
None,
|
|
|
|
|
"associated type",
|
|
|
|
|
);
|
2020-07-22 14:42:45 +09:00
|
|
|
}
|
2017-02-14 11:32:00 +02:00
|
|
|
};
|
2016-12-04 04:21:06 +02:00
|
|
|
|
2025-01-30 16:20:09 +11:00
|
|
|
tcx.ensure_ok().predicates_of(def_id);
|
2016-12-04 04:21:06 +02:00
|
|
|
}
|
|
|
|
|
|
2025-06-05 10:52:24 +00:00
|
|
|
pub(super) fn lower_impl_item(tcx: TyCtxt<'_>, impl_item_id: hir::ImplItemId) {
|
2022-10-27 14:02:18 +11:00
|
|
|
let def_id = impl_item_id.owner_id;
|
2025-01-30 16:20:09 +11:00
|
|
|
tcx.ensure_ok().generics_of(def_id);
|
|
|
|
|
tcx.ensure_ok().type_of(def_id);
|
|
|
|
|
tcx.ensure_ok().predicates_of(def_id);
|
2025-02-03 10:45:49 +11:00
|
|
|
let impl_item = tcx.hir_impl_item(impl_item_id);
|
2024-07-05 10:05:58 +00:00
|
|
|
let icx = ItemCtxt::new(tcx, def_id.def_id);
|
2020-02-17 12:07:50 -08:00
|
|
|
match impl_item.kind {
|
2020-03-05 09:57:34 -06:00
|
|
|
hir::ImplItemKind::Fn(..) => {
|
2025-01-30 16:20:09 +11:00
|
|
|
tcx.ensure_ok().codegen_fn_attrs(def_id);
|
|
|
|
|
tcx.ensure_ok().fn_sig(def_id);
|
2020-02-17 12:07:50 -08:00
|
|
|
}
|
2022-10-09 07:09:57 +00:00
|
|
|
hir::ImplItemKind::Type(_) => {
|
2020-02-17 12:07:50 -08:00
|
|
|
// Account for `type T = _;`
|
2022-01-05 11:43:21 +01:00
|
|
|
let mut visitor = HirPlaceholderCollector::default();
|
2020-02-17 12:07:50 -08:00
|
|
|
visitor.visit_impl_item(impl_item);
|
2021-02-10 15:49:23 +00:00
|
|
|
|
2025-01-02 19:08:12 +00:00
|
|
|
placeholder_type_error(
|
|
|
|
|
icx.lowerer(),
|
|
|
|
|
None,
|
|
|
|
|
visitor.spans,
|
|
|
|
|
false,
|
|
|
|
|
None,
|
|
|
|
|
"associated type",
|
|
|
|
|
);
|
2020-02-17 12:07:50 -08:00
|
|
|
}
|
2023-06-10 21:50:36 +00:00
|
|
|
hir::ImplItemKind::Const(ty, _) => {
|
|
|
|
|
// Account for `const T: _ = ..;`
|
2024-01-09 18:12:56 +00:00
|
|
|
if !ty.is_suggestable_infer_ty() {
|
2023-06-10 21:50:36 +00:00
|
|
|
let mut visitor = HirPlaceholderCollector::default();
|
|
|
|
|
visitor.visit_impl_item(impl_item);
|
2024-07-05 10:05:58 +00:00
|
|
|
placeholder_type_error(
|
|
|
|
|
icx.lowerer(),
|
|
|
|
|
None,
|
2025-01-02 19:08:12 +00:00
|
|
|
visitor.spans,
|
2024-07-05 10:05:58 +00:00
|
|
|
false,
|
|
|
|
|
None,
|
|
|
|
|
"associated constant",
|
|
|
|
|
);
|
2023-06-10 21:50:36 +00:00
|
|
|
}
|
|
|
|
|
}
|
2017-05-13 17:11:52 +03:00
|
|
|
}
|
2016-11-08 13:23:59 -05:00
|
|
|
}
|
|
|
|
|
|
2024-03-15 03:21:55 +01:00
|
|
|
fn lower_variant_ctor(tcx: TyCtxt<'_>, def_id: LocalDefId) {
|
2025-01-30 16:20:09 +11:00
|
|
|
tcx.ensure_ok().generics_of(def_id);
|
|
|
|
|
tcx.ensure_ok().type_of(def_id);
|
|
|
|
|
tcx.ensure_ok().predicates_of(def_id);
|
2015-07-22 21:53:52 +03:00
|
|
|
}
|
|
|
|
|
|
2024-03-15 03:21:55 +01:00
|
|
|
fn lower_enum_variant_types(tcx: TyCtxt<'_>, def_id: DefId) {
|
2017-04-24 15:20:46 +03:00
|
|
|
let def = tcx.adt_def(def_id);
|
2022-03-05 07:28:41 +11:00
|
|
|
let repr_type = def.repr().discr_type();
|
2017-02-05 07:01:48 +02:00
|
|
|
let initial = repr_type.initial_discriminant(tcx);
|
2019-09-09 09:26:25 -03:00
|
|
|
let mut prev_discr = None::<Discr<'_>>;
|
2017-02-05 07:01:48 +02:00
|
|
|
|
|
|
|
|
// fill the discriminant values and field types
|
2022-10-30 09:17:16 +00:00
|
|
|
for variant in def.variants() {
|
2018-01-25 16:44:45 +01:00
|
|
|
let wrapped_discr = prev_discr.map_or(initial, |d| d.wrap_incr(tcx));
|
2018-08-19 12:34:21 -04:00
|
|
|
prev_discr = Some(
|
2022-10-30 09:17:16 +00:00
|
|
|
if let ty::VariantDiscr::Explicit(const_def_id) = variant.discr {
|
2024-02-16 16:40:51 +11:00
|
|
|
def.eval_explicit_discr(tcx, const_def_id).ok()
|
2018-08-19 12:34:21 -04:00
|
|
|
} else if let Some(discr) = repr_type.disr_incr(tcx, prev_discr) {
|
|
|
|
|
Some(discr)
|
|
|
|
|
} else {
|
2022-10-30 09:17:16 +00:00
|
|
|
let span = tcx.def_span(variant.def_id);
|
2023-12-18 22:21:37 +11:00
|
|
|
tcx.dcx().emit_err(errors::EnumDiscriminantOverflowed {
|
2023-04-07 02:04:42 +03:00
|
|
|
span,
|
|
|
|
|
discr: prev_discr.unwrap().to_string(),
|
2025-01-27 01:16:12 +00:00
|
|
|
item_name: tcx.item_ident(variant.def_id),
|
2023-04-07 02:04:42 +03:00
|
|
|
wrapped_discr: wrapped_discr.to_string(),
|
|
|
|
|
});
|
2018-08-19 12:34:21 -04:00
|
|
|
None
|
|
|
|
|
}
|
|
|
|
|
.unwrap_or(wrapped_discr),
|
|
|
|
|
);
|
2017-02-05 07:01:48 +02:00
|
|
|
|
2022-10-30 09:17:16 +00:00
|
|
|
for f in &variant.fields {
|
2025-01-30 16:20:09 +11:00
|
|
|
tcx.ensure_ok().generics_of(f.did);
|
|
|
|
|
tcx.ensure_ok().type_of(f.did);
|
|
|
|
|
tcx.ensure_ok().predicates_of(f.did);
|
2015-10-02 00:03:22 +03:00
|
|
|
}
|
2015-07-22 21:53:52 +03:00
|
|
|
|
2024-02-11 09:22:52 +01:00
|
|
|
// Lower the ctor, if any. This also registers the variant as an item.
|
2022-10-25 20:15:15 +04:00
|
|
|
if let Some(ctor_def_id) = variant.ctor_def_id() {
|
2024-03-15 03:21:55 +01:00
|
|
|
lower_variant_ctor(tcx, ctor_def_id.expect_local());
|
2019-03-21 23:38:50 +01:00
|
|
|
}
|
2015-07-22 21:53:52 +03:00
|
|
|
}
|
|
|
|
|
}
|
2014-02-24 20:17:02 +13:00
|
|
|
|
2024-01-04 21:56:45 +08:00
|
|
|
#[derive(Clone, Copy)]
|
|
|
|
|
struct NestedSpan {
|
|
|
|
|
span: Span,
|
|
|
|
|
nested_field_span: Span,
|
|
|
|
|
}
|
|
|
|
|
|
2024-01-29 15:08:11 +08:00
|
|
|
impl NestedSpan {
|
|
|
|
|
fn to_field_already_declared_nested_help(&self) -> errors::FieldAlreadyDeclaredNestedHelp {
|
|
|
|
|
errors::FieldAlreadyDeclaredNestedHelp { span: self.span }
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2024-01-04 21:56:45 +08:00
|
|
|
#[derive(Clone, Copy)]
|
|
|
|
|
enum FieldDeclSpan {
|
|
|
|
|
NotNested(Span),
|
|
|
|
|
Nested(NestedSpan),
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
impl From<Span> for FieldDeclSpan {
|
|
|
|
|
fn from(span: Span) -> Self {
|
|
|
|
|
Self::NotNested(span)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
impl From<NestedSpan> for FieldDeclSpan {
|
|
|
|
|
fn from(span: NestedSpan) -> Self {
|
|
|
|
|
Self::Nested(span)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2024-01-29 15:08:11 +08:00
|
|
|
struct FieldUniquenessCheckContext<'tcx> {
|
|
|
|
|
tcx: TyCtxt<'tcx>,
|
2024-02-11 19:50:50 +08:00
|
|
|
seen_fields: FxIndexMap<Ident, FieldDeclSpan>,
|
2024-01-29 15:08:11 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
impl<'tcx> FieldUniquenessCheckContext<'tcx> {
|
|
|
|
|
fn new(tcx: TyCtxt<'tcx>) -> Self {
|
2024-02-11 19:50:50 +08:00
|
|
|
Self { tcx, seen_fields: FxIndexMap::default() }
|
2024-01-29 15:08:11 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// Check if a given field `ident` declared at `field_decl` has been declared elsewhere before.
|
2025-01-27 01:16:12 +00:00
|
|
|
fn check_field_decl(&mut self, field_name: Ident, field_decl: FieldDeclSpan) {
|
2024-01-29 15:08:11 +08:00
|
|
|
use FieldDeclSpan::*;
|
2025-01-27 01:16:12 +00:00
|
|
|
let field_name = field_name.normalize_to_macros_2_0();
|
|
|
|
|
match (field_decl, self.seen_fields.get(&field_name).copied()) {
|
2024-01-29 15:08:11 +08:00
|
|
|
(NotNested(span), Some(NotNested(prev_span))) => {
|
|
|
|
|
self.tcx.dcx().emit_err(errors::FieldAlreadyDeclared::NotNested {
|
|
|
|
|
field_name,
|
|
|
|
|
span,
|
|
|
|
|
prev_span,
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
(NotNested(span), Some(Nested(prev))) => {
|
|
|
|
|
self.tcx.dcx().emit_err(errors::FieldAlreadyDeclared::PreviousNested {
|
|
|
|
|
field_name,
|
|
|
|
|
span,
|
|
|
|
|
prev_span: prev.span,
|
|
|
|
|
prev_nested_field_span: prev.nested_field_span,
|
|
|
|
|
prev_help: prev.to_field_already_declared_nested_help(),
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
(
|
|
|
|
|
Nested(current @ NestedSpan { span, nested_field_span, .. }),
|
|
|
|
|
Some(NotNested(prev_span)),
|
|
|
|
|
) => {
|
|
|
|
|
self.tcx.dcx().emit_err(errors::FieldAlreadyDeclared::CurrentNested {
|
|
|
|
|
field_name,
|
|
|
|
|
span,
|
|
|
|
|
nested_field_span,
|
|
|
|
|
help: current.to_field_already_declared_nested_help(),
|
|
|
|
|
prev_span,
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
(Nested(current @ NestedSpan { span, nested_field_span }), Some(Nested(prev))) => {
|
|
|
|
|
self.tcx.dcx().emit_err(errors::FieldAlreadyDeclared::BothNested {
|
|
|
|
|
field_name,
|
|
|
|
|
span,
|
|
|
|
|
nested_field_span,
|
|
|
|
|
help: current.to_field_already_declared_nested_help(),
|
|
|
|
|
prev_span: prev.span,
|
|
|
|
|
prev_nested_field_span: prev.nested_field_span,
|
|
|
|
|
prev_help: prev.to_field_already_declared_nested_help(),
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
(field_decl, None) => {
|
2025-01-27 01:16:12 +00:00
|
|
|
self.seen_fields.insert(field_name, field_decl);
|
2024-01-29 15:08:11 +08:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
2024-01-04 21:45:06 +08:00
|
|
|
}
|
|
|
|
|
|
2024-08-24 17:22:48 +00:00
|
|
|
fn lower_variant<'tcx>(
|
|
|
|
|
tcx: TyCtxt<'tcx>,
|
2020-04-09 09:43:00 +01:00
|
|
|
variant_did: Option<LocalDefId>,
|
2018-12-01 02:47:08 +00:00
|
|
|
ident: Ident,
|
2018-08-19 12:34:21 -04:00
|
|
|
discr: ty::VariantDiscr,
|
2024-08-24 17:22:48 +00:00
|
|
|
def: &hir::VariantData<'tcx>,
|
2018-09-22 21:53:58 +03:00
|
|
|
adt_kind: ty::AdtKind,
|
2020-04-12 13:45:41 +01:00
|
|
|
parent_did: LocalDefId,
|
2018-08-19 12:34:21 -04:00
|
|
|
) -> ty::VariantDef {
|
2024-01-29 15:08:11 +08:00
|
|
|
let mut field_uniqueness_check_ctx = FieldUniquenessCheckContext::new(tcx);
|
2018-08-19 12:34:21 -04:00
|
|
|
let fields = def
|
|
|
|
|
.fields()
|
|
|
|
|
.iter()
|
2024-09-29 22:10:16 -04:00
|
|
|
.inspect(|field| {
|
|
|
|
|
field_uniqueness_check_ctx.check_field_decl(field.ident, field.span.into());
|
2024-01-04 21:53:06 +08:00
|
|
|
})
|
|
|
|
|
.map(|f| ty::FieldDef {
|
|
|
|
|
did: f.def_id.to_def_id(),
|
|
|
|
|
name: f.ident.name,
|
|
|
|
|
vis: tcx.visibility(f.def_id),
|
2024-10-27 01:35:33 +02:00
|
|
|
safety: f.safety,
|
2024-08-24 17:22:48 +00:00
|
|
|
value: f.default.map(|v| v.def_id.to_def_id()),
|
2018-08-19 12:34:21 -04:00
|
|
|
})
|
|
|
|
|
.collect();
|
2024-07-11 00:07:07 +08:00
|
|
|
let recovered = match def {
|
|
|
|
|
hir::VariantData::Struct { recovered: Recovered::Yes(guar), .. } => Some(*guar),
|
|
|
|
|
_ => None,
|
|
|
|
|
};
|
2019-03-21 23:38:50 +01:00
|
|
|
ty::VariantDef::new(
|
2022-01-02 22:37:05 -05:00
|
|
|
ident.name,
|
2020-04-09 09:43:00 +01:00
|
|
|
variant_did.map(LocalDefId::to_def_id),
|
2022-10-25 20:15:15 +04:00
|
|
|
def.ctor().map(|(kind, _, def_id)| (kind, def_id.to_def_id())),
|
2017-08-06 22:54:09 -07:00
|
|
|
discr,
|
|
|
|
|
fields,
|
2020-04-12 13:45:41 +01:00
|
|
|
parent_did.to_def_id(),
|
2019-03-17 20:09:53 -07:00
|
|
|
recovered,
|
2023-03-13 18:54:05 +00:00
|
|
|
adt_kind == AdtKind::Struct && tcx.has_attr(parent_did, sym::non_exhaustive)
|
|
|
|
|
|| variant_did
|
2023-05-24 14:19:22 +00:00
|
|
|
.is_some_and(|variant_did| tcx.has_attr(variant_did, sym::non_exhaustive)),
|
2018-12-01 02:47:08 +00:00
|
|
|
)
|
2015-07-22 21:53:52 +03:00
|
|
|
}
|
2014-02-24 20:17:02 +13:00
|
|
|
|
2023-03-13 18:54:05 +00:00
|
|
|
fn adt_def(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::AdtDef<'_> {
|
2020-01-05 02:37:57 +01:00
|
|
|
use rustc_hir::*;
|
2016-11-25 01:33:29 +02:00
|
|
|
|
2023-12-01 05:28:34 -08:00
|
|
|
let Node::Item(item) = tcx.hir_node_by_def_id(def_id) else {
|
2023-12-15 03:19:46 +00:00
|
|
|
bug!("expected ADT to be an item");
|
2017-02-14 01:11:24 +02:00
|
|
|
};
|
2017-02-05 07:01:48 +02:00
|
|
|
|
2024-09-29 22:10:16 -04:00
|
|
|
let repr = tcx.repr_options_of_def(def_id);
|
2023-01-09 16:30:40 +00:00
|
|
|
let (kind, variants) = match &item.kind {
|
2025-05-28 15:18:48 +10:00
|
|
|
ItemKind::Enum(_, _, def) => {
|
2017-02-14 01:11:24 +02:00
|
|
|
let mut distance_from_explicit = 0;
|
2019-03-21 23:38:50 +01:00
|
|
|
let variants = def
|
|
|
|
|
.variants
|
|
|
|
|
.iter()
|
|
|
|
|
.map(|v| {
|
2023-01-09 16:30:40 +00:00
|
|
|
let discr = if let Some(e) = &v.disr_expr {
|
2019-03-21 23:38:50 +01:00
|
|
|
distance_from_explicit = 0;
|
2022-11-06 19:17:57 +00:00
|
|
|
ty::VariantDiscr::Explicit(e.def_id.to_def_id())
|
2019-03-21 23:38:50 +01:00
|
|
|
} else {
|
|
|
|
|
ty::VariantDiscr::Relative(distance_from_explicit)
|
|
|
|
|
};
|
|
|
|
|
distance_from_explicit += 1;
|
|
|
|
|
|
2024-03-15 03:21:55 +01:00
|
|
|
lower_variant(
|
2019-08-13 21:40:21 -03:00
|
|
|
tcx,
|
2022-11-06 19:46:55 +00:00
|
|
|
Some(v.def_id),
|
2019-08-13 21:40:21 -03:00
|
|
|
v.ident,
|
|
|
|
|
discr,
|
|
|
|
|
&v.data,
|
|
|
|
|
AdtKind::Enum,
|
|
|
|
|
def_id,
|
|
|
|
|
)
|
2019-03-21 23:38:50 +01:00
|
|
|
})
|
|
|
|
|
.collect();
|
2017-02-14 01:11:24 +02:00
|
|
|
|
2019-03-21 23:38:50 +01:00
|
|
|
(AdtKind::Enum, variants)
|
2017-02-14 01:11:24 +02:00
|
|
|
}
|
2025-05-28 15:18:48 +10:00
|
|
|
ItemKind::Struct(ident, _, def) | ItemKind::Union(ident, _, def) => {
|
2022-10-25 20:15:15 +04:00
|
|
|
let adt_kind = match item.kind {
|
|
|
|
|
ItemKind::Struct(..) => AdtKind::Struct,
|
|
|
|
|
_ => AdtKind::Union,
|
|
|
|
|
};
|
2024-03-15 03:21:55 +01:00
|
|
|
let variants = std::iter::once(lower_variant(
|
2019-03-21 23:38:50 +01:00
|
|
|
tcx,
|
2022-11-06 19:46:55 +00:00
|
|
|
None,
|
Move `hir::Item::ident` into `hir::ItemKind`.
`hir::Item` has an `ident` field.
- It's always non-empty for these item kinds: `ExternCrate`, `Static`,
`Const`, `Fn`, `Macro`, `Mod`, `TyAlias`, `Enum`, `Struct`, `Union`,
Trait`, TraitAalis`.
- It's always empty for these item kinds: `ForeignMod`, `GlobalAsm`,
`Impl`.
- For `Use`, it is non-empty for `UseKind::Single` and empty for
`UseKind::{Glob,ListStem}`.
All of this is quite non-obvious; the only documentation is a single
comment saying "The name might be a dummy name in case of anonymous
items". Some sites that handle items check for an empty ident, some
don't. This is a very C-like way of doing things, but this is Rust, we
have sum types, we can do this properly and never forget to check for
the exceptional case and never YOLO possibly empty identifiers (or
possibly dummy spans) around and hope that things will work out.
The commit is large but it's mostly obvious plumbing work. Some notable
things.
- A similar transformation makes sense for `ast::Item`, but this is
already a big change. That can be done later.
- Lots of assertions are added to item lowering to ensure that
identifiers are empty/non-empty as expected. These will be removable
when `ast::Item` is done later.
- `ItemKind::Use` doesn't get an `Ident`, but `UseKind::Single` does.
- `lower_use_tree` is significantly simpler. No more confusing `&mut
Ident` to deal with.
- `ItemKind::ident` is a new method, it returns an `Option<Ident>`. It's
used with `unwrap` in a few places; sometimes it's hard to tell
exactly which item kinds might occur. None of these unwraps fail on
the test suite. It's conceivable that some might fail on alternative
input. We can deal with those if/when they happen.
- In `trait_path` the `find_map`/`if let` is replaced with a loop, and
things end up much clearer that way.
- `named_span` no longer checks for an empty name; instead the call site
now checks for a missing identifier if necessary.
- `maybe_inline_local` doesn't need the `glob` argument, it can be
computed in-function from the `renamed` argument.
- `arbitrary_source_item_ordering::check_mod` had a big `if` statement
that was just getting the ident from the item kinds that had one. It
could be mostly replaced by a single call to the new `ItemKind::ident`
method.
- `ItemKind` grows from 56 to 64 bytes, but `Item` stays the same size,
and that's what matters, because `ItemKind` only occurs within `Item`.
2025-03-06 19:07:36 +11:00
|
|
|
*ident,
|
2019-03-21 23:38:50 +01:00
|
|
|
ty::VariantDiscr::Relative(0),
|
|
|
|
|
def,
|
2022-10-25 20:15:15 +04:00
|
|
|
adt_kind,
|
2019-03-21 23:38:50 +01:00
|
|
|
def_id,
|
|
|
|
|
))
|
|
|
|
|
.collect();
|
|
|
|
|
|
2022-10-25 20:15:15 +04:00
|
|
|
(adt_kind, variants)
|
2019-03-21 23:38:50 +01:00
|
|
|
}
|
2023-12-15 03:19:46 +00:00
|
|
|
_ => bug!("{:?} is not an ADT", item.owner_id.def_id),
|
2017-02-14 01:11:24 +02:00
|
|
|
};
|
2024-09-29 22:10:16 -04:00
|
|
|
tcx.mk_adt_def(def_id.to_def_id(), kind, variants, repr)
|
2016-08-09 01:18:47 +03:00
|
|
|
}
|
|
|
|
|
|
2023-03-13 18:54:05 +00:00
|
|
|
fn trait_def(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::TraitDef {
|
2025-02-21 18:33:05 +11:00
|
|
|
let item = tcx.hir_expect_item(def_id);
|
2015-02-11 10:25:52 -05:00
|
|
|
|
2024-07-25 00:32:50 -04:00
|
|
|
let (is_alias, is_auto, safety, items) = match item.kind {
|
2024-05-17 14:17:48 -03:00
|
|
|
hir::ItemKind::Trait(is_auto, safety, .., items) => {
|
2024-07-25 00:32:50 -04:00
|
|
|
(false, is_auto == hir::IsAuto::Yes, safety, items)
|
2021-12-21 18:40:50 +03:00
|
|
|
}
|
2024-07-25 00:32:50 -04:00
|
|
|
hir::ItemKind::TraitAlias(..) => (true, false, hir::Safety::Safe, &[][..]),
|
2017-02-14 01:11:24 +02:00
|
|
|
_ => span_bug!(item.span, "trait_def_of_item invoked on non-trait"),
|
|
|
|
|
};
|
2013-12-18 16:05:47 -08:00
|
|
|
|
2024-07-25 00:32:50 -04:00
|
|
|
// Only regular traits can be const.
|
|
|
|
|
let constness = if !is_alias && tcx.has_attr(def_id, sym::const_trait) {
|
2024-07-01 08:36:28 +00:00
|
|
|
hir::Constness::Const
|
|
|
|
|
} else {
|
|
|
|
|
hir::Constness::NotConst
|
|
|
|
|
};
|
2024-07-25 00:32:50 -04:00
|
|
|
|
2019-05-08 13:21:18 +10:00
|
|
|
let paren_sugar = tcx.has_attr(def_id, sym::rustc_paren_sugar);
|
2024-10-09 09:01:57 +02:00
|
|
|
if paren_sugar && !tcx.features().unboxed_closures() {
|
2023-12-18 22:21:37 +11:00
|
|
|
tcx.dcx().emit_err(errors::ParenSugarAttribute { span: item.span });
|
2017-02-14 01:11:24 +02:00
|
|
|
}
|
2016-09-12 18:09:49 -04:00
|
|
|
|
2024-07-25 00:32:50 -04:00
|
|
|
// Only regular traits can be marker.
|
|
|
|
|
let is_marker = !is_alias && tcx.has_attr(def_id, sym::marker);
|
|
|
|
|
|
2023-02-14 10:17:19 +01:00
|
|
|
let rustc_coinductive = tcx.has_attr(def_id, sym::rustc_coinductive);
|
2024-07-06 18:16:02 -04:00
|
|
|
let is_fundamental = tcx.has_attr(def_id, sym::fundamental);
|
2024-04-17 16:32:17 -04:00
|
|
|
|
|
|
|
|
// FIXME: We could probably do way better attribute validation here.
|
|
|
|
|
let mut skip_array_during_method_dispatch = false;
|
|
|
|
|
let mut skip_boxed_slice_during_method_dispatch = false;
|
|
|
|
|
for attr in tcx.get_attrs(def_id, sym::rustc_skip_during_method_dispatch) {
|
|
|
|
|
if let Some(lst) = attr.meta_item_list() {
|
|
|
|
|
for item in lst {
|
|
|
|
|
if let Some(ident) = item.ident() {
|
|
|
|
|
match ident.as_str() {
|
|
|
|
|
"array" => skip_array_during_method_dispatch = true,
|
|
|
|
|
"boxed_slice" => skip_boxed_slice_during_method_dispatch = true,
|
|
|
|
|
_ => (),
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2023-02-14 10:17:19 +01:00
|
|
|
let specialization_kind = if tcx.has_attr(def_id, sym::rustc_unsafe_specialization_marker) {
|
2020-02-08 17:56:25 +00:00
|
|
|
ty::trait_def::TraitSpecializationKind::Marker
|
|
|
|
|
} else if tcx.has_attr(def_id, sym::rustc_specialization_trait) {
|
|
|
|
|
ty::trait_def::TraitSpecializationKind::AlwaysApplicable
|
|
|
|
|
} else {
|
|
|
|
|
ty::trait_def::TraitSpecializationKind::None
|
|
|
|
|
};
|
2021-12-21 18:40:50 +03:00
|
|
|
let must_implement_one_of = tcx
|
2022-05-02 09:31:56 +02:00
|
|
|
.get_attr(def_id, sym::rustc_must_implement_one_of)
|
2021-12-21 18:40:50 +03:00
|
|
|
// Check that there are at least 2 arguments of `#[rustc_must_implement_one_of]`
|
|
|
|
|
// and that they are all identifiers
|
|
|
|
|
.and_then(|attr| match attr.meta_item_list() {
|
|
|
|
|
Some(items) if items.len() < 2 => {
|
2025-02-09 22:49:28 +01:00
|
|
|
tcx.dcx().emit_err(errors::MustImplementOneOfAttribute { span: attr.span() });
|
2021-12-21 18:40:50 +03:00
|
|
|
|
|
|
|
|
None
|
|
|
|
|
}
|
|
|
|
|
Some(items) => items
|
|
|
|
|
.into_iter()
|
|
|
|
|
.map(|item| item.ident().ok_or(item.span()))
|
|
|
|
|
.collect::<Result<Box<[_]>, _>>()
|
|
|
|
|
.map_err(|span| {
|
2023-12-18 22:21:37 +11:00
|
|
|
tcx.dcx().emit_err(errors::MustBeNameOfAssociatedFunction { span });
|
2021-12-21 18:40:50 +03:00
|
|
|
})
|
|
|
|
|
.ok()
|
2025-02-09 22:49:28 +01:00
|
|
|
.zip(Some(attr.span())),
|
2021-12-21 18:40:50 +03:00
|
|
|
// Error is reported by `rustc_attr!`
|
|
|
|
|
None => None,
|
|
|
|
|
})
|
|
|
|
|
// Check that all arguments of `#[rustc_must_implement_one_of]` reference
|
2022-01-04 13:21:56 +03:00
|
|
|
// functions in the trait with default implementations
|
2021-12-21 18:40:50 +03:00
|
|
|
.and_then(|(list, attr_span)| {
|
|
|
|
|
let errors = list.iter().filter_map(|ident| {
|
|
|
|
|
let item = items.iter().find(|item| item.ident == *ident);
|
|
|
|
|
|
|
|
|
|
match item {
|
|
|
|
|
Some(item) if matches!(item.kind, hir::AssocItemKind::Fn { .. }) => {
|
2023-06-01 06:14:06 +00:00
|
|
|
if !tcx.defaultness(item.id.owner_id).has_value() {
|
2023-12-18 22:21:37 +11:00
|
|
|
tcx.dcx().emit_err(errors::FunctionNotHaveDefaultImplementation {
|
2023-04-07 02:04:42 +03:00
|
|
|
span: item.span,
|
|
|
|
|
note_span: attr_span,
|
|
|
|
|
});
|
2021-12-21 18:40:50 +03:00
|
|
|
|
|
|
|
|
return Some(());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return None;
|
|
|
|
|
}
|
2022-01-27 09:44:25 +00:00
|
|
|
Some(item) => {
|
2023-12-18 22:21:37 +11:00
|
|
|
tcx.dcx().emit_err(errors::MustImplementNotFunction {
|
2023-04-07 02:04:42 +03:00
|
|
|
span: item.span,
|
|
|
|
|
span_note: errors::MustImplementNotFunctionSpanNote { span: attr_span },
|
|
|
|
|
note: errors::MustImplementNotFunctionNote {},
|
|
|
|
|
});
|
2022-01-27 09:44:25 +00:00
|
|
|
}
|
|
|
|
|
None => {
|
2023-12-18 22:21:37 +11:00
|
|
|
tcx.dcx().emit_err(errors::FunctionNotFoundInTrait { span: ident.span });
|
2022-01-27 09:44:25 +00:00
|
|
|
}
|
2021-12-21 18:40:50 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Some(())
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
(errors.count() == 0).then_some(list)
|
2022-01-14 16:38:47 +03:00
|
|
|
})
|
|
|
|
|
// Check for duplicates
|
|
|
|
|
.and_then(|list| {
|
2023-12-21 10:52:27 +01:00
|
|
|
let mut set: UnordMap<Symbol, Span> = Default::default();
|
2022-01-14 16:38:47 +03:00
|
|
|
let mut no_dups = true;
|
|
|
|
|
|
|
|
|
|
for ident in &*list {
|
2022-01-15 02:04:58 +03:00
|
|
|
if let Some(dup) = set.insert(ident.name, ident.span) {
|
2023-12-18 22:21:37 +11:00
|
|
|
tcx.dcx()
|
2023-04-07 02:04:42 +03:00
|
|
|
.emit_err(errors::FunctionNamesDuplicated { spans: vec![dup, ident.span] });
|
2022-01-14 16:38:47 +03:00
|
|
|
|
|
|
|
|
no_dups = false;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
no_dups.then_some(list)
|
2021-12-21 18:40:50 +03:00
|
|
|
});
|
|
|
|
|
|
2024-12-20 16:57:14 +01:00
|
|
|
let deny_explicit_impl = tcx.has_attr(def_id, sym::rustc_deny_explicit_impl);
|
|
|
|
|
let implement_via_object = !tcx.has_attr(def_id, sym::rustc_do_not_implement_via_object);
|
2021-12-21 18:40:50 +03:00
|
|
|
|
2023-02-14 10:17:19 +01:00
|
|
|
ty::TraitDef {
|
2023-03-13 18:54:05 +00:00
|
|
|
def_id: def_id.to_def_id(),
|
2024-05-17 14:17:48 -03:00
|
|
|
safety,
|
2024-07-01 08:36:28 +00:00
|
|
|
constness,
|
2021-04-12 16:03:53 -07:00
|
|
|
paren_sugar,
|
2023-02-14 10:17:19 +01:00
|
|
|
has_auto_impl: is_auto,
|
2021-04-12 16:03:53 -07:00
|
|
|
is_marker,
|
2023-02-14 10:17:19 +01:00
|
|
|
is_coinductive: rustc_coinductive || is_auto,
|
2024-07-06 18:16:02 -04:00
|
|
|
is_fundamental,
|
2021-04-12 16:03:53 -07:00
|
|
|
skip_array_during_method_dispatch,
|
2024-04-17 16:32:17 -04:00
|
|
|
skip_boxed_slice_during_method_dispatch,
|
2023-02-14 10:17:19 +01:00
|
|
|
specialization_kind,
|
2021-12-21 18:40:50 +03:00
|
|
|
must_implement_one_of,
|
2023-06-13 22:31:25 +00:00
|
|
|
implement_via_object,
|
|
|
|
|
deny_explicit_impl,
|
2023-02-14 10:17:19 +01:00
|
|
|
}
|
2012-05-15 19:36:04 -07:00
|
|
|
}
|
|
|
|
|
|
2024-08-20 00:48:43 +00:00
|
|
|
#[instrument(level = "debug", skip(tcx), ret)]
|
2024-05-26 20:03:47 -04:00
|
|
|
fn fn_sig(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::EarlyBinder<'_, ty::PolyFnSig<'_>> {
|
2020-01-05 02:37:57 +01:00
|
|
|
use rustc_hir::Node::*;
|
|
|
|
|
use rustc_hir::*;
|
2017-05-13 17:11:52 +03:00
|
|
|
|
2023-11-24 19:28:19 +03:00
|
|
|
let hir_id = tcx.local_def_id_to_hir_id(def_id);
|
2017-05-13 17:11:52 +03:00
|
|
|
|
2023-03-13 19:06:41 +00:00
|
|
|
let icx = ItemCtxt::new(tcx, def_id);
|
2017-05-13 17:11:52 +03:00
|
|
|
|
2023-12-01 05:28:34 -08:00
|
|
|
let output = match tcx.hir_node(hir_id) {
|
2018-08-22 23:05:26 +01:00
|
|
|
TraitItem(hir::TraitItem {
|
2020-03-05 09:57:34 -06:00
|
|
|
kind: TraitItemKind::Fn(sig, TraitFn::Provided(_)),
|
2019-12-23 14:16:34 -08:00
|
|
|
generics,
|
2018-08-19 12:34:21 -04:00
|
|
|
..
|
|
|
|
|
})
|
2025-01-04 11:30:31 +01:00
|
|
|
| Item(hir::Item { kind: ItemKind::Fn { sig, generics, .. }, .. }) => {
|
2024-12-13 15:10:58 +00:00
|
|
|
lower_fn_sig_recovering_infer_ret_ty(&icx, sig, generics, def_id)
|
2022-03-27 19:43:08 -07:00
|
|
|
}
|
2021-02-24 12:21:18 -08:00
|
|
|
|
2022-02-07 22:58:30 +01:00
|
|
|
ImplItem(hir::ImplItem { kind: ImplItemKind::Fn(sig, _), generics, .. }) => {
|
2022-10-20 09:39:09 +00:00
|
|
|
// Do not try to infer the return type for a impl method coming from a trait
|
2024-02-09 23:58:36 +03:00
|
|
|
if let Item(hir::Item { kind: ItemKind::Impl(i), .. }) = tcx.parent_hir_node(hir_id)
|
2022-03-27 19:43:08 -07:00
|
|
|
&& i.of_trait.is_some()
|
|
|
|
|
{
|
2024-03-15 03:21:55 +01:00
|
|
|
icx.lowerer().lower_fn_ty(
|
2020-10-26 14:18:31 -04:00
|
|
|
hir_id,
|
2024-12-13 12:19:46 +00:00
|
|
|
sig.header.safety(),
|
2019-12-23 14:16:34 -08:00
|
|
|
sig.header.abi,
|
2021-09-30 19:38:50 +02:00
|
|
|
sig.decl,
|
2022-02-07 22:58:30 +01:00
|
|
|
Some(generics),
|
2021-02-10 15:49:23 +00:00
|
|
|
None,
|
2022-03-27 19:43:08 -07:00
|
|
|
)
|
|
|
|
|
} else {
|
2024-12-13 15:10:58 +00:00
|
|
|
lower_fn_sig_recovering_infer_ret_ty(&icx, sig, generics, def_id)
|
2019-12-22 17:42:04 -05:00
|
|
|
}
|
2019-07-15 19:30:48 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
TraitItem(hir::TraitItem {
|
2020-08-12 17:02:14 -04:00
|
|
|
kind: TraitItemKind::Fn(FnSig { header, decl, span: _ }, _),
|
2019-12-23 14:16:34 -08:00
|
|
|
generics,
|
2019-07-15 19:30:48 +03:00
|
|
|
..
|
2024-12-13 12:19:46 +00:00
|
|
|
}) => icx.lowerer().lower_fn_ty(
|
|
|
|
|
hir_id,
|
|
|
|
|
header.safety(),
|
|
|
|
|
header.abi,
|
|
|
|
|
decl,
|
|
|
|
|
Some(generics),
|
|
|
|
|
None,
|
|
|
|
|
),
|
2018-08-19 12:34:21 -04:00
|
|
|
|
2024-08-07 13:01:34 -04:00
|
|
|
ForeignItem(&hir::ForeignItem { kind: ForeignItemKind::Fn(sig, _, _), .. }) => {
|
2025-02-21 18:33:05 +11:00
|
|
|
let abi = tcx.hir_get_foreign_abi(hir_id);
|
2024-12-13 12:19:46 +00:00
|
|
|
compute_sig_of_foreign_fn_decl(tcx, def_id, sig.decl, abi, sig.header.safety())
|
2017-05-13 17:11:52 +03:00
|
|
|
}
|
|
|
|
|
|
2025-04-07 18:06:21 +00:00
|
|
|
Ctor(data) => {
|
|
|
|
|
assert_matches!(data.ctor(), Some(_));
|
2025-02-21 07:54:35 +11:00
|
|
|
let adt_def_id = tcx.hir_get_parent_item(hir_id).def_id.to_def_id();
|
2023-08-27 21:04:34 +00:00
|
|
|
let ty = tcx.type_of(adt_def_id).instantiate_identity();
|
2023-07-11 22:35:29 +01:00
|
|
|
let inputs = data.fields().iter().map(|f| tcx.type_of(f.def_id).instantiate_identity());
|
2023-08-27 21:04:34 +00:00
|
|
|
// constructors for structs with `layout_scalar_valid_range` are unsafe to call
|
|
|
|
|
let safety = match tcx.layout_scalar_valid_range(adt_def_id) {
|
2024-05-17 14:17:48 -03:00
|
|
|
(Bound::Unbounded, Bound::Unbounded) => hir::Safety::Safe,
|
|
|
|
|
_ => hir::Safety::Unsafe,
|
2023-08-27 21:04:34 +00:00
|
|
|
};
|
2024-11-02 19:32:56 -07:00
|
|
|
ty::Binder::dummy(tcx.mk_fn_sig(inputs, ty, false, safety, ExternAbi::Rust))
|
2017-05-13 17:11:52 +03:00
|
|
|
}
|
|
|
|
|
|
2022-06-11 21:25:25 +02:00
|
|
|
Expr(&hir::Expr { kind: hir::ExprKind::Closure { .. }, .. }) => {
|
2017-12-06 15:15:27 -05:00
|
|
|
// Closure signatures are not like other function
|
|
|
|
|
// signatures and cannot be accessed through `fn_sig`. For
|
|
|
|
|
// example, a closure signature excludes the `self`
|
|
|
|
|
// argument. In any case they are embedded within the
|
2023-07-11 22:35:29 +01:00
|
|
|
// closure type as part of the `ClosureArgs`.
|
2017-12-01 09:26:13 -05:00
|
|
|
//
|
2020-03-18 02:16:01 +02:00
|
|
|
// To get the signature of a closure, you should use the
|
2023-07-11 22:35:29 +01:00
|
|
|
// `sig` method on the `ClosureArgs`:
|
2017-12-01 09:26:13 -05:00
|
|
|
//
|
2023-07-11 22:35:29 +01:00
|
|
|
// args.as_closure().sig(def_id, tcx)
|
|
|
|
|
bug!("to get the signature of a closure, use `args.as_closure().sig()` not `fn_sig()`",);
|
2017-05-13 17:11:52 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
x => {
|
|
|
|
|
bug!("unexpected sort of node in fn_sig(): {:?}", x);
|
|
|
|
|
}
|
2023-01-18 16:52:47 -07:00
|
|
|
};
|
2023-05-29 13:46:10 +02:00
|
|
|
ty::EarlyBinder::bind(output)
|
2017-05-13 17:11:52 +03:00
|
|
|
}
|
|
|
|
|
|
2024-12-13 15:10:58 +00:00
|
|
|
fn lower_fn_sig_recovering_infer_ret_ty<'tcx>(
|
|
|
|
|
icx: &ItemCtxt<'tcx>,
|
|
|
|
|
sig: &'tcx hir::FnSig<'tcx>,
|
|
|
|
|
generics: &'tcx hir::Generics<'tcx>,
|
2022-03-27 19:43:08 -07:00
|
|
|
def_id: LocalDefId,
|
2024-12-13 15:10:58 +00:00
|
|
|
) -> ty::PolyFnSig<'tcx> {
|
2025-01-02 18:19:46 +00:00
|
|
|
if let Some(infer_ret_ty) = sig.decl.output.is_suggestable_infer_ty() {
|
2024-12-13 15:10:58 +00:00
|
|
|
return recover_infer_ret_ty(icx, infer_ret_ty, generics, def_id);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
icx.lowerer().lower_fn_ty(
|
|
|
|
|
icx.tcx().local_def_id_to_hir_id(def_id),
|
2024-12-13 12:19:46 +00:00
|
|
|
sig.header.safety(),
|
2024-12-13 15:10:58 +00:00
|
|
|
sig.header.abi,
|
|
|
|
|
sig.decl,
|
|
|
|
|
Some(generics),
|
|
|
|
|
None,
|
|
|
|
|
)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn recover_infer_ret_ty<'tcx>(
|
2022-03-27 19:43:08 -07:00
|
|
|
icx: &ItemCtxt<'tcx>,
|
2024-12-13 15:10:58 +00:00
|
|
|
infer_ret_ty: &'tcx hir::Ty<'tcx>,
|
|
|
|
|
generics: &'tcx hir::Generics<'tcx>,
|
|
|
|
|
def_id: LocalDefId,
|
2022-03-27 19:43:08 -07:00
|
|
|
) -> ty::PolyFnSig<'tcx> {
|
2024-07-05 10:05:58 +00:00
|
|
|
let tcx = icx.tcx;
|
2023-11-24 19:28:19 +03:00
|
|
|
let hir_id = tcx.local_def_id_to_hir_id(def_id);
|
2022-03-27 19:43:08 -07:00
|
|
|
|
2024-12-13 15:10:58 +00:00
|
|
|
let fn_sig = tcx.typeck(def_id).liberated_fn_sigs()[hir_id];
|
|
|
|
|
|
|
|
|
|
// Typeck doesn't expect erased regions to be returned from `type_of`.
|
|
|
|
|
// This is a heuristic approach. If the scope has region parameters,
|
|
|
|
|
// we should change fn_sig's lifetime from `ReErased` to `ReError`,
|
|
|
|
|
// otherwise to `ReStatic`.
|
|
|
|
|
let has_region_params = generics.params.iter().any(|param| match param.kind {
|
|
|
|
|
GenericParamKind::Lifetime { .. } => true,
|
|
|
|
|
_ => false,
|
|
|
|
|
});
|
2025-04-08 10:51:41 +08:00
|
|
|
let fn_sig = fold_regions(tcx, fn_sig, |r, _| match r.kind() {
|
2024-12-13 15:10:58 +00:00
|
|
|
ty::ReErased => {
|
|
|
|
|
if has_region_params {
|
|
|
|
|
ty::Region::new_error_with_message(
|
|
|
|
|
tcx,
|
|
|
|
|
DUMMY_SP,
|
|
|
|
|
"erased region is not allowed here in return type",
|
|
|
|
|
)
|
|
|
|
|
} else {
|
|
|
|
|
tcx.lifetimes.re_static
|
2022-03-27 19:43:08 -07:00
|
|
|
}
|
|
|
|
|
}
|
2024-12-13 15:10:58 +00:00
|
|
|
_ => r,
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
let mut visitor = HirPlaceholderCollector::default();
|
2025-01-18 22:45:41 +00:00
|
|
|
visitor.visit_ty_unambig(infer_ret_ty);
|
2024-12-13 15:10:58 +00:00
|
|
|
|
2025-01-02 19:08:12 +00:00
|
|
|
let mut diag = bad_placeholder(icx.lowerer(), visitor.spans, "return type");
|
2024-12-13 15:10:58 +00:00
|
|
|
let ret_ty = fn_sig.output();
|
|
|
|
|
|
|
|
|
|
// Don't leak types into signatures unless they're nameable!
|
|
|
|
|
// For example, if a function returns itself, we don't want that
|
|
|
|
|
// recursive function definition to leak out into the fn sig.
|
|
|
|
|
let mut recovered_ret_ty = None;
|
|
|
|
|
if let Some(suggestable_ret_ty) = ret_ty.make_suggestable(tcx, false, None) {
|
|
|
|
|
diag.span_suggestion(
|
|
|
|
|
infer_ret_ty.span,
|
|
|
|
|
"replace with the correct return type",
|
|
|
|
|
suggestable_ret_ty,
|
|
|
|
|
Applicability::MachineApplicable,
|
|
|
|
|
);
|
|
|
|
|
recovered_ret_ty = Some(suggestable_ret_ty);
|
|
|
|
|
} else if let Some(sugg) = suggest_impl_trait(
|
|
|
|
|
&tcx.infer_ctxt().build(TypingMode::non_body_analysis()),
|
|
|
|
|
tcx.param_env(def_id),
|
|
|
|
|
ret_ty,
|
|
|
|
|
) {
|
|
|
|
|
diag.span_suggestion(
|
|
|
|
|
infer_ret_ty.span,
|
|
|
|
|
"replace with an appropriate return type",
|
|
|
|
|
sugg,
|
|
|
|
|
Applicability::MachineApplicable,
|
|
|
|
|
);
|
|
|
|
|
} else if ret_ty.is_closure() {
|
|
|
|
|
diag.help("consider using an `Fn`, `FnMut`, or `FnOnce` trait bound");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Also note how `Fn` traits work just in case!
|
|
|
|
|
if ret_ty.is_closure() {
|
|
|
|
|
diag.note(
|
|
|
|
|
"for more information on `Fn` traits and closure types, see \
|
|
|
|
|
https://doc.rust-lang.org/book/ch13-01-closures.html",
|
|
|
|
|
);
|
2022-03-27 19:43:08 -07:00
|
|
|
}
|
2024-12-13 15:10:58 +00:00
|
|
|
let guar = diag.emit();
|
|
|
|
|
ty::Binder::dummy(tcx.mk_fn_sig(
|
|
|
|
|
fn_sig.inputs().iter().copied(),
|
|
|
|
|
recovered_ret_ty.unwrap_or_else(|| Ty::new_error(tcx, guar)),
|
|
|
|
|
fn_sig.c_variadic,
|
|
|
|
|
fn_sig.safety,
|
|
|
|
|
fn_sig.abi,
|
|
|
|
|
))
|
2022-03-27 19:43:08 -07:00
|
|
|
}
|
|
|
|
|
|
2024-04-10 18:42:48 -04:00
|
|
|
pub fn suggest_impl_trait<'tcx>(
|
|
|
|
|
infcx: &InferCtxt<'tcx>,
|
|
|
|
|
param_env: ty::ParamEnv<'tcx>,
|
2022-12-26 17:44:16 -08:00
|
|
|
ret_ty: Ty<'tcx>,
|
2022-12-27 23:56:46 +00:00
|
|
|
) -> Option<String> {
|
|
|
|
|
let format_as_assoc: fn(_, _, _, _, _) -> _ =
|
|
|
|
|
|tcx: TyCtxt<'tcx>,
|
2023-07-11 22:35:29 +01:00
|
|
|
_: ty::GenericArgsRef<'tcx>,
|
2022-12-27 23:56:46 +00:00
|
|
|
trait_def_id: DefId,
|
|
|
|
|
assoc_item_def_id: DefId,
|
|
|
|
|
item_ty: Ty<'tcx>| {
|
|
|
|
|
let trait_name = tcx.item_name(trait_def_id);
|
|
|
|
|
let assoc_name = tcx.item_name(assoc_item_def_id);
|
|
|
|
|
Some(format!("impl {trait_name}<{assoc_name} = {item_ty}>"))
|
|
|
|
|
};
|
|
|
|
|
let format_as_parenthesized: fn(_, _, _, _, _) -> _ =
|
|
|
|
|
|tcx: TyCtxt<'tcx>,
|
2023-07-11 22:35:29 +01:00
|
|
|
args: ty::GenericArgsRef<'tcx>,
|
2022-12-27 23:56:46 +00:00
|
|
|
trait_def_id: DefId,
|
|
|
|
|
_: DefId,
|
|
|
|
|
item_ty: Ty<'tcx>| {
|
|
|
|
|
let trait_name = tcx.item_name(trait_def_id);
|
2023-07-11 22:35:29 +01:00
|
|
|
let args_tuple = args.type_at(1);
|
2022-12-27 23:56:46 +00:00
|
|
|
let ty::Tuple(types) = *args_tuple.kind() else {
|
|
|
|
|
return None;
|
|
|
|
|
};
|
2024-03-20 22:50:32 +00:00
|
|
|
let types = types.make_suggestable(tcx, false, None)?;
|
2022-12-27 23:56:46 +00:00
|
|
|
let maybe_ret =
|
|
|
|
|
if item_ty.is_unit() { String::new() } else { format!(" -> {item_ty}") };
|
|
|
|
|
Some(format!(
|
|
|
|
|
"impl {trait_name}({}){maybe_ret}",
|
|
|
|
|
types.iter().map(|ty| ty.to_string()).collect::<Vec<_>>().join(", ")
|
|
|
|
|
))
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
for (trait_def_id, assoc_item_def_id, formatter) in [
|
|
|
|
|
(
|
2024-04-10 18:42:48 -04:00
|
|
|
infcx.tcx.get_diagnostic_item(sym::Iterator),
|
|
|
|
|
infcx.tcx.get_diagnostic_item(sym::IteratorItem),
|
2022-12-27 23:56:46 +00:00
|
|
|
format_as_assoc,
|
|
|
|
|
),
|
|
|
|
|
(
|
2024-04-10 18:42:48 -04:00
|
|
|
infcx.tcx.lang_items().future_trait(),
|
2024-05-29 14:22:56 -04:00
|
|
|
infcx.tcx.lang_items().future_output(),
|
2022-12-27 23:56:46 +00:00
|
|
|
format_as_assoc,
|
|
|
|
|
),
|
|
|
|
|
(
|
2024-04-10 18:42:48 -04:00
|
|
|
infcx.tcx.lang_items().fn_trait(),
|
|
|
|
|
infcx.tcx.lang_items().fn_once_output(),
|
|
|
|
|
format_as_parenthesized,
|
|
|
|
|
),
|
|
|
|
|
(
|
|
|
|
|
infcx.tcx.lang_items().fn_mut_trait(),
|
|
|
|
|
infcx.tcx.lang_items().fn_once_output(),
|
2022-12-27 23:56:46 +00:00
|
|
|
format_as_parenthesized,
|
|
|
|
|
),
|
|
|
|
|
(
|
2024-04-10 18:42:48 -04:00
|
|
|
infcx.tcx.lang_items().fn_once_trait(),
|
|
|
|
|
infcx.tcx.lang_items().fn_once_output(),
|
2022-12-27 23:56:46 +00:00
|
|
|
format_as_parenthesized,
|
|
|
|
|
),
|
|
|
|
|
] {
|
|
|
|
|
let Some(trait_def_id) = trait_def_id else {
|
|
|
|
|
continue;
|
|
|
|
|
};
|
|
|
|
|
let Some(assoc_item_def_id) = assoc_item_def_id else {
|
|
|
|
|
continue;
|
|
|
|
|
};
|
2024-04-10 18:42:48 -04:00
|
|
|
if infcx.tcx.def_kind(assoc_item_def_id) != DefKind::AssocTy {
|
2022-12-27 23:56:46 +00:00
|
|
|
continue;
|
|
|
|
|
}
|
2024-04-10 18:42:48 -04:00
|
|
|
let sugg = infcx.probe(|_| {
|
|
|
|
|
let args = ty::GenericArgs::for_item(infcx.tcx, trait_def_id, |param, _| {
|
|
|
|
|
if param.index == 0 { ret_ty.into() } else { infcx.var_for_def(DUMMY_SP, param) }
|
|
|
|
|
});
|
|
|
|
|
if !infcx
|
|
|
|
|
.type_implements_trait(trait_def_id, args, param_env)
|
|
|
|
|
.must_apply_modulo_regions()
|
|
|
|
|
{
|
|
|
|
|
return None;
|
|
|
|
|
}
|
|
|
|
|
let ocx = ObligationCtxt::new(&infcx);
|
|
|
|
|
let item_ty = ocx.normalize(
|
|
|
|
|
&ObligationCause::dummy(),
|
|
|
|
|
param_env,
|
2024-06-21 13:33:08 -04:00
|
|
|
Ty::new_projection_from_args(infcx.tcx, assoc_item_def_id, args),
|
2024-04-10 18:42:48 -04:00
|
|
|
);
|
|
|
|
|
// FIXME(compiler-errors): We may benefit from resolving regions here.
|
|
|
|
|
if ocx.select_where_possible().is_empty()
|
|
|
|
|
&& let item_ty = infcx.resolve_vars_if_possible(item_ty)
|
|
|
|
|
&& let Some(item_ty) = item_ty.make_suggestable(infcx.tcx, false, None)
|
|
|
|
|
&& let Some(sugg) = formatter(
|
|
|
|
|
infcx.tcx,
|
|
|
|
|
infcx.resolve_vars_if_possible(args),
|
|
|
|
|
trait_def_id,
|
|
|
|
|
assoc_item_def_id,
|
|
|
|
|
item_ty,
|
|
|
|
|
)
|
|
|
|
|
{
|
|
|
|
|
return Some(sugg);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
None
|
2022-12-27 23:56:46 +00:00
|
|
|
});
|
2024-04-10 18:42:48 -04:00
|
|
|
|
|
|
|
|
if sugg.is_some() {
|
|
|
|
|
return sugg;
|
2022-12-27 23:56:46 +00:00
|
|
|
}
|
2022-12-26 17:44:16 -08:00
|
|
|
}
|
|
|
|
|
None
|
|
|
|
|
}
|
|
|
|
|
|
2024-03-05 20:19:05 +01:00
|
|
|
fn impl_trait_header(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Option<ty::ImplTraitHeader<'_>> {
|
2023-03-13 19:06:41 +00:00
|
|
|
let icx = ItemCtxt::new(tcx, def_id);
|
2025-02-21 18:33:05 +11:00
|
|
|
let item = tcx.hir_expect_item(def_id);
|
2024-02-10 21:26:48 +00:00
|
|
|
let impl_ = item.expect_impl();
|
2024-06-14 12:16:15 +00:00
|
|
|
impl_.of_trait.as_ref().map(|ast_trait_ref| {
|
|
|
|
|
let selfty = tcx.type_of(def_id).instantiate_identity();
|
2023-08-06 17:00:26 +00:00
|
|
|
|
2024-12-10 10:12:36 +00:00
|
|
|
check_impl_constness(tcx, impl_.constness, ast_trait_ref);
|
2024-06-14 12:16:15 +00:00
|
|
|
|
|
|
|
|
let trait_ref = icx.lowerer().lower_impl_trait_ref(ast_trait_ref, selfty);
|
|
|
|
|
|
|
|
|
|
ty::ImplTraitHeader {
|
|
|
|
|
trait_ref: ty::EarlyBinder::bind(trait_ref),
|
|
|
|
|
safety: impl_.safety,
|
|
|
|
|
polarity: polarity_of_impl(tcx, def_id, impl_, item.span),
|
2024-12-10 10:12:36 +00:00
|
|
|
constness: impl_.constness,
|
2024-06-14 12:16:15 +00:00
|
|
|
}
|
|
|
|
|
})
|
2015-02-11 10:25:52 -05:00
|
|
|
}
|
|
|
|
|
|
2023-08-06 17:00:26 +00:00
|
|
|
fn check_impl_constness(
|
|
|
|
|
tcx: TyCtxt<'_>,
|
2024-12-10 10:12:36 +00:00
|
|
|
constness: hir::Constness,
|
2024-02-11 09:24:35 +01:00
|
|
|
hir_trait_ref: &hir::TraitRef<'_>,
|
2024-12-10 10:12:36 +00:00
|
|
|
) {
|
|
|
|
|
if let hir::Constness::NotConst = constness {
|
|
|
|
|
return;
|
2022-10-25 18:28:04 +00:00
|
|
|
}
|
2023-08-06 17:00:26 +00:00
|
|
|
|
2024-12-10 10:12:36 +00:00
|
|
|
let Some(trait_def_id) = hir_trait_ref.trait_def_id() else { return };
|
2024-07-01 08:36:28 +00:00
|
|
|
if tcx.is_const_trait(trait_def_id) {
|
2024-12-10 10:12:36 +00:00
|
|
|
return;
|
2023-08-06 17:00:26 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
let trait_name = tcx.item_name(trait_def_id).to_string();
|
2024-12-09 19:34:43 +00:00
|
|
|
let (local_trait_span, suggestion_pre) =
|
|
|
|
|
match (trait_def_id.is_local(), tcx.sess.is_nightly_build()) {
|
|
|
|
|
(true, true) => (
|
|
|
|
|
Some(tcx.def_span(trait_def_id).shrink_to_lo()),
|
|
|
|
|
if tcx.features().const_trait_impl() {
|
|
|
|
|
""
|
|
|
|
|
} else {
|
|
|
|
|
"enable `#![feature(const_trait_impl)]` in your crate and "
|
|
|
|
|
},
|
|
|
|
|
),
|
|
|
|
|
(false, _) | (_, false) => (None, ""),
|
|
|
|
|
};
|
2024-12-10 10:12:36 +00:00
|
|
|
tcx.dcx().emit_err(errors::ConstImplForNonConstTrait {
|
2024-02-11 09:24:35 +01:00
|
|
|
trait_ref_span: hir_trait_ref.path.span,
|
2023-08-06 17:00:26 +00:00
|
|
|
trait_name,
|
2024-12-09 19:34:43 +00:00
|
|
|
local_trait_span,
|
|
|
|
|
suggestion_pre,
|
2023-08-06 17:00:26 +00:00
|
|
|
marking: (),
|
|
|
|
|
adding: (),
|
2024-12-10 10:12:36 +00:00
|
|
|
});
|
2022-10-25 18:28:04 +00:00
|
|
|
}
|
|
|
|
|
|
2024-02-10 21:26:48 +00:00
|
|
|
fn polarity_of_impl(
|
|
|
|
|
tcx: TyCtxt<'_>,
|
|
|
|
|
def_id: LocalDefId,
|
|
|
|
|
impl_: &hir::Impl<'_>,
|
|
|
|
|
span: Span,
|
|
|
|
|
) -> ty::ImplPolarity {
|
2019-07-14 00:09:46 +03:00
|
|
|
let is_rustc_reservation = tcx.has_attr(def_id, sym::rustc_reservation_impl);
|
2024-02-10 21:26:48 +00:00
|
|
|
match &impl_ {
|
|
|
|
|
hir::Impl { polarity: hir::ImplPolarity::Negative(span), of_trait, .. } => {
|
2019-07-14 00:09:46 +03:00
|
|
|
if is_rustc_reservation {
|
2021-01-11 20:45:33 +01:00
|
|
|
let span = span.to(of_trait.as_ref().map_or(*span, |t| t.path.span));
|
2023-12-18 22:21:37 +11:00
|
|
|
tcx.dcx().span_err(span, "reservation impls can't be negative");
|
2019-07-14 00:09:46 +03:00
|
|
|
}
|
|
|
|
|
ty::ImplPolarity::Negative
|
|
|
|
|
}
|
2024-02-10 21:26:48 +00:00
|
|
|
hir::Impl { polarity: hir::ImplPolarity::Positive, of_trait: None, .. } => {
|
2019-07-14 00:09:46 +03:00
|
|
|
if is_rustc_reservation {
|
2024-02-10 21:26:48 +00:00
|
|
|
tcx.dcx().span_err(span, "reservation impls can't be inherent");
|
2019-07-14 00:09:46 +03:00
|
|
|
}
|
|
|
|
|
ty::ImplPolarity::Positive
|
|
|
|
|
}
|
2024-02-10 21:26:48 +00:00
|
|
|
hir::Impl { polarity: hir::ImplPolarity::Positive, of_trait: Some(_), .. } => {
|
2019-07-14 00:09:46 +03:00
|
|
|
if is_rustc_reservation {
|
|
|
|
|
ty::ImplPolarity::Reservation
|
|
|
|
|
} else {
|
|
|
|
|
ty::ImplPolarity::Positive
|
|
|
|
|
}
|
|
|
|
|
}
|
2017-04-20 20:37:02 +03:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2015-02-18 10:39:39 -05:00
|
|
|
/// Returns the early-bound lifetimes declared in this generics
|
2019-02-08 14:53:55 +01:00
|
|
|
/// listing. For anything other than fns/methods, this is just all
|
2015-02-18 10:39:39 -05:00
|
|
|
/// the lifetimes that are declared. For fns or methods, we have to
|
|
|
|
|
/// screen out those that do not appear in any where-clauses etc using
|
|
|
|
|
/// `resolve_lifetime::early_bound_lifetimes`.
|
2025-02-20 18:58:46 +00:00
|
|
|
fn early_bound_lifetimes_from_generics<'a, 'tcx>(
|
2019-06-14 00:48:52 +03:00
|
|
|
tcx: TyCtxt<'tcx>,
|
2019-12-01 16:08:58 +01:00
|
|
|
generics: &'a hir::Generics<'a>,
|
2025-02-20 18:58:46 +00:00
|
|
|
) -> impl Iterator<Item = &'a hir::GenericParam<'a>> {
|
2018-08-19 12:34:21 -04:00
|
|
|
generics.params.iter().filter(move |param| match param.kind {
|
2022-05-26 08:59:15 +02:00
|
|
|
GenericParamKind::Lifetime { .. } => !tcx.is_late_bound(param.hir_id),
|
2018-08-19 12:34:21 -04:00
|
|
|
_ => false,
|
|
|
|
|
})
|
2015-02-18 10:39:39 -05:00
|
|
|
}
|
|
|
|
|
|
2019-06-11 23:35:39 +03:00
|
|
|
fn compute_sig_of_foreign_fn_decl<'tcx>(
|
2019-06-14 00:48:52 +03:00
|
|
|
tcx: TyCtxt<'tcx>,
|
2023-03-13 19:06:41 +00:00
|
|
|
def_id: LocalDefId,
|
2019-12-01 16:08:58 +01:00
|
|
|
decl: &'tcx hir::FnDecl<'tcx>,
|
2024-11-02 19:32:56 -07:00
|
|
|
abi: ExternAbi,
|
2024-05-23 10:01:05 -03:00
|
|
|
safety: hir::Safety,
|
2018-08-19 12:34:21 -04:00
|
|
|
) -> ty::PolyFnSig<'tcx> {
|
2023-11-24 19:28:19 +03:00
|
|
|
let hir_id = tcx.local_def_id_to_hir_id(def_id);
|
2023-01-11 18:58:44 +00:00
|
|
|
let fty =
|
2024-05-17 14:17:48 -03:00
|
|
|
ItemCtxt::new(tcx, def_id).lowerer().lower_fn_ty(hir_id, safety, abi, decl, None, None);
|
2012-05-15 19:36:04 -07:00
|
|
|
|
2019-03-16 00:04:02 +00:00
|
|
|
// Feature gate SIMD types in FFI, since I am not sure that the
|
|
|
|
|
// ABIs are handled at all correctly. -huonw
|
2025-04-06 21:32:58 +02:00
|
|
|
if !tcx.features().simd_ffi() {
|
2024-02-11 09:24:35 +01:00
|
|
|
let check = |hir_ty: &hir::Ty<'_>, ty: Ty<'_>| {
|
2016-02-23 21:06:32 +02:00
|
|
|
if ty.is_simd() {
|
2020-03-24 02:44:41 +01:00
|
|
|
let snip = tcx
|
|
|
|
|
.sess
|
|
|
|
|
.source_map()
|
2024-02-11 09:24:35 +01:00
|
|
|
.span_to_snippet(hir_ty.span)
|
2023-07-25 23:17:39 +02:00
|
|
|
.map_or_else(|_| String::new(), |s| format!(" `{s}`"));
|
2024-02-11 09:24:35 +01:00
|
|
|
tcx.dcx().emit_err(errors::SIMDFFIHighlyExperimental { span: hir_ty.span, snip });
|
2016-02-23 21:06:32 +02:00
|
|
|
}
|
|
|
|
|
};
|
2021-03-08 15:32:41 -08:00
|
|
|
for (input, ty) in iter::zip(decl.inputs, fty.inputs().skip_binder()) {
|
Overhaul `TyS` and `Ty`.
Specifically, change `Ty` from this:
```
pub type Ty<'tcx> = &'tcx TyS<'tcx>;
```
to this
```
pub struct Ty<'tcx>(Interned<'tcx, TyS<'tcx>>);
```
There are two benefits to this.
- It's now a first class type, so we can define methods on it. This
means we can move a lot of methods away from `TyS`, leaving `TyS` as a
barely-used type, which is appropriate given that it's not meant to
be used directly.
- The uniqueness requirement is now explicit, via the `Interned` type.
E.g. the pointer-based `Eq` and `Hash` comes from `Interned`, rather
than via `TyS`, which wasn't obvious at all.
Much of this commit is boring churn. The interesting changes are in
these files:
- compiler/rustc_middle/src/arena.rs
- compiler/rustc_middle/src/mir/visit.rs
- compiler/rustc_middle/src/ty/context.rs
- compiler/rustc_middle/src/ty/mod.rs
Specifically:
- Most mentions of `TyS` are removed. It's very much a dumb struct now;
`Ty` has all the smarts.
- `TyS` now has `crate` visibility instead of `pub`.
- `TyS::make_for_test` is removed in favour of the static `BOOL_TY`,
which just works better with the new structure.
- The `Eq`/`Ord`/`Hash` impls are removed from `TyS`. `Interned`s impls
of `Eq`/`Hash` now suffice. `Ord` is now partly on `Interned`
(pointer-based, for the `Equal` case) and partly on `TyS`
(contents-based, for the other cases).
- There are many tedious sigil adjustments, i.e. adding or removing `*`
or `&`. They seem to be unavoidable.
2022-01-25 14:13:38 +11:00
|
|
|
check(input, *ty)
|
2016-02-23 21:06:32 +02:00
|
|
|
}
|
2023-01-09 16:30:40 +00:00
|
|
|
if let hir::FnRetTy::Return(ty) = decl.output {
|
2021-09-30 19:38:50 +02:00
|
|
|
check(ty, fty.output().skip_binder())
|
2016-02-23 21:06:32 +02:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2017-05-13 17:11:52 +03:00
|
|
|
fty
|
2012-05-15 19:36:04 -07:00
|
|
|
}
|
2017-04-14 10:51:22 -04:00
|
|
|
|
2023-10-19 21:46:28 +00:00
|
|
|
fn coroutine_kind(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Option<hir::CoroutineKind> {
|
2023-12-01 05:28:34 -08:00
|
|
|
match tcx.hir_node_by_def_id(def_id) {
|
2023-12-22 21:29:12 +00:00
|
|
|
Node::Expr(&hir::Expr {
|
|
|
|
|
kind:
|
|
|
|
|
hir::ExprKind::Closure(&rustc_hir::Closure {
|
2023-12-25 16:56:12 +00:00
|
|
|
kind: hir::ClosureKind::Coroutine(kind),
|
2023-12-22 21:29:12 +00:00
|
|
|
..
|
|
|
|
|
}),
|
2020-02-08 16:33:50 -06:00
|
|
|
..
|
2023-12-22 21:29:12 +00:00
|
|
|
}) => Some(kind),
|
2023-03-13 18:54:05 +00:00
|
|
|
_ => None,
|
2020-01-25 19:09:23 -06:00
|
|
|
}
|
|
|
|
|
}
|
2023-01-18 18:03:06 +00:00
|
|
|
|
2024-01-24 22:27:25 +00:00
|
|
|
fn coroutine_for_closure(tcx: TyCtxt<'_>, def_id: LocalDefId) -> DefId {
|
2024-01-25 19:17:21 +00:00
|
|
|
let &rustc_hir::Closure { kind: hir::ClosureKind::CoroutineClosure(_), body, .. } =
|
|
|
|
|
tcx.hir_node_by_def_id(def_id).expect_closure()
|
2024-01-24 22:27:25 +00:00
|
|
|
else {
|
|
|
|
|
bug!()
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
let &hir::Expr {
|
|
|
|
|
kind:
|
|
|
|
|
hir::ExprKind::Closure(&rustc_hir::Closure {
|
|
|
|
|
def_id,
|
|
|
|
|
kind: hir::ClosureKind::Coroutine(_),
|
|
|
|
|
..
|
|
|
|
|
}),
|
|
|
|
|
..
|
2025-02-03 10:45:49 +11:00
|
|
|
} = tcx.hir_body(body).value
|
2024-01-24 22:27:25 +00:00
|
|
|
else {
|
|
|
|
|
bug!()
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
def_id.to_def_id()
|
|
|
|
|
}
|
|
|
|
|
|
2024-10-02 23:16:31 -04:00
|
|
|
fn opaque_ty_origin<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> hir::OpaqueTyOrigin<DefId> {
|
|
|
|
|
match tcx.hir_node_by_def_id(def_id).expect_opaque_ty().origin {
|
|
|
|
|
hir::OpaqueTyOrigin::FnReturn { parent, in_trait_or_impl } => {
|
|
|
|
|
hir::OpaqueTyOrigin::FnReturn { parent: parent.to_def_id(), in_trait_or_impl }
|
|
|
|
|
}
|
|
|
|
|
hir::OpaqueTyOrigin::AsyncFn { parent, in_trait_or_impl } => {
|
|
|
|
|
hir::OpaqueTyOrigin::AsyncFn { parent: parent.to_def_id(), in_trait_or_impl }
|
|
|
|
|
}
|
|
|
|
|
hir::OpaqueTyOrigin::TyAlias { parent, in_assoc_ty } => {
|
|
|
|
|
hir::OpaqueTyOrigin::TyAlias { parent: parent.to_def_id(), in_assoc_ty }
|
|
|
|
|
}
|
|
|
|
|
}
|
2023-01-18 18:03:06 +00:00
|
|
|
}
|
2024-07-12 13:07:16 -04:00
|
|
|
|
|
|
|
|
fn rendered_precise_capturing_args<'tcx>(
|
|
|
|
|
tcx: TyCtxt<'tcx>,
|
|
|
|
|
def_id: LocalDefId,
|
2025-03-02 18:06:06 +09:00
|
|
|
) -> Option<&'tcx [PreciseCapturingArgKind<Symbol, Symbol>]> {
|
2024-07-12 13:07:16 -04:00
|
|
|
if let Some(ty::ImplTraitInTraitData::Trait { opaque_def_id, .. }) =
|
|
|
|
|
tcx.opt_rpitit_info(def_id.to_def_id())
|
|
|
|
|
{
|
|
|
|
|
return tcx.rendered_precise_capturing_args(opaque_def_id);
|
|
|
|
|
}
|
|
|
|
|
|
2024-08-09 20:43:30 -07:00
|
|
|
tcx.hir_node_by_def_id(def_id).expect_opaque_ty().bounds.iter().find_map(|bound| match bound {
|
|
|
|
|
hir::GenericBound::Use(args, ..) => {
|
2025-03-02 18:06:06 +09:00
|
|
|
Some(&*tcx.arena.alloc_from_iter(args.iter().map(|arg| match arg {
|
|
|
|
|
PreciseCapturingArgKind::Lifetime(_) => {
|
|
|
|
|
PreciseCapturingArgKind::Lifetime(arg.name())
|
|
|
|
|
}
|
|
|
|
|
PreciseCapturingArgKind::Param(_) => PreciseCapturingArgKind::Param(arg.name()),
|
|
|
|
|
})))
|
2024-08-09 20:43:30 -07:00
|
|
|
}
|
|
|
|
|
_ => None,
|
|
|
|
|
})
|
2024-07-12 13:07:16 -04:00
|
|
|
}
|
2024-11-19 05:01:59 +00:00
|
|
|
|
|
|
|
|
fn const_param_default<'tcx>(
|
|
|
|
|
tcx: TyCtxt<'tcx>,
|
|
|
|
|
def_id: LocalDefId,
|
|
|
|
|
) -> ty::EarlyBinder<'tcx, Const<'tcx>> {
|
|
|
|
|
let default_ct = match tcx.hir_node_by_def_id(def_id) {
|
|
|
|
|
hir::Node::GenericParam(hir::GenericParam {
|
|
|
|
|
kind: hir::GenericParamKind::Const { default: Some(ct), .. },
|
|
|
|
|
..
|
|
|
|
|
}) => ct,
|
|
|
|
|
_ => span_bug!(
|
|
|
|
|
tcx.def_span(def_id),
|
|
|
|
|
"`const_param_default` expected a generic parameter with a constant"
|
|
|
|
|
),
|
|
|
|
|
};
|
|
|
|
|
let icx = ItemCtxt::new(tcx, def_id);
|
2025-02-25 00:06:38 +00:00
|
|
|
let identity_args = ty::GenericArgs::identity_for_item(tcx, def_id);
|
|
|
|
|
let ct = icx
|
|
|
|
|
.lowerer()
|
|
|
|
|
.lower_const_arg(default_ct, FeedConstTy::Param(def_id.to_def_id(), identity_args));
|
2024-11-19 05:01:59 +00:00
|
|
|
ty::EarlyBinder::bind(ct)
|
|
|
|
|
}
|
2025-03-12 11:23:20 +00:00
|
|
|
|
|
|
|
|
fn anon_const_kind<'tcx>(tcx: TyCtxt<'tcx>, def: LocalDefId) -> ty::AnonConstKind {
|
|
|
|
|
let hir_id = tcx.local_def_id_to_hir_id(def);
|
|
|
|
|
let const_arg_id = tcx.parent_hir_id(hir_id);
|
|
|
|
|
match tcx.hir_node(const_arg_id) {
|
|
|
|
|
hir::Node::ConstArg(_) => {
|
|
|
|
|
if tcx.features().generic_const_exprs() {
|
2025-05-01 16:22:31 +01:00
|
|
|
ty::AnonConstKind::GCE
|
2025-03-12 11:23:20 +00:00
|
|
|
} else if tcx.features().min_generic_const_args() {
|
2025-05-01 16:22:31 +01:00
|
|
|
ty::AnonConstKind::MCG
|
2025-03-12 11:23:20 +00:00
|
|
|
} else if let hir::Node::Expr(hir::Expr {
|
|
|
|
|
kind: hir::ExprKind::Repeat(_, repeat_count),
|
|
|
|
|
..
|
|
|
|
|
}) = tcx.hir_node(tcx.parent_hir_id(const_arg_id))
|
|
|
|
|
&& repeat_count.hir_id == const_arg_id
|
|
|
|
|
{
|
|
|
|
|
ty::AnonConstKind::RepeatExprCount
|
|
|
|
|
} else {
|
2025-05-01 16:22:31 +01:00
|
|
|
ty::AnonConstKind::MCG
|
2025-03-12 11:23:20 +00:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
_ => ty::AnonConstKind::NonTypeSystem,
|
|
|
|
|
}
|
|
|
|
|
}
|