2017-09-19 12:43:15 +00: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 12:43:15 +00: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 15:25:52 +00:00
|
|
|
|
2021-08-15 07:09:47 +00:00
|
|
|
use crate::astconv::AstConv;
|
2019-09-28 16:24:05 +00:00
|
|
|
use crate::check::intrinsic::intrinsic_operation_unsafety;
|
2020-08-27 10:00:21 +00:00
|
|
|
use crate::errors;
|
2020-04-27 17:56:11 +00:00
|
|
|
use rustc_ast as ast;
|
2020-10-08 22:23:27 +00:00
|
|
|
use rustc_ast::{MetaItemKind, NestedMetaItem};
|
|
|
|
use rustc_attr::{list_contains_name, InlineAttr, InstructionSetAttr, OptimizeAttr};
|
2020-01-06 06:03:46 +00:00
|
|
|
use rustc_data_structures::captures::Captures;
|
2022-09-29 09:31:46 +00:00
|
|
|
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
|
2022-09-16 02:24:14 +00:00
|
|
|
use rustc_errors::{struct_span_err, Applicability, DiagnosticBuilder, ErrorGuaranteed, StashKey};
|
2020-01-05 01:37:57 +00:00
|
|
|
use rustc_hir as hir;
|
2022-09-20 05:11:23 +00:00
|
|
|
use rustc_hir::def_id::{DefId, LocalDefId, LOCAL_CRATE};
|
2021-11-03 23:03:12 +00:00
|
|
|
use rustc_hir::intravisit::{self, Visitor};
|
2022-10-26 21:18:59 +00:00
|
|
|
use rustc_hir::weak_lang_items::WEAK_LANG_ITEMS;
|
|
|
|
use rustc_hir::{lang_items, GenericParamKind, LangItem, Node};
|
2021-11-03 23:03:12 +00:00
|
|
|
use rustc_middle::hir::nested_filter;
|
2020-03-29 15:19:48 +00:00
|
|
|
use rustc_middle::middle::codegen_fn_attrs::{CodegenFnAttrFlags, CodegenFnAttrs};
|
|
|
|
use rustc_middle::mir::mono::Linkage;
|
|
|
|
use rustc_middle::ty::query::Providers;
|
2022-09-29 09:31:46 +00:00
|
|
|
use rustc_middle::ty::util::{Discr, IntTypeExt};
|
2022-11-25 19:35:27 +00:00
|
|
|
use rustc_middle::ty::{self, AdtKind, Const, DefIdTree, IsSuggestable, ToPredicate, Ty, TyCtxt};
|
2020-03-11 11:49:08 +00:00
|
|
|
use rustc_session::lint;
|
|
|
|
use rustc_session::parse::feature_err;
|
2020-04-19 11:00:18 +00:00
|
|
|
use rustc_span::symbol::{kw, sym, Ident, Symbol};
|
2022-09-29 09:31:46 +00:00
|
|
|
use rustc_span::Span;
|
2022-04-27 08:44:00 +00:00
|
|
|
use rustc_target::spec::{abi, SanitizerSet};
|
2020-04-05 22:33:33 +00:00
|
|
|
use rustc_trait_selection::traits::error_reporting::suggestions::NextTypeParamName;
|
2021-03-08 23:32:41 +00:00
|
|
|
use std::iter;
|
2016-06-21 22:08:13 +00:00
|
|
|
|
2022-09-29 09:31:46 +00:00
|
|
|
mod generics_of;
|
2020-06-23 17:18:06 +00:00
|
|
|
mod item_bounds;
|
2022-10-09 20:26:39 +00:00
|
|
|
mod lifetimes;
|
2022-09-29 09:31:46 +00:00
|
|
|
mod predicates_of;
|
2020-01-17 21:15:03 +00:00
|
|
|
mod type_of;
|
|
|
|
|
2014-08-28 01:46:52 +00:00
|
|
|
///////////////////////////////////////////////////////////////////////////
|
|
|
|
// Main entry point
|
2013-08-14 14:56:28 +00:00
|
|
|
|
2020-06-27 11:09:54 +00:00
|
|
|
fn collect_mod_item_types(tcx: TyCtxt<'_>, module_def_id: LocalDefId) {
|
2022-07-03 13:28:57 +00:00
|
|
|
tcx.hir().visit_item_likes_in_module(module_def_id, &mut CollectItemTypesVisitor { tcx });
|
2012-05-16 02:36:04 +00:00
|
|
|
}
|
|
|
|
|
2020-07-05 20:00:14 +00:00
|
|
|
pub fn provide(providers: &mut Providers) {
|
2022-10-09 20:26:39 +00:00
|
|
|
lifetimes::provide(providers);
|
2017-02-13 23:11:24 +00:00
|
|
|
*providers = Providers {
|
2020-07-02 20:35:11 +00:00
|
|
|
opt_const_param_of: type_of::opt_const_param_of,
|
2020-01-17 21:15:03 +00:00
|
|
|
type_of: type_of::type_of,
|
2020-06-23 17:18:06 +00:00
|
|
|
item_bounds: item_bounds::item_bounds,
|
2020-06-24 18:13:44 +00:00
|
|
|
explicit_item_bounds: item_bounds::explicit_item_bounds,
|
2022-09-29 09:31:46 +00:00
|
|
|
generics_of: generics_of::generics_of,
|
|
|
|
predicates_of: predicates_of::predicates_of,
|
2018-07-02 14:35:30 +00:00
|
|
|
predicates_defined_on,
|
2022-09-29 09:31:46 +00:00
|
|
|
explicit_predicates_of: predicates_of::explicit_predicates_of,
|
|
|
|
super_predicates_of: predicates_of::super_predicates_of,
|
|
|
|
super_predicates_that_define_assoc_type:
|
|
|
|
predicates_of::super_predicates_that_define_assoc_type,
|
|
|
|
trait_explicit_predicates_and_bounds: predicates_of::trait_explicit_predicates_and_bounds,
|
|
|
|
type_param_predicates: predicates_of::type_param_predicates,
|
2017-02-13 23:11:24 +00:00
|
|
|
trait_def,
|
|
|
|
adt_def,
|
2017-05-13 14:11:52 +00:00
|
|
|
fn_sig,
|
2017-02-14 09:32:00 +00:00
|
|
|
impl_trait_ref,
|
2017-04-20 17:37:02 +00:00
|
|
|
impl_polarity,
|
2017-04-14 14:51:22 +00:00
|
|
|
is_foreign_item,
|
2020-01-26 01:09:23 +00:00
|
|
|
generator_kind,
|
2018-05-08 13:10:16 +00:00
|
|
|
codegen_fn_attrs,
|
2022-02-17 18:16:04 +00:00
|
|
|
asm_target_features,
|
2018-06-06 20:13:52 +00:00
|
|
|
collect_mod_item_types,
|
2021-01-24 18:32:37 +00:00
|
|
|
should_inherit_track_caller,
|
2017-02-13 23:11:24 +00:00
|
|
|
..*providers
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
2015-01-05 09:24:00 +00:00
|
|
|
///////////////////////////////////////////////////////////////////////////
|
|
|
|
|
2015-02-18 01:46:26 +00:00
|
|
|
/// Context specific to some particular item. This is what implements
|
2022-08-08 04:16:47 +00:00
|
|
|
/// [`AstConv`].
|
2022-08-08 02:11:47 +00:00
|
|
|
///
|
2022-08-08 04:16:47 +00:00
|
|
|
/// # `ItemCtxt` vs `FnCtxt`
|
2022-08-08 02:11:47 +00:00
|
|
|
///
|
2022-08-08 04:16:47 +00:00
|
|
|
/// `ItemCtxt` is primarily used to type-check item signatures and lower them
|
|
|
|
/// from HIR to their [`ty::Ty`] representation, which is exposed using [`AstConv`].
|
|
|
|
/// It's also used for the bodies of items like structs where the body (the fields)
|
|
|
|
/// are just signatures.
|
|
|
|
///
|
2022-10-20 21:47:49 +00:00
|
|
|
/// This is in contrast to `FnCtxt`, which is used to type-check bodies of
|
2022-08-08 04:16:47 +00: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-18 01:46:26 +00:00
|
|
|
/// on the trait. Unfortunately, this predicate information is
|
|
|
|
/// available in various different forms at various points in the
|
2018-11-27 02:59:49 +00:00
|
|
|
/// process. So we can't just store a pointer to e.g., the AST or the
|
2015-02-18 15:39:39 +00:00
|
|
|
/// parsed ty form, we have to be more flexible. To this end, the
|
2017-02-02 12:18:13 +00:00
|
|
|
/// `ItemCtxt` is parameterized by a `DefId` that it uses to satisfy
|
|
|
|
/// `get_type_parameter_bounds` requests, drawing the information from
|
|
|
|
/// the AST (`hir::Generics`), recursively.
|
2019-06-11 19:03:44 +00:00
|
|
|
pub struct ItemCtxt<'tcx> {
|
2019-06-13 21:48:52 +00:00
|
|
|
tcx: TyCtxt<'tcx>,
|
2017-02-02 12:18:13 +00:00
|
|
|
item_def_id: DefId,
|
2015-02-16 20:48:31 +00:00
|
|
|
}
|
|
|
|
|
2014-08-28 01:46:52 +00:00
|
|
|
///////////////////////////////////////////////////////////////////////////
|
|
|
|
|
2019-12-30 19:45:48 +00:00
|
|
|
#[derive(Default)]
|
2022-05-20 23:51:09 +00:00
|
|
|
pub(crate) struct HirPlaceholderCollector(pub(crate) Vec<Span>);
|
2019-12-24 21:18:09 +00:00
|
|
|
|
2022-01-05 10:43:21 +00:00
|
|
|
impl<'v> Visitor<'v> for HirPlaceholderCollector {
|
2019-12-24 21:18:09 +00:00
|
|
|
fn visit_ty(&mut self, t: &'v hir::Ty<'v>) {
|
|
|
|
if let hir::TyKind::Infer = t.kind {
|
|
|
|
self.0.push(t.span);
|
|
|
|
}
|
2020-01-05 01:37:57 +00:00
|
|
|
intravisit::walk_ty(self, t)
|
2019-12-24 21:18:09 +00:00
|
|
|
}
|
2021-04-24 21:41:57 +00:00
|
|
|
fn visit_generic_arg(&mut self, generic_arg: &'v hir::GenericArg<'v>) {
|
|
|
|
match generic_arg {
|
|
|
|
hir::GenericArg::Infer(inf) => {
|
|
|
|
self.0.push(inf.span);
|
2021-04-26 18:19:23 +00:00
|
|
|
intravisit::walk_inf(self, inf);
|
2021-04-24 21:41:57 +00:00
|
|
|
}
|
|
|
|
hir::GenericArg::Type(t) => self.visit_ty(t),
|
|
|
|
_ => {}
|
|
|
|
}
|
|
|
|
}
|
2022-01-05 10:43:21 +00:00
|
|
|
fn visit_array_length(&mut self, length: &'v hir::ArrayLen) {
|
|
|
|
if let &hir::ArrayLen::Infer(_, span) = length {
|
|
|
|
self.0.push(span);
|
|
|
|
}
|
|
|
|
intravisit::walk_array_len(self, length)
|
|
|
|
}
|
2019-12-24 21:18:09 +00:00
|
|
|
}
|
|
|
|
|
2019-06-11 19:03:44 +00:00
|
|
|
struct CollectItemTypesVisitor<'tcx> {
|
2019-06-13 21:48:52 +00:00
|
|
|
tcx: TyCtxt<'tcx>,
|
2014-08-28 01:46:52 +00:00
|
|
|
}
|
|
|
|
|
2019-12-30 19:45:48 +00: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 23:51:09 +00:00
|
|
|
pub(crate) fn placeholder_type_error<'tcx>(
|
2019-12-24 21:18:09 +00:00
|
|
|
tcx: TyCtxt<'tcx>,
|
2022-02-07 21:58:30 +00:00
|
|
|
generics: Option<&hir::Generics<'_>>,
|
2019-12-24 21:18:09 +00:00
|
|
|
placeholder_types: Vec<Span>,
|
|
|
|
suggest: bool,
|
2021-02-10 15:49:23 +00:00
|
|
|
hir_ty: Option<&hir::Ty<'_>>,
|
2021-06-18 23:01:37 +00:00
|
|
|
kind: &'static str,
|
2019-12-24 21:18:09 +00:00
|
|
|
) {
|
2019-12-26 22:01:45 +00:00
|
|
|
if placeholder_types.is_empty() {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2022-02-07 21:58:30 +00:00
|
|
|
placeholder_type_error_diag(tcx, generics, placeholder_types, vec![], suggest, hir_ty, kind)
|
|
|
|
.emit();
|
2022-03-28 02:43:05 +00:00
|
|
|
}
|
|
|
|
|
2022-05-20 23:51:09 +00:00
|
|
|
pub(crate) fn placeholder_type_error_diag<'tcx>(
|
2022-03-28 02:43:05 +00:00
|
|
|
tcx: TyCtxt<'tcx>,
|
2022-02-07 21:58:30 +00:00
|
|
|
generics: Option<&hir::Generics<'_>>,
|
2022-03-28 02:43:05 +00:00
|
|
|
placeholder_types: Vec<Span>,
|
|
|
|
additional_spans: Vec<Span>,
|
|
|
|
suggest: bool,
|
|
|
|
hir_ty: Option<&hir::Ty<'_>>,
|
|
|
|
kind: &'static str,
|
|
|
|
) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> {
|
|
|
|
if placeholder_types.is_empty() {
|
|
|
|
return bad_placeholder(tcx, additional_spans, kind);
|
|
|
|
}
|
|
|
|
|
2022-02-07 21:58:30 +00:00
|
|
|
let params = generics.map(|g| g.params).unwrap_or_default();
|
|
|
|
let type_name = params.next_type_param_name(None);
|
2019-12-26 22:01:45 +00:00
|
|
|
let mut sugg: Vec<_> =
|
2020-03-05 13:29:58 +00:00
|
|
|
placeholder_types.iter().map(|sp| (*sp, (*type_name).to_string())).collect();
|
2020-07-12 15:40:22 +00:00
|
|
|
|
2022-02-07 21:58:30 +00:00
|
|
|
if let Some(generics) = generics {
|
|
|
|
if let Some(arg) = params.iter().find(|arg| {
|
|
|
|
matches!(arg.name, hir::ParamName::Plain(Ident { name: kw::Underscore, .. }))
|
|
|
|
}) {
|
|
|
|
// Account for `_` already present in cases like `struct S<_>(_);` and suggest
|
|
|
|
// `struct S<T>(T);` instead of `struct S<_, T>(T);`.
|
|
|
|
sugg.push((arg.span, (*type_name).to_string()));
|
|
|
|
} 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)`.
|
|
|
|
sugg.push((span, format!(", {}", type_name)));
|
|
|
|
} else {
|
|
|
|
sugg.push((generics.span, format!("<{}>", type_name)));
|
2020-07-12 15:40:22 +00:00
|
|
|
}
|
2019-12-26 22:01:45 +00:00
|
|
|
}
|
2020-07-12 15:40:22 +00:00
|
|
|
|
2022-03-28 02:43:05 +00:00
|
|
|
let mut err =
|
|
|
|
bad_placeholder(tcx, 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 22:01:45 +00:00
|
|
|
if suggest {
|
2021-02-10 15:49:23 +00:00
|
|
|
let mut is_fn = false;
|
2021-06-16 09:47:26 +00:00
|
|
|
let mut is_const_or_static = false;
|
2021-02-10 15:49:23 +00:00
|
|
|
|
2022-02-26 10:43:47 +00: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
|
|
|
|
let parent_id = tcx.hir().get_parent_node(hir_ty.hir_id);
|
|
|
|
let parent_node = tcx.hir().get(parent_id);
|
|
|
|
|
|
|
|
is_const_or_static = matches!(
|
|
|
|
parent_node,
|
|
|
|
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 09:47:26 +00: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 21:18:09 +00:00
|
|
|
}
|
2022-03-28 02:43:05 +00:00
|
|
|
|
|
|
|
err
|
2019-12-24 21:18:09 +00:00
|
|
|
}
|
|
|
|
|
2021-12-14 13:26:57 +00:00
|
|
|
fn reject_placeholder_type_signatures_in_item<'tcx>(
|
|
|
|
tcx: TyCtxt<'tcx>,
|
|
|
|
item: &'tcx hir::Item<'tcx>,
|
|
|
|
) {
|
2019-12-24 21:18:09 +00:00
|
|
|
let (generics, suggest) = match &item.kind {
|
|
|
|
hir::ItemKind::Union(_, generics)
|
|
|
|
| hir::ItemKind::Enum(_, generics)
|
2020-01-09 21:46:37 +00:00
|
|
|
| hir::ItemKind::TraitAlias(generics, _)
|
|
|
|
| hir::ItemKind::Trait(_, _, generics, ..)
|
2020-11-22 22:46:21 +00:00
|
|
|
| hir::ItemKind::Impl(hir::Impl { generics, .. })
|
2020-01-09 21:46:37 +00:00
|
|
|
| hir::ItemKind::Struct(_, generics) => (generics, true),
|
|
|
|
hir::ItemKind::OpaqueTy(hir::OpaqueTy { generics, .. })
|
|
|
|
| hir::ItemKind::TyAlias(_, generics) => (generics, false),
|
2019-12-27 23:45:39 +00:00
|
|
|
// `static`, `fn` and `const` are handled elsewhere to suggest appropriate type.
|
2019-12-24 21:18:09 +00:00
|
|
|
_ => return,
|
|
|
|
};
|
|
|
|
|
2022-01-05 10:43:21 +00:00
|
|
|
let mut visitor = HirPlaceholderCollector::default();
|
2019-12-24 21:18:09 +00:00
|
|
|
visitor.visit_item(item);
|
|
|
|
|
2022-02-07 21:58:30 +00:00
|
|
|
placeholder_type_error(tcx, Some(generics), visitor.0, suggest, None, item.kind.descr());
|
2019-12-24 21:18:09 +00:00
|
|
|
}
|
|
|
|
|
2021-12-14 01:45:08 +00:00
|
|
|
impl<'tcx> Visitor<'tcx> for CollectItemTypesVisitor<'tcx> {
|
2021-11-03 23:03:12 +00:00
|
|
|
type NestedFilter = nested_filter::OnlyBodies;
|
2020-01-07 16:25:33 +00:00
|
|
|
|
2021-11-03 23:03:12 +00:00
|
|
|
fn nested_visit_map(&mut self) -> Self::Map {
|
|
|
|
self.tcx.hir()
|
2016-11-19 20:14:06 +00:00
|
|
|
}
|
|
|
|
|
2019-11-28 18:28:50 +00:00
|
|
|
fn visit_item(&mut self, item: &'tcx hir::Item<'tcx>) {
|
2021-01-30 16:47:51 +00:00
|
|
|
convert_item(self.tcx, item.item_id());
|
2019-12-24 21:18:09 +00:00
|
|
|
reject_placeholder_type_signatures_in_item(self.tcx, item);
|
2016-11-10 14:49:53 +00:00
|
|
|
intravisit::walk_item(self, item);
|
|
|
|
}
|
|
|
|
|
2019-12-01 15:08:58 +00:00
|
|
|
fn visit_generics(&mut self, generics: &'tcx hir::Generics<'tcx>) {
|
2019-12-01 16:10:12 +00:00
|
|
|
for param in generics.params {
|
2018-05-25 23:27:54 +00:00
|
|
|
match param.kind {
|
|
|
|
hir::GenericParamKind::Lifetime { .. } => {}
|
2018-08-19 16:34:21 +00:00
|
|
|
hir::GenericParamKind::Type { default: Some(_), .. } => {
|
2022-11-06 18:26:36 +00:00
|
|
|
self.tcx.ensure().type_of(param.def_id);
|
2018-05-25 23:27:54 +00:00
|
|
|
}
|
2018-05-27 20:54:10 +00:00
|
|
|
hir::GenericParamKind::Type { .. } => {}
|
2020-12-30 15:34:53 +00:00
|
|
|
hir::GenericParamKind::Const { default, .. } => {
|
2022-11-06 18:26:36 +00:00
|
|
|
self.tcx.ensure().type_of(param.def_id);
|
2020-12-30 15:34:53 +00:00
|
|
|
if let Some(default) = default {
|
2021-03-03 06:38:02 +00:00
|
|
|
// need to store default and type of default
|
2022-11-06 19:17:57 +00:00
|
|
|
self.tcx.ensure().type_of(default.def_id);
|
2022-11-06 18:26:36 +00:00
|
|
|
self.tcx.ensure().const_param_default(param.def_id);
|
2020-12-30 15:34:53 +00:00
|
|
|
}
|
2019-02-15 22:22:54 +00:00
|
|
|
}
|
2017-01-25 20:01:11 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
intravisit::walk_generics(self, generics);
|
|
|
|
}
|
|
|
|
|
2019-11-30 14:08:22 +00:00
|
|
|
fn visit_expr(&mut self, expr: &'tcx hir::Expr<'tcx>) {
|
2022-11-06 13:29:21 +00:00
|
|
|
if let hir::ExprKind::Closure(closure) = expr.kind {
|
|
|
|
self.tcx.ensure().generics_of(closure.def_id);
|
|
|
|
self.tcx.ensure().codegen_fn_attrs(closure.def_id);
|
2021-11-19 21:18:28 +00:00
|
|
|
// We do not call `type_of` for closures here as that
|
|
|
|
// depends on typecheck and would therefore hide
|
|
|
|
// any further errors in case one typeck fails.
|
2016-11-12 21:20:02 +00:00
|
|
|
}
|
|
|
|
intravisit::walk_expr(self, expr);
|
|
|
|
}
|
|
|
|
|
2019-11-28 20:47:10 +00:00
|
|
|
fn visit_trait_item(&mut self, trait_item: &'tcx hir::TraitItem<'tcx>) {
|
2021-01-30 19:46:50 +00:00
|
|
|
convert_trait_item(self.tcx, trait_item.trait_item_id());
|
2016-12-04 02:21:06 +00:00
|
|
|
intravisit::walk_trait_item(self, trait_item);
|
|
|
|
}
|
|
|
|
|
2019-11-28 21:16:44 +00:00
|
|
|
fn visit_impl_item(&mut self, impl_item: &'tcx hir::ImplItem<'tcx>) {
|
2021-01-30 22:25:03 +00:00
|
|
|
convert_impl_item(self.tcx, impl_item.impl_item_id());
|
2016-11-08 18:23:59 +00:00
|
|
|
intravisit::walk_impl_item(self, impl_item);
|
2016-11-04 22:20:15 +00:00
|
|
|
}
|
2014-08-28 01:46:52 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
///////////////////////////////////////////////////////////////////////////
|
|
|
|
// Utility types and common code for the above passes.
|
|
|
|
|
2021-12-23 09:01:51 +00:00
|
|
|
fn bad_placeholder<'tcx>(
|
2019-12-27 12:15:48 +00:00
|
|
|
tcx: TyCtxt<'tcx>,
|
|
|
|
mut spans: Vec<Span>,
|
2021-06-18 23:01:37 +00:00
|
|
|
kind: &'static str,
|
2022-01-23 18:34:26 +00:00
|
|
|
) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> {
|
2021-06-18 23:01:37 +00:00
|
|
|
let kind = if kind.ends_with('s') { format!("{}es", kind) } else { format!("{}s", kind) };
|
|
|
|
|
2019-12-27 12:15:48 +00:00
|
|
|
spans.sort();
|
|
|
|
let mut err = struct_span_err!(
|
2019-11-11 22:34:57 +00:00
|
|
|
tcx.sess,
|
2019-12-27 12:15:48 +00:00
|
|
|
spans.clone(),
|
2019-11-11 22:34:57 +00:00
|
|
|
E0121,
|
2022-01-05 10:43:21 +00:00
|
|
|
"the placeholder `_` is not allowed within types on item signatures for {}",
|
2021-06-18 23:01:37 +00:00
|
|
|
kind
|
2019-07-17 06:55:15 +00:00
|
|
|
);
|
2019-12-27 12:15:48 +00:00
|
|
|
for span in spans {
|
|
|
|
err.span_label(span, "not allowed in type signatures");
|
|
|
|
}
|
|
|
|
err
|
2019-07-17 06:55:15 +00:00
|
|
|
}
|
|
|
|
|
2021-12-14 01:45:08 +00:00
|
|
|
impl<'tcx> ItemCtxt<'tcx> {
|
2019-06-13 21:48:52 +00:00
|
|
|
pub fn new(tcx: TyCtxt<'tcx>, item_def_id: DefId) -> ItemCtxt<'tcx> {
|
2018-08-19 16:34:21 +00:00
|
|
|
ItemCtxt { tcx, item_def_id }
|
2015-02-16 20:48:31 +00:00
|
|
|
}
|
|
|
|
|
2021-02-10 01:05:18 +00:00
|
|
|
pub fn to_ty(&self, ast_ty: &hir::Ty<'_>) -> Ty<'tcx> {
|
2021-03-07 15:47:39 +00:00
|
|
|
<dyn AstConv<'_>>::ast_ty_to_ty(self, ast_ty)
|
2012-05-16 02:36:04 +00:00
|
|
|
}
|
2020-02-11 03:14:31 +00:00
|
|
|
|
|
|
|
pub fn hir_id(&self) -> hir::HirId {
|
2020-08-12 10:22:56 +00:00
|
|
|
self.tcx.hir().local_def_id_to_hir_id(self.item_def_id.expect_local())
|
2020-02-11 03:14:31 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
pub fn node(&self) -> hir::Node<'tcx> {
|
|
|
|
self.tcx.hir().get(self.hir_id())
|
|
|
|
}
|
2012-05-16 02:36:04 +00:00
|
|
|
}
|
|
|
|
|
2021-12-14 01:45:08 +00:00
|
|
|
impl<'tcx> AstConv<'tcx> for ItemCtxt<'tcx> {
|
2019-06-13 21:48:52 +00:00
|
|
|
fn tcx(&self) -> TyCtxt<'tcx> {
|
2018-08-19 16:34:21 +00:00
|
|
|
self.tcx
|
|
|
|
}
|
2012-05-16 02:36:04 +00:00
|
|
|
|
2022-10-31 16:19:36 +00:00
|
|
|
fn item_def_id(&self) -> DefId {
|
|
|
|
self.item_def_id
|
2019-11-01 12:50:36 +00:00
|
|
|
}
|
|
|
|
|
2020-12-03 23:10:55 +00:00
|
|
|
fn get_type_parameter_bounds(
|
|
|
|
&self,
|
|
|
|
span: Span,
|
|
|
|
def_id: DefId,
|
|
|
|
assoc_name: Ident,
|
|
|
|
) -> ty::GenericPredicates<'tcx> {
|
|
|
|
self.tcx.at(span).type_param_predicates((
|
|
|
|
self.item_def_id,
|
|
|
|
def_id.expect_local(),
|
|
|
|
assoc_name,
|
|
|
|
))
|
2015-02-17 16:04:25 +00:00
|
|
|
}
|
|
|
|
|
2019-06-06 00:55:34 +00:00
|
|
|
fn re_infer(&self, _: Option<&ty::GenericParamDef>, _: Span) -> Option<ty::Region<'tcx>> {
|
2017-01-25 15:32:44 +00:00
|
|
|
None
|
2017-01-13 13:09:56 +00:00
|
|
|
}
|
|
|
|
|
2019-12-23 22:16:34 +00:00
|
|
|
fn allow_ty_infer(&self) -> bool {
|
|
|
|
false
|
|
|
|
}
|
2018-09-26 15:32:23 +00:00
|
|
|
|
2019-06-06 00:55:34 +00:00
|
|
|
fn ty_infer(&self, _: Option<&ty::GenericParamDef>, span: Span) -> Ty<'tcx> {
|
2022-01-05 10:42:08 +00:00
|
|
|
self.tcx().ty_error_with_message(span, "bad placeholder type")
|
2012-05-16 02:36:04 +00:00
|
|
|
}
|
2014-08-06 02:44:21 +00:00
|
|
|
|
2022-02-02 03:24:45 +00:00
|
|
|
fn ct_infer(&self, ty: Ty<'tcx>, _: Option<&ty::GenericParamDef>, span: Span) -> Const<'tcx> {
|
2022-06-27 13:55:03 +00:00
|
|
|
let ty = self.tcx.fold_regions(ty, |r, _| match *r {
|
2021-02-24 20:21:18 +00:00
|
|
|
ty::ReErased => self.tcx.lifetimes.re_static,
|
|
|
|
_ => r,
|
|
|
|
});
|
2022-01-05 10:42:08 +00:00
|
|
|
self.tcx().const_error_with_message(ty, span, "bad placeholder constant")
|
2019-06-06 00:55:09 +00:00
|
|
|
}
|
|
|
|
|
2018-08-19 16:34:21 +00:00
|
|
|
fn projected_ty_from_poly_trait_ref(
|
|
|
|
&self,
|
|
|
|
span: Span,
|
|
|
|
item_def_id: DefId,
|
2019-12-01 15:08:58 +00:00
|
|
|
item_segment: &hir::PathSegment<'_>,
|
2018-08-19 16:34:21 +00:00
|
|
|
poly_trait_ref: ty::PolyTraitRef<'tcx>,
|
|
|
|
) -> Ty<'tcx> {
|
2018-10-24 20:30:34 +00:00
|
|
|
if let Some(trait_ref) = poly_trait_ref.no_bound_vars() {
|
2019-12-08 17:04:17 +00:00
|
|
|
let item_substs = <dyn AstConv<'tcx>>::create_substs_for_associated_item(
|
|
|
|
self,
|
|
|
|
span,
|
|
|
|
item_def_id,
|
|
|
|
item_segment,
|
|
|
|
trait_ref.substs,
|
|
|
|
);
|
|
|
|
self.tcx().mk_projection(item_def_id, item_substs)
|
2016-05-03 02:23:22 +00:00
|
|
|
} else {
|
2019-06-17 22:40:24 +00:00
|
|
|
// There are no late-bound regions; we can just ignore the binder.
|
2020-02-11 03:14:31 +00:00
|
|
|
let mut err = struct_span_err!(
|
2018-08-19 16:34:21 +00:00
|
|
|
self.tcx().sess,
|
|
|
|
span,
|
|
|
|
E0212,
|
2020-12-04 12:18:01 +00:00
|
|
|
"cannot use the associated type of a trait \
|
|
|
|
with uninferred generic parameters"
|
2020-02-11 03:14:31 +00:00
|
|
|
);
|
|
|
|
|
|
|
|
match self.node() {
|
2020-02-11 20:37:12 +00:00
|
|
|
hir::Node::Field(_) | hir::Node::Ctor(_) | hir::Node::Variant(_) => {
|
2022-09-20 05:11:23 +00:00
|
|
|
let item = self
|
|
|
|
.tcx
|
|
|
|
.hir()
|
|
|
|
.expect_item(self.tcx.hir().get_parent_item(self.hir_id()).def_id);
|
2020-02-11 20:37:12 +00:00
|
|
|
match &item.kind {
|
|
|
|
hir::ItemKind::Enum(_, generics)
|
|
|
|
| hir::ItemKind::Struct(_, generics)
|
|
|
|
| hir::ItemKind::Union(_, generics) => {
|
2020-02-14 06:45:48 +00:00
|
|
|
let lt_name = get_new_lifetime_name(self.tcx, poly_trait_ref, generics);
|
2021-02-15 23:30:06 +00:00
|
|
|
let (lt_sp, sugg) = match generics.params {
|
2020-02-14 06:45:48 +00:00
|
|
|
[] => (generics.span, format!("<{}>", lt_name)),
|
|
|
|
[bound, ..] => {
|
|
|
|
(bound.span.shrink_to_lo(), format!("{}, ", lt_name))
|
|
|
|
}
|
2020-02-11 20:37:12 +00:00
|
|
|
};
|
|
|
|
let suggestions = vec![
|
|
|
|
(lt_sp, sugg),
|
|
|
|
(
|
2021-08-10 10:53:43 +00:00
|
|
|
span.with_hi(item_segment.ident.span.lo()),
|
2020-02-11 20:37:12 +00:00
|
|
|
format!(
|
2021-08-10 10:53:43 +00:00
|
|
|
"{}::",
|
2020-02-11 20:37:12 +00:00
|
|
|
// Replace the existing lifetimes with a new named lifetime.
|
2022-06-02 11:31:04 +00:00
|
|
|
self.tcx.replace_late_bound_regions_uncached(
|
|
|
|
poly_trait_ref,
|
|
|
|
|_| {
|
2020-02-11 20:37:12 +00:00
|
|
|
self.tcx.mk_region(ty::ReEarlyBound(
|
|
|
|
ty::EarlyBoundRegion {
|
|
|
|
def_id: item_def_id,
|
|
|
|
index: 0,
|
2020-02-14 06:45:48 +00:00
|
|
|
name: Symbol::intern(<_name),
|
2020-02-11 20:37:12 +00:00
|
|
|
},
|
|
|
|
))
|
2022-06-02 11:31:04 +00:00
|
|
|
}
|
|
|
|
),
|
2020-02-11 20:37:12 +00:00
|
|
|
),
|
|
|
|
),
|
|
|
|
];
|
|
|
|
err.multipart_suggestion(
|
|
|
|
"use a fully qualified path with explicit lifetimes",
|
|
|
|
suggestions,
|
|
|
|
Applicability::MaybeIncorrect,
|
|
|
|
);
|
|
|
|
}
|
|
|
|
_ => {}
|
|
|
|
}
|
2020-02-11 03:14:31 +00:00
|
|
|
}
|
2020-04-17 00:38:52 +00:00
|
|
|
hir::Node::Item(hir::Item {
|
|
|
|
kind:
|
|
|
|
hir::ItemKind::Struct(..) | hir::ItemKind::Enum(..) | hir::ItemKind::Union(..),
|
|
|
|
..
|
|
|
|
}) => {}
|
2020-02-11 03:14:31 +00:00
|
|
|
hir::Node::Item(_)
|
|
|
|
| hir::Node::ForeignItem(_)
|
|
|
|
| hir::Node::TraitItem(_)
|
|
|
|
| hir::Node::ImplItem(_) => {
|
2021-08-10 10:53:43 +00:00
|
|
|
err.span_suggestion_verbose(
|
|
|
|
span.with_hi(item_segment.ident.span.lo()),
|
2020-02-11 03:14:31 +00:00
|
|
|
"use a fully qualified path with inferred lifetimes",
|
|
|
|
format!(
|
2021-08-10 10:53:43 +00:00
|
|
|
"{}::",
|
2020-02-11 03:14:31 +00:00
|
|
|
// Erase named lt, we want `<A as B<'_>::C`, not `<A as B<'a>::C`.
|
2020-10-24 00:21:18 +00:00
|
|
|
self.tcx.anonymize_late_bound_regions(poly_trait_ref).skip_binder(),
|
2020-02-11 03:14:31 +00:00
|
|
|
),
|
|
|
|
Applicability::MaybeIncorrect,
|
|
|
|
);
|
|
|
|
}
|
|
|
|
_ => {}
|
|
|
|
}
|
2022-11-03 06:15:17 +00:00
|
|
|
self.tcx().ty_error_with_guaranteed(err.emit())
|
2016-05-03 02:23:22 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-02-28 23:30:41 +00:00
|
|
|
fn normalize_ty(&self, _span: Span, ty: Ty<'tcx>) -> Ty<'tcx> {
|
2019-06-17 22:40:24 +00:00
|
|
|
// Types in item signatures are not normalized to avoid undue dependencies.
|
2017-02-28 23:30:41 +00:00
|
|
|
ty
|
2014-08-06 02:44:21 +00:00
|
|
|
}
|
2016-03-15 08:49:10 +00:00
|
|
|
|
2022-11-18 11:30:21 +00:00
|
|
|
fn set_tainted_by_errors(&self, _: ErrorGuaranteed) {
|
2019-06-17 22:40:24 +00:00
|
|
|
// There's no obvious place to track this, so just let it go.
|
2016-03-15 08:49:10 +00:00
|
|
|
}
|
2017-09-15 23:33:41 +00:00
|
|
|
|
|
|
|
fn record_ty(&self, _hir_id: hir::HirId, _ty: Ty<'tcx>, _span: Span) {
|
2019-06-17 22:40:24 +00:00
|
|
|
// There's no place to record types from signatures?
|
2017-09-15 23:33:41 +00:00
|
|
|
}
|
2012-05-16 02:36:04 +00:00
|
|
|
}
|
|
|
|
|
2020-02-14 06:45:48 +00: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
|
|
|
|
.collect_referenced_late_bound_regions(&poly_trait_ref)
|
|
|
|
.into_iter()
|
|
|
|
.filter_map(|lt| {
|
2020-12-18 18:24:55 +00:00
|
|
|
if let ty::BoundRegionKind::BrNamed(_, name) = lt {
|
2020-02-14 06:45:48 +00: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-28 23:35:24 +00:00
|
|
|
let mut s = '\''.to_string();
|
2020-02-14 06:45:48 +00: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()
|
|
|
|
}
|
|
|
|
|
2021-01-30 16:47:51 +00:00
|
|
|
fn convert_item(tcx: TyCtxt<'_>, item_id: hir::ItemId) {
|
|
|
|
let it = tcx.hir().item(item_id);
|
|
|
|
debug!("convert: item {} with id {}", it.ident, it.hir_id());
|
2022-10-27 03:02:18 +00:00
|
|
|
let def_id = item_id.owner_id.def_id;
|
2021-02-10 15:49:23 +00:00
|
|
|
|
2019-09-26 16:51:36 +00:00
|
|
|
match it.kind {
|
2014-02-17 05:52:11 +00:00
|
|
|
// These don't define types.
|
2018-08-19 16:34:21 +00:00
|
|
|
hir::ItemKind::ExternCrate(_)
|
|
|
|
| hir::ItemKind::Use(..)
|
2021-12-11 11:52:23 +00:00
|
|
|
| hir::ItemKind::Macro(..)
|
2018-08-19 16:34:21 +00:00
|
|
|
| hir::ItemKind::Mod(_)
|
|
|
|
| hir::ItemKind::GlobalAsm(_) => {}
|
2020-11-11 21:40:09 +00:00
|
|
|
hir::ItemKind::ForeignMod { items, .. } => {
|
|
|
|
for item in items {
|
2020-11-11 20:57:54 +00:00
|
|
|
let item = tcx.hir().foreign_item(item.id);
|
2022-10-27 03:02:18 +00:00
|
|
|
tcx.ensure().generics_of(item.owner_id);
|
|
|
|
tcx.ensure().type_of(item.owner_id);
|
|
|
|
tcx.ensure().predicates_of(item.owner_id);
|
2021-04-01 01:45:42 +00:00
|
|
|
match item.kind {
|
2022-11-06 16:28:07 +00:00
|
|
|
hir::ForeignItemKind::Fn(..) => {
|
|
|
|
tcx.ensure().codegen_fn_attrs(item.owner_id);
|
|
|
|
tcx.ensure().fn_sig(item.owner_id)
|
|
|
|
}
|
2021-04-01 01:45:42 +00:00
|
|
|
hir::ForeignItemKind::Static(..) => {
|
2022-11-06 16:28:07 +00:00
|
|
|
tcx.ensure().codegen_fn_attrs(item.owner_id);
|
2022-01-05 10:43:21 +00:00
|
|
|
let mut visitor = HirPlaceholderCollector::default();
|
2021-04-01 01:45:42 +00:00
|
|
|
visitor.visit_foreign_item(item);
|
2021-06-18 23:01:37 +00:00
|
|
|
placeholder_type_error(
|
|
|
|
tcx,
|
|
|
|
None,
|
|
|
|
visitor.0,
|
|
|
|
false,
|
|
|
|
None,
|
|
|
|
"static variable",
|
|
|
|
);
|
2021-04-01 01:45:42 +00:00
|
|
|
}
|
|
|
|
_ => (),
|
2017-05-13 14:11:52 +00:00
|
|
|
}
|
2015-12-22 21:35:02 +00:00
|
|
|
}
|
2015-02-11 15:25:52 +00:00
|
|
|
}
|
2022-10-30 09:17:16 +00:00
|
|
|
hir::ItemKind::Enum(..) => {
|
2020-05-01 09:32:20 +00:00
|
|
|
tcx.ensure().generics_of(def_id);
|
|
|
|
tcx.ensure().type_of(def_id);
|
|
|
|
tcx.ensure().predicates_of(def_id);
|
2022-10-30 09:17:16 +00:00
|
|
|
convert_enum_variant_types(tcx, def_id.to_def_id());
|
2018-08-19 16:34:21 +00:00
|
|
|
}
|
2020-01-18 00:14:29 +00:00
|
|
|
hir::ItemKind::Impl { .. } => {
|
2020-05-01 09:32:20 +00:00
|
|
|
tcx.ensure().generics_of(def_id);
|
|
|
|
tcx.ensure().type_of(def_id);
|
|
|
|
tcx.ensure().impl_trait_ref(def_id);
|
|
|
|
tcx.ensure().predicates_of(def_id);
|
2018-08-19 16:34:21 +00:00
|
|
|
}
|
2018-07-11 15:36:06 +00:00
|
|
|
hir::ItemKind::Trait(..) => {
|
2020-05-01 09:32:20 +00:00
|
|
|
tcx.ensure().generics_of(def_id);
|
|
|
|
tcx.ensure().trait_def(def_id);
|
2017-04-24 15:06:39 +00:00
|
|
|
tcx.at(it.span).super_predicates_of(def_id);
|
2020-05-01 09:32:20 +00:00
|
|
|
tcx.ensure().predicates_of(def_id);
|
2018-08-19 16:34:21 +00:00
|
|
|
}
|
2018-07-11 15:36:06 +00:00
|
|
|
hir::ItemKind::TraitAlias(..) => {
|
2020-05-01 09:32:20 +00:00
|
|
|
tcx.ensure().generics_of(def_id);
|
2018-10-12 00:50:03 +00:00
|
|
|
tcx.at(it.span).super_predicates_of(def_id);
|
2020-05-01 09:32:20 +00:00
|
|
|
tcx.ensure().predicates_of(def_id);
|
2018-08-19 16:34:21 +00:00
|
|
|
}
|
|
|
|
hir::ItemKind::Struct(ref struct_def, _) | hir::ItemKind::Union(ref struct_def, _) => {
|
2020-05-01 09:32:20 +00:00
|
|
|
tcx.ensure().generics_of(def_id);
|
|
|
|
tcx.ensure().type_of(def_id);
|
|
|
|
tcx.ensure().predicates_of(def_id);
|
2017-02-14 09:32:00 +00:00
|
|
|
|
|
|
|
for f in struct_def.fields() {
|
2022-11-06 19:46:55 +00:00
|
|
|
tcx.ensure().generics_of(f.def_id);
|
|
|
|
tcx.ensure().type_of(f.def_id);
|
|
|
|
tcx.ensure().predicates_of(f.def_id);
|
2015-08-05 22:29:52 +00:00
|
|
|
}
|
|
|
|
|
2022-11-06 19:46:55 +00:00
|
|
|
if let Some(ctor_def_id) = struct_def.ctor_def_id() {
|
2022-10-30 09:17:16 +00:00
|
|
|
convert_variant_ctor(tcx, ctor_def_id);
|
2015-07-22 18:53:52 +00:00
|
|
|
}
|
2018-08-19 16:34:21 +00:00
|
|
|
}
|
2018-07-03 17:38:14 +00:00
|
|
|
|
2020-09-26 16:56:03 +00:00
|
|
|
// Don't call `type_of` on opaque types, since that depends on type
|
|
|
|
// checking function bodies. `check_item_type` ensures that it's called
|
|
|
|
// instead.
|
|
|
|
hir::ItemKind::OpaqueTy(..) => {
|
|
|
|
tcx.ensure().generics_of(def_id);
|
|
|
|
tcx.ensure().predicates_of(def_id);
|
2020-09-07 09:01:45 +00:00
|
|
|
tcx.ensure().explicit_item_bounds(def_id);
|
2022-11-11 10:29:27 +00:00
|
|
|
tcx.ensure().item_bounds(def_id);
|
2020-09-26 16:56:03 +00:00
|
|
|
}
|
2022-11-11 10:29:27 +00:00
|
|
|
|
|
|
|
hir::ItemKind::TyAlias(..) => {
|
2020-05-01 09:32:20 +00:00
|
|
|
tcx.ensure().generics_of(def_id);
|
|
|
|
tcx.ensure().type_of(def_id);
|
|
|
|
tcx.ensure().predicates_of(def_id);
|
2022-11-11 10:29:27 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
hir::ItemKind::Static(ty, ..) | hir::ItemKind::Const(ty, ..) => {
|
|
|
|
tcx.ensure().generics_of(def_id);
|
|
|
|
tcx.ensure().type_of(def_id);
|
|
|
|
tcx.ensure().predicates_of(def_id);
|
|
|
|
if !is_suggestable_infer_ty(ty) {
|
|
|
|
let mut visitor = HirPlaceholderCollector::default();
|
|
|
|
visitor.visit_item(it);
|
|
|
|
placeholder_type_error(tcx, None, visitor.0, false, None, it.kind.descr());
|
2017-05-13 14:11:52 +00:00
|
|
|
}
|
2017-03-17 03:16:40 +00:00
|
|
|
}
|
2022-11-11 10:29:27 +00:00
|
|
|
|
|
|
|
hir::ItemKind::Fn(..) => {
|
|
|
|
tcx.ensure().generics_of(def_id);
|
|
|
|
tcx.ensure().type_of(def_id);
|
|
|
|
tcx.ensure().predicates_of(def_id);
|
|
|
|
tcx.ensure().fn_sig(def_id);
|
2022-11-06 16:28:07 +00:00
|
|
|
tcx.ensure().codegen_fn_attrs(def_id);
|
2022-11-11 10:29:27 +00:00
|
|
|
}
|
2012-05-15 15:29:22 +00:00
|
|
|
}
|
|
|
|
}
|
2012-08-07 23:46:19 +00:00
|
|
|
|
2021-01-30 19:46:50 +00:00
|
|
|
fn convert_trait_item(tcx: TyCtxt<'_>, trait_item_id: hir::TraitItemId) {
|
|
|
|
let trait_item = tcx.hir().trait_item(trait_item_id);
|
2022-10-27 03:02:18 +00:00
|
|
|
let def_id = trait_item_id.owner_id;
|
2022-09-20 05:11:23 +00:00
|
|
|
tcx.ensure().generics_of(def_id);
|
2017-02-14 09:32:00 +00:00
|
|
|
|
2019-09-26 16:07:54 +00:00
|
|
|
match trait_item.kind {
|
2020-03-03 18:46:22 +00:00
|
|
|
hir::TraitItemKind::Fn(..) => {
|
2022-11-06 16:28:07 +00:00
|
|
|
tcx.ensure().codegen_fn_attrs(def_id);
|
2022-09-20 05:11:23 +00:00
|
|
|
tcx.ensure().type_of(def_id);
|
|
|
|
tcx.ensure().fn_sig(def_id);
|
2020-02-17 20:07:50 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
hir::TraitItemKind::Const(.., Some(_)) => {
|
2022-09-20 05:11:23 +00:00
|
|
|
tcx.ensure().type_of(def_id);
|
2020-02-17 20:07:50 +00:00
|
|
|
}
|
|
|
|
|
2022-09-16 02:24:14 +00:00
|
|
|
hir::TraitItemKind::Const(hir_ty, _) => {
|
2022-09-20 05:11:23 +00:00
|
|
|
tcx.ensure().type_of(def_id);
|
2020-06-27 20:36:35 +00:00
|
|
|
// Account for `const C: _;`.
|
2022-01-05 10:43:21 +00:00
|
|
|
let mut visitor = HirPlaceholderCollector::default();
|
2020-06-27 20:36:35 +00:00
|
|
|
visitor.visit_trait_item(trait_item);
|
2022-09-16 02:24:14 +00:00
|
|
|
if !tcx.sess.diagnostic().has_stashed_diagnostic(hir_ty.span, StashKey::ItemNoType) {
|
|
|
|
placeholder_type_error(tcx, None, visitor.0, false, None, "constant");
|
|
|
|
}
|
2020-06-27 20:36:35 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
hir::TraitItemKind::Type(_, Some(_)) => {
|
2022-09-20 05:11:23 +00:00
|
|
|
tcx.ensure().item_bounds(def_id);
|
|
|
|
tcx.ensure().type_of(def_id);
|
2020-06-27 20:36:35 +00:00
|
|
|
// Account for `type T = _;`.
|
2022-01-05 10:43:21 +00:00
|
|
|
let mut visitor = HirPlaceholderCollector::default();
|
2020-02-17 20:07:50 +00:00
|
|
|
visitor.visit_trait_item(trait_item);
|
2022-02-07 21:58:30 +00:00
|
|
|
placeholder_type_error(tcx, None, visitor.0, false, None, "associated type");
|
2016-12-04 02:21:06 +00:00
|
|
|
}
|
|
|
|
|
2020-07-22 05:42:45 +00:00
|
|
|
hir::TraitItemKind::Type(_, None) => {
|
2022-09-20 05:11:23 +00:00
|
|
|
tcx.ensure().item_bounds(def_id);
|
2020-07-22 05:42:45 +00:00
|
|
|
// #74612: Visit and try to find bad placeholders
|
|
|
|
// even if there is no concrete type.
|
2022-01-05 10:43:21 +00:00
|
|
|
let mut visitor = HirPlaceholderCollector::default();
|
2020-07-22 05:42:45 +00:00
|
|
|
visitor.visit_trait_item(trait_item);
|
2021-02-10 15:49:23 +00:00
|
|
|
|
2022-02-07 21:58:30 +00:00
|
|
|
placeholder_type_error(tcx, None, visitor.0, false, None, "associated type");
|
2020-07-22 05:42:45 +00:00
|
|
|
}
|
2017-02-14 09:32:00 +00:00
|
|
|
};
|
2016-12-04 02:21:06 +00:00
|
|
|
|
2022-09-20 05:11:23 +00:00
|
|
|
tcx.ensure().predicates_of(def_id);
|
2016-12-04 02:21:06 +00:00
|
|
|
}
|
|
|
|
|
2021-01-30 22:25:03 +00:00
|
|
|
fn convert_impl_item(tcx: TyCtxt<'_>, impl_item_id: hir::ImplItemId) {
|
2022-10-27 03:02:18 +00:00
|
|
|
let def_id = impl_item_id.owner_id;
|
2020-05-01 09:32:20 +00:00
|
|
|
tcx.ensure().generics_of(def_id);
|
|
|
|
tcx.ensure().type_of(def_id);
|
|
|
|
tcx.ensure().predicates_of(def_id);
|
2021-01-30 22:25:03 +00:00
|
|
|
let impl_item = tcx.hir().impl_item(impl_item_id);
|
2020-02-17 20:07:50 +00:00
|
|
|
match impl_item.kind {
|
2020-03-05 15:57:34 +00:00
|
|
|
hir::ImplItemKind::Fn(..) => {
|
2022-11-06 16:28:07 +00:00
|
|
|
tcx.ensure().codegen_fn_attrs(def_id);
|
2020-05-01 09:32:20 +00:00
|
|
|
tcx.ensure().fn_sig(def_id);
|
2020-02-17 20:07:50 +00:00
|
|
|
}
|
2022-10-09 07:09:57 +00:00
|
|
|
hir::ImplItemKind::Type(_) => {
|
2020-02-17 20:07:50 +00:00
|
|
|
// Account for `type T = _;`
|
2022-01-05 10:43:21 +00:00
|
|
|
let mut visitor = HirPlaceholderCollector::default();
|
2020-02-17 20:07:50 +00:00
|
|
|
visitor.visit_impl_item(impl_item);
|
2021-02-10 15:49:23 +00:00
|
|
|
|
2022-02-07 21:58:30 +00:00
|
|
|
placeholder_type_error(tcx, None, visitor.0, false, None, "associated type");
|
2020-02-17 20:07:50 +00:00
|
|
|
}
|
|
|
|
hir::ImplItemKind::Const(..) => {}
|
2017-05-13 14:11:52 +00:00
|
|
|
}
|
2016-11-08 18:23:59 +00:00
|
|
|
}
|
|
|
|
|
2022-10-30 09:17:16 +00:00
|
|
|
fn convert_variant_ctor(tcx: TyCtxt<'_>, def_id: LocalDefId) {
|
2020-05-01 09:32:20 +00:00
|
|
|
tcx.ensure().generics_of(def_id);
|
|
|
|
tcx.ensure().type_of(def_id);
|
|
|
|
tcx.ensure().predicates_of(def_id);
|
2015-07-22 18:53:52 +00:00
|
|
|
}
|
|
|
|
|
2022-10-30 09:17:16 +00:00
|
|
|
fn convert_enum_variant_types(tcx: TyCtxt<'_>, def_id: DefId) {
|
2017-04-24 12:20:46 +00:00
|
|
|
let def = tcx.adt_def(def_id);
|
2022-03-04 20:28:41 +00:00
|
|
|
let repr_type = def.repr().discr_type();
|
2017-02-05 05:01:48 +00:00
|
|
|
let initial = repr_type.initial_discriminant(tcx);
|
2019-09-09 12:26:25 +00:00
|
|
|
let mut prev_discr = None::<Discr<'_>>;
|
2017-02-05 05:01:48 +00:00
|
|
|
|
|
|
|
// fill the discriminant values and field types
|
2022-10-30 09:17:16 +00:00
|
|
|
for variant in def.variants() {
|
2018-01-25 15:44:45 +00:00
|
|
|
let wrapped_discr = prev_discr.map_or(initial, |d| d.wrap_incr(tcx));
|
2018-08-19 16:34:21 +00:00
|
|
|
prev_discr = Some(
|
2022-10-30 09:17:16 +00:00
|
|
|
if let ty::VariantDiscr::Explicit(const_def_id) = variant.discr {
|
|
|
|
def.eval_explicit_discr(tcx, const_def_id)
|
2018-08-19 16:34:21 +00: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);
|
|
|
|
struct_span_err!(tcx.sess, span, E0370, "enum discriminant overflowed")
|
|
|
|
.span_label(span, format!("overflowed on value after {}", prev_discr.unwrap()))
|
2018-09-26 15:32:23 +00:00
|
|
|
.note(&format!(
|
|
|
|
"explicitly set `{} = {}` if that is desired outcome",
|
2022-10-30 09:17:16 +00:00
|
|
|
tcx.item_name(variant.def_id),
|
|
|
|
wrapped_discr
|
2018-09-26 15:32:23 +00:00
|
|
|
))
|
|
|
|
.emit();
|
2018-08-19 16:34:21 +00:00
|
|
|
None
|
|
|
|
}
|
|
|
|
.unwrap_or(wrapped_discr),
|
|
|
|
);
|
2017-02-05 05:01:48 +00:00
|
|
|
|
2022-10-30 09:17:16 +00:00
|
|
|
for f in &variant.fields {
|
|
|
|
tcx.ensure().generics_of(f.did);
|
|
|
|
tcx.ensure().type_of(f.did);
|
|
|
|
tcx.ensure().predicates_of(f.did);
|
2015-10-01 21:03:22 +00:00
|
|
|
}
|
2015-07-22 18:53:52 +00:00
|
|
|
|
2015-08-05 22:29:52 +00:00
|
|
|
// Convert the ctor, if any. This also registers the variant as
|
|
|
|
// an item.
|
2022-10-25 16:15:15 +00:00
|
|
|
if let Some(ctor_def_id) = variant.ctor_def_id() {
|
2022-10-30 09:17:16 +00:00
|
|
|
convert_variant_ctor(tcx, ctor_def_id.expect_local());
|
2019-03-21 22:38:50 +00:00
|
|
|
}
|
2015-07-22 18:53:52 +00:00
|
|
|
}
|
|
|
|
}
|
2014-02-24 07:17:02 +00:00
|
|
|
|
2019-06-21 21:49:03 +00:00
|
|
|
fn convert_variant(
|
|
|
|
tcx: TyCtxt<'_>,
|
2020-04-09 08:43:00 +00:00
|
|
|
variant_did: Option<LocalDefId>,
|
2018-12-01 02:47:08 +00:00
|
|
|
ident: Ident,
|
2018-08-19 16:34:21 +00:00
|
|
|
discr: ty::VariantDiscr,
|
2019-11-29 08:26:18 +00:00
|
|
|
def: &hir::VariantData<'_>,
|
2018-09-22 18:53:58 +00:00
|
|
|
adt_kind: ty::AdtKind,
|
2020-04-12 12:45:41 +00:00
|
|
|
parent_did: LocalDefId,
|
2018-08-19 16:34:21 +00:00
|
|
|
) -> ty::VariantDef {
|
2020-04-19 11:00:18 +00:00
|
|
|
let mut seen_fields: FxHashMap<Ident, Span> = Default::default();
|
2018-08-19 16:34:21 +00:00
|
|
|
let fields = def
|
|
|
|
.fields()
|
|
|
|
.iter()
|
|
|
|
.map(|f| {
|
2020-03-13 22:36:46 +00:00
|
|
|
let dup_span = seen_fields.get(&f.ident.normalize_to_macros_2_0()).cloned();
|
2018-08-19 16:34:21 +00:00
|
|
|
if let Some(prev_span) = dup_span {
|
2020-08-27 10:00:21 +00:00
|
|
|
tcx.sess.emit_err(errors::FieldAlreadyDeclared {
|
|
|
|
field_name: f.ident,
|
|
|
|
span: f.span,
|
|
|
|
prev_span,
|
|
|
|
});
|
2018-08-19 16:34:21 +00:00
|
|
|
} else {
|
2020-03-13 22:36:46 +00:00
|
|
|
seen_fields.insert(f.ident.normalize_to_macros_2_0(), f.span);
|
2018-08-19 16:34:21 +00:00
|
|
|
}
|
2016-02-27 00:05:14 +00:00
|
|
|
|
2022-11-06 19:46:55 +00:00
|
|
|
ty::FieldDef {
|
|
|
|
did: f.def_id.to_def_id(),
|
|
|
|
name: f.ident.name,
|
|
|
|
vis: tcx.visibility(f.def_id),
|
|
|
|
}
|
2018-08-19 16:34:21 +00:00
|
|
|
})
|
|
|
|
.collect();
|
2019-03-18 03:09:53 +00:00
|
|
|
let recovered = match def {
|
2019-03-21 22:38:50 +00:00
|
|
|
hir::VariantData::Struct(_, r) => *r,
|
2019-03-18 03:09:53 +00:00
|
|
|
_ => false,
|
|
|
|
};
|
2019-03-21 22:38:50 +00:00
|
|
|
ty::VariantDef::new(
|
2022-01-03 03:37:05 +00:00
|
|
|
ident.name,
|
2020-04-09 08:43:00 +00:00
|
|
|
variant_did.map(LocalDefId::to_def_id),
|
2022-10-25 16:15:15 +00:00
|
|
|
def.ctor().map(|(kind, _, def_id)| (kind, def_id.to_def_id())),
|
2017-08-07 05:54:09 +00:00
|
|
|
discr,
|
|
|
|
fields,
|
2019-03-21 22:38:50 +00:00
|
|
|
adt_kind,
|
2020-04-12 12:45:41 +00:00
|
|
|
parent_did.to_def_id(),
|
2019-03-18 03:09:53 +00:00
|
|
|
recovered,
|
2020-07-28 17:31:48 +00:00
|
|
|
adt_kind == AdtKind::Struct && tcx.has_attr(parent_did.to_def_id(), sym::non_exhaustive)
|
|
|
|
|| variant_did.map_or(false, |variant_did| {
|
|
|
|
tcx.has_attr(variant_did.to_def_id(), sym::non_exhaustive)
|
|
|
|
}),
|
2018-12-01 02:47:08 +00:00
|
|
|
)
|
2015-07-22 18:53:52 +00:00
|
|
|
}
|
2014-02-24 07:17:02 +00:00
|
|
|
|
2022-03-04 20:28:41 +00:00
|
|
|
fn adt_def<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId) -> ty::AdtDef<'tcx> {
|
2020-01-05 01:37:57 +00:00
|
|
|
use rustc_hir::*;
|
2016-11-24 23:33:29 +00:00
|
|
|
|
2020-04-12 12:45:41 +00:00
|
|
|
let def_id = def_id.expect_local();
|
2020-08-12 10:22:56 +00:00
|
|
|
let hir_id = tcx.hir().local_def_id_to_hir_id(def_id);
|
2022-02-18 23:44:45 +00:00
|
|
|
let Node::Item(item) = tcx.hir().get(hir_id) else {
|
|
|
|
bug!();
|
2017-02-13 23:11:24 +00:00
|
|
|
};
|
2017-02-05 05:01:48 +00:00
|
|
|
|
2022-11-06 21:06:11 +00:00
|
|
|
let repr = tcx.repr_options_of_def(def_id.to_def_id());
|
2019-09-26 16:51:36 +00:00
|
|
|
let (kind, variants) = match item.kind {
|
2018-07-11 15:36:06 +00:00
|
|
|
ItemKind::Enum(ref def, _) => {
|
2017-02-13 23:11:24 +00:00
|
|
|
let mut distance_from_explicit = 0;
|
2019-03-21 22:38:50 +00:00
|
|
|
let variants = def
|
|
|
|
.variants
|
|
|
|
.iter()
|
|
|
|
.map(|v| {
|
2019-08-14 00:40:21 +00:00
|
|
|
let discr = if let Some(ref e) = v.disr_expr {
|
2019-03-21 22:38:50 +00: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 22:38:50 +00:00
|
|
|
} else {
|
|
|
|
ty::VariantDiscr::Relative(distance_from_explicit)
|
|
|
|
};
|
|
|
|
distance_from_explicit += 1;
|
|
|
|
|
2019-08-14 00:40:21 +00:00
|
|
|
convert_variant(
|
|
|
|
tcx,
|
2022-11-06 19:46:55 +00:00
|
|
|
Some(v.def_id),
|
2019-08-14 00:40:21 +00:00
|
|
|
v.ident,
|
|
|
|
discr,
|
|
|
|
&v.data,
|
|
|
|
AdtKind::Enum,
|
|
|
|
def_id,
|
|
|
|
)
|
2019-03-21 22:38:50 +00:00
|
|
|
})
|
|
|
|
.collect();
|
2017-02-13 23:11:24 +00:00
|
|
|
|
2019-03-21 22:38:50 +00:00
|
|
|
(AdtKind::Enum, variants)
|
2017-02-13 23:11:24 +00:00
|
|
|
}
|
2022-10-25 16:15:15 +00:00
|
|
|
ItemKind::Struct(ref def, _) | ItemKind::Union(ref def, _) => {
|
|
|
|
let adt_kind = match item.kind {
|
|
|
|
ItemKind::Struct(..) => AdtKind::Struct,
|
|
|
|
_ => AdtKind::Union,
|
|
|
|
};
|
2019-03-21 22:38:50 +00:00
|
|
|
let variants = std::iter::once(convert_variant(
|
|
|
|
tcx,
|
2022-11-06 19:46:55 +00:00
|
|
|
None,
|
2019-03-21 22:38:50 +00:00
|
|
|
item.ident,
|
|
|
|
ty::VariantDiscr::Relative(0),
|
|
|
|
def,
|
2022-10-25 16:15:15 +00:00
|
|
|
adt_kind,
|
2019-03-21 22:38:50 +00:00
|
|
|
def_id,
|
|
|
|
))
|
|
|
|
.collect();
|
|
|
|
|
2022-10-25 16:15:15 +00:00
|
|
|
(adt_kind, variants)
|
2019-03-21 22:38:50 +00:00
|
|
|
}
|
2018-08-19 16:34:21 +00:00
|
|
|
_ => bug!(),
|
2017-02-13 23:11:24 +00:00
|
|
|
};
|
2020-04-12 12:45:41 +00:00
|
|
|
tcx.alloc_adt_def(def_id.to_def_id(), kind, variants, repr)
|
2016-08-08 22:18:47 +00:00
|
|
|
}
|
|
|
|
|
2020-03-27 19:26:20 +00:00
|
|
|
fn trait_def(tcx: TyCtxt<'_>, def_id: DefId) -> ty::TraitDef {
|
2021-10-20 20:38:10 +00:00
|
|
|
let item = tcx.hir().expect_item(def_id.expect_local());
|
2015-02-11 15:25:52 +00:00
|
|
|
|
2021-12-21 15:40:50 +00:00
|
|
|
let (is_auto, unsafety, items) = match item.kind {
|
|
|
|
hir::ItemKind::Trait(is_auto, unsafety, .., items) => {
|
|
|
|
(is_auto == hir::IsAuto::Yes, unsafety, items)
|
|
|
|
}
|
|
|
|
hir::ItemKind::TraitAlias(..) => (false, hir::Unsafety::Normal, &[][..]),
|
2017-02-13 23:11:24 +00:00
|
|
|
_ => span_bug!(item.span, "trait_def_of_item invoked on non-trait"),
|
|
|
|
};
|
2013-12-19 00:05:47 +00:00
|
|
|
|
2019-05-08 03:21:18 +00:00
|
|
|
let paren_sugar = tcx.has_attr(def_id, sym::rustc_paren_sugar);
|
2018-02-14 15:11:02 +00:00
|
|
|
if paren_sugar && !tcx.features().unboxed_closures {
|
2019-12-31 20:25:16 +00:00
|
|
|
tcx.sess
|
|
|
|
.struct_span_err(
|
|
|
|
item.span,
|
|
|
|
"the `#[rustc_paren_sugar]` attribute is a temporary means of controlling \
|
2020-01-26 01:09:23 +00:00
|
|
|
which traits can use parenthetical notation",
|
2019-12-31 20:25:16 +00:00
|
|
|
)
|
|
|
|
.help("add `#![feature(unboxed_closures)]` to the crate attributes to use it")
|
|
|
|
.emit();
|
2017-02-13 23:11:24 +00:00
|
|
|
}
|
2016-09-12 22:09:49 +00:00
|
|
|
|
2019-05-08 03:21:18 +00:00
|
|
|
let is_marker = tcx.has_attr(def_id, sym::marker);
|
2021-04-12 23:03:53 +00:00
|
|
|
let skip_array_during_method_dispatch =
|
|
|
|
tcx.has_attr(def_id, sym::rustc_skip_array_during_method_dispatch);
|
2020-02-08 17:56:25 +00:00
|
|
|
let spec_kind = if tcx.has_attr(def_id, sym::rustc_unsafe_specialization_marker) {
|
|
|
|
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 15:40:50 +00:00
|
|
|
let must_implement_one_of = tcx
|
2022-05-02 07:31:56 +00:00
|
|
|
.get_attr(def_id, sym::rustc_must_implement_one_of)
|
2021-12-21 15:40:50 +00: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 => {
|
|
|
|
tcx.sess
|
|
|
|
.struct_span_err(
|
|
|
|
attr.span,
|
|
|
|
"the `#[rustc_must_implement_one_of]` attribute must be \
|
2022-12-09 18:44:11 +00:00
|
|
|
used with at least 2 args",
|
2021-12-21 15:40:50 +00:00
|
|
|
)
|
|
|
|
.emit();
|
|
|
|
|
|
|
|
None
|
|
|
|
}
|
|
|
|
Some(items) => items
|
|
|
|
.into_iter()
|
|
|
|
.map(|item| item.ident().ok_or(item.span()))
|
|
|
|
.collect::<Result<Box<[_]>, _>>()
|
|
|
|
.map_err(|span| {
|
2022-01-04 10:21:56 +00:00
|
|
|
tcx.sess
|
|
|
|
.struct_span_err(span, "must be a name of an associated function")
|
|
|
|
.emit();
|
2021-12-21 15:40:50 +00:00
|
|
|
})
|
|
|
|
.ok()
|
|
|
|
.zip(Some(attr.span)),
|
|
|
|
// Error is reported by `rustc_attr!`
|
|
|
|
None => None,
|
|
|
|
})
|
|
|
|
// Check that all arguments of `#[rustc_must_implement_one_of]` reference
|
2022-01-04 10:21:56 +00:00
|
|
|
// functions in the trait with default implementations
|
2021-12-21 15:40:50 +00: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 { .. }) => {
|
2022-10-27 03:02:18 +00:00
|
|
|
if !tcx.impl_defaultness(item.id.owner_id).has_value() {
|
2021-12-21 15:40:50 +00:00
|
|
|
tcx.sess
|
|
|
|
.struct_span_err(
|
|
|
|
item.span,
|
2022-12-09 18:44:11 +00:00
|
|
|
"function doesn't have a default implementation",
|
2021-12-21 15:40:50 +00:00
|
|
|
)
|
|
|
|
.span_note(attr_span, "required by this annotation")
|
|
|
|
.emit();
|
|
|
|
|
|
|
|
return Some(());
|
|
|
|
}
|
|
|
|
|
|
|
|
return None;
|
|
|
|
}
|
2022-01-27 09:44:25 +00:00
|
|
|
Some(item) => {
|
|
|
|
tcx.sess
|
2022-12-09 18:44:11 +00:00
|
|
|
.struct_span_err(item.span, "not a function")
|
2022-01-27 09:44:25 +00:00
|
|
|
.span_note(attr_span, "required by this annotation")
|
|
|
|
.note(
|
2022-12-09 18:44:11 +00:00
|
|
|
"all `#[rustc_must_implement_one_of]` arguments must be associated \
|
|
|
|
function names",
|
2022-01-27 09:44:25 +00:00
|
|
|
)
|
|
|
|
.emit();
|
|
|
|
}
|
|
|
|
None => {
|
|
|
|
tcx.sess
|
2022-12-09 18:44:11 +00:00
|
|
|
.struct_span_err(ident.span, "function not found in this trait")
|
2022-01-27 09:44:25 +00:00
|
|
|
.emit();
|
|
|
|
}
|
2021-12-21 15:40:50 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
Some(())
|
|
|
|
});
|
|
|
|
|
|
|
|
(errors.count() == 0).then_some(list)
|
2022-01-14 13:38:47 +00:00
|
|
|
})
|
|
|
|
// Check for duplicates
|
|
|
|
.and_then(|list| {
|
2022-01-14 23:04:58 +00:00
|
|
|
let mut set: FxHashMap<Symbol, Span> = FxHashMap::default();
|
2022-01-14 13:38:47 +00:00
|
|
|
let mut no_dups = true;
|
|
|
|
|
|
|
|
for ident in &*list {
|
2022-01-14 23:04:58 +00:00
|
|
|
if let Some(dup) = set.insert(ident.name, ident.span) {
|
2022-01-14 13:38:47 +00:00
|
|
|
tcx.sess
|
2022-12-09 18:44:11 +00:00
|
|
|
.struct_span_err(vec![dup, ident.span], "functions names are duplicated")
|
|
|
|
.note("all `#[rustc_must_implement_one_of]` arguments must be unique")
|
2022-01-14 13:38:47 +00:00
|
|
|
.emit();
|
|
|
|
|
|
|
|
no_dups = false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
no_dups.then_some(list)
|
2021-12-21 15:40:50 +00:00
|
|
|
});
|
|
|
|
|
2021-04-12 23:03:53 +00:00
|
|
|
ty::TraitDef::new(
|
|
|
|
def_id,
|
|
|
|
unsafety,
|
|
|
|
paren_sugar,
|
|
|
|
is_auto,
|
|
|
|
is_marker,
|
|
|
|
skip_array_during_method_dispatch,
|
|
|
|
spec_kind,
|
2021-12-21 15:40:50 +00:00
|
|
|
must_implement_one_of,
|
2021-04-12 23:03:53 +00:00
|
|
|
)
|
2012-05-16 02:36:04 +00:00
|
|
|
}
|
|
|
|
|
2020-01-15 00:18:21 +00:00
|
|
|
fn are_suggestable_generic_args(generic_args: &[hir::GenericArg<'_>]) -> bool {
|
2021-04-24 21:41:57 +00:00
|
|
|
generic_args.iter().any(|arg| match arg {
|
|
|
|
hir::GenericArg::Type(ty) => is_suggestable_infer_ty(ty),
|
|
|
|
hir::GenericArg::Infer(_) => true,
|
|
|
|
_ => false,
|
|
|
|
})
|
2020-01-15 00:18:21 +00:00
|
|
|
}
|
|
|
|
|
2020-03-06 11:13:55 +00:00
|
|
|
/// Whether `ty` is a type with `_` placeholders that can be inferred. Used in diagnostics only to
|
2019-12-27 23:45:39 +00:00
|
|
|
/// use inference to provide suggestions for the appropriate type if possible.
|
|
|
|
fn is_suggestable_infer_ty(ty: &hir::Ty<'_>) -> bool {
|
2022-01-05 10:43:21 +00:00
|
|
|
debug!(?ty);
|
2020-01-09 21:46:37 +00:00
|
|
|
use hir::TyKind::*;
|
2019-12-23 22:16:34 +00:00
|
|
|
match &ty.kind {
|
2020-01-09 21:46:37 +00:00
|
|
|
Infer => true,
|
2022-01-05 10:43:21 +00:00
|
|
|
Slice(ty) => is_suggestable_infer_ty(ty),
|
|
|
|
Array(ty, length) => {
|
|
|
|
is_suggestable_infer_ty(ty) || matches!(length, hir::ArrayLen::Infer(_, _))
|
|
|
|
}
|
2020-01-09 21:46:37 +00:00
|
|
|
Tup(tys) => tys.iter().any(is_suggestable_infer_ty),
|
|
|
|
Ptr(mut_ty) | Rptr(_, mut_ty) => is_suggestable_infer_ty(mut_ty.ty),
|
2022-09-06 15:37:00 +00:00
|
|
|
OpaqueDef(_, generic_args, _) => are_suggestable_generic_args(generic_args),
|
2020-01-15 00:18:21 +00:00
|
|
|
Path(hir::QPath::TypeRelative(ty, segment)) => {
|
2021-01-02 18:45:11 +00:00
|
|
|
is_suggestable_infer_ty(ty) || are_suggestable_generic_args(segment.args().args)
|
2020-01-15 00:18:21 +00:00
|
|
|
}
|
|
|
|
Path(hir::QPath::Resolved(ty_opt, hir::Path { segments, .. })) => {
|
|
|
|
ty_opt.map_or(false, is_suggestable_infer_ty)
|
2021-01-02 18:45:11 +00:00
|
|
|
|| segments.iter().any(|segment| are_suggestable_generic_args(segment.args().args))
|
2020-01-15 00:18:21 +00:00
|
|
|
}
|
2019-12-23 22:16:34 +00:00
|
|
|
_ => false,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-12-14 01:45:08 +00:00
|
|
|
pub fn get_infer_ret_ty<'hir>(output: &'hir hir::FnRetTy<'hir>) -> Option<&'hir hir::Ty<'hir>> {
|
2021-09-30 17:38:50 +00:00
|
|
|
if let hir::FnRetTy::Return(ty) = output {
|
2019-12-27 23:45:39 +00:00
|
|
|
if is_suggestable_infer_ty(ty) {
|
2021-09-30 17:38:50 +00:00
|
|
|
return Some(&*ty);
|
2019-07-15 16:30:48 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
None
|
|
|
|
}
|
|
|
|
|
2022-06-26 04:10:07 +00:00
|
|
|
#[instrument(level = "debug", skip(tcx))]
|
2019-06-21 21:49:03 +00:00
|
|
|
fn fn_sig(tcx: TyCtxt<'_>, def_id: DefId) -> ty::PolyFnSig<'_> {
|
2020-01-05 01:37:57 +00:00
|
|
|
use rustc_hir::Node::*;
|
|
|
|
use rustc_hir::*;
|
2017-05-13 14:11:52 +00:00
|
|
|
|
2020-04-17 14:17:01 +00:00
|
|
|
let def_id = def_id.expect_local();
|
2020-08-12 10:22:56 +00:00
|
|
|
let hir_id = tcx.hir().local_def_id_to_hir_id(def_id);
|
2017-05-13 14:11:52 +00:00
|
|
|
|
2020-04-17 14:17:01 +00:00
|
|
|
let icx = ItemCtxt::new(tcx, def_id.to_def_id());
|
2017-05-13 14:11:52 +00:00
|
|
|
|
2019-06-20 08:39:19 +00:00
|
|
|
match tcx.hir().get(hir_id) {
|
2018-08-22 22:05:26 +00:00
|
|
|
TraitItem(hir::TraitItem {
|
2020-03-05 15:57:34 +00:00
|
|
|
kind: TraitItemKind::Fn(sig, TraitFn::Provided(_)),
|
2019-12-23 22:16:34 +00:00
|
|
|
generics,
|
2018-08-19 16:34:21 +00:00
|
|
|
..
|
|
|
|
})
|
2022-02-07 21:58:30 +00:00
|
|
|
| Item(hir::Item { kind: ItemKind::Fn(sig, generics, _), .. }) => {
|
|
|
|
infer_return_ty_for_fn_sig(tcx, sig, generics, def_id, &icx)
|
2022-03-28 02:43:08 +00:00
|
|
|
}
|
2021-02-24 20:21:18 +00:00
|
|
|
|
2022-02-07 21:58:30 +00: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
|
2022-03-28 02:43:08 +00:00
|
|
|
if let Item(hir::Item { kind: ItemKind::Impl(i), .. }) =
|
|
|
|
tcx.hir().get(tcx.hir().get_parent_node(hir_id))
|
|
|
|
&& i.of_trait.is_some()
|
|
|
|
{
|
|
|
|
<dyn AstConv<'_>>::ty_of_fn(
|
2019-12-23 22:16:34 +00:00
|
|
|
&icx,
|
2020-10-26 18:18:31 +00:00
|
|
|
hir_id,
|
2019-12-23 22:16:34 +00:00
|
|
|
sig.header.unsafety,
|
|
|
|
sig.header.abi,
|
2021-09-30 17:38:50 +00:00
|
|
|
sig.decl,
|
2022-02-07 21:58:30 +00:00
|
|
|
Some(generics),
|
2021-02-10 15:49:23 +00:00
|
|
|
None,
|
2022-03-28 02:43:08 +00:00
|
|
|
)
|
|
|
|
} else {
|
2022-02-07 21:58:30 +00:00
|
|
|
infer_return_ty_for_fn_sig(tcx, sig, generics, def_id, &icx)
|
2019-12-22 22:42:04 +00:00
|
|
|
}
|
2019-07-15 16:30:48 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
TraitItem(hir::TraitItem {
|
2020-08-12 21:02:14 +00:00
|
|
|
kind: TraitItemKind::Fn(FnSig { header, decl, span: _ }, _),
|
2019-12-23 22:16:34 +00:00
|
|
|
generics,
|
2019-07-15 16:30:48 +00:00
|
|
|
..
|
2021-03-07 15:47:39 +00:00
|
|
|
}) => <dyn AstConv<'_>>::ty_of_fn(
|
2021-02-10 15:49:23 +00:00
|
|
|
&icx,
|
2020-10-26 18:18:31 +00:00
|
|
|
hir_id,
|
2021-02-10 15:49:23 +00:00
|
|
|
header.unsafety,
|
|
|
|
header.abi,
|
|
|
|
decl,
|
2022-02-07 21:58:30 +00:00
|
|
|
Some(generics),
|
2021-02-10 15:49:23 +00:00
|
|
|
None,
|
|
|
|
),
|
2018-08-19 16:34:21 +00:00
|
|
|
|
2022-02-07 21:58:30 +00:00
|
|
|
ForeignItem(&hir::ForeignItem { kind: ForeignItemKind::Fn(fn_decl, _, _), .. }) => {
|
2019-06-14 16:58:55 +00:00
|
|
|
let abi = tcx.hir().get_foreign_abi(hir_id);
|
2022-02-07 21:58:30 +00:00
|
|
|
compute_sig_of_foreign_fn_decl(tcx, def_id.to_def_id(), fn_decl, abi)
|
2017-05-13 14:11:52 +00:00
|
|
|
}
|
|
|
|
|
2022-10-25 16:15:15 +00:00
|
|
|
Ctor(data) | Variant(hir::Variant { data, .. }) if data.ctor().is_some() => {
|
2021-10-21 17:41:47 +00:00
|
|
|
let ty = tcx.type_of(tcx.hir().get_parent_item(hir_id));
|
2022-11-06 19:46:55 +00:00
|
|
|
let inputs = data.fields().iter().map(|f| tcx.type_of(f.def_id));
|
2021-07-02 09:48:34 +00:00
|
|
|
ty::Binder::dummy(tcx.mk_fn_sig(
|
|
|
|
inputs,
|
|
|
|
ty,
|
|
|
|
false,
|
|
|
|
hir::Unsafety::Normal,
|
|
|
|
abi::Abi::Rust,
|
|
|
|
))
|
2017-05-13 14:11:52 +00:00
|
|
|
}
|
|
|
|
|
2022-06-11 19:25:25 +00:00
|
|
|
Expr(&hir::Expr { kind: hir::ExprKind::Closure { .. }, .. }) => {
|
2017-12-06 20:15:27 +00: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
|
|
|
|
// closure type as part of the `ClosureSubsts`.
|
2017-12-01 14:26:13 +00:00
|
|
|
//
|
2020-03-18 00:16:01 +00:00
|
|
|
// To get the signature of a closure, you should use the
|
|
|
|
// `sig` method on the `ClosureSubsts`:
|
2017-12-01 14:26:13 +00:00
|
|
|
//
|
2020-03-18 00:16:01 +00:00
|
|
|
// substs.as_closure().sig(def_id, tcx)
|
|
|
|
bug!(
|
|
|
|
"to get the signature of a closure, use `substs.as_closure().sig()` not `fn_sig()`",
|
|
|
|
);
|
2017-05-13 14:11:52 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
x => {
|
|
|
|
bug!("unexpected sort of node in fn_sig(): {:?}", x);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-03-28 02:43:08 +00:00
|
|
|
fn infer_return_ty_for_fn_sig<'tcx>(
|
|
|
|
tcx: TyCtxt<'tcx>,
|
|
|
|
sig: &hir::FnSig<'_>,
|
|
|
|
generics: &hir::Generics<'_>,
|
|
|
|
def_id: LocalDefId,
|
|
|
|
icx: &ItemCtxt<'tcx>,
|
|
|
|
) -> ty::PolyFnSig<'tcx> {
|
|
|
|
let hir_id = tcx.hir().local_def_id_to_hir_id(def_id);
|
|
|
|
|
|
|
|
match get_infer_ret_ty(&sig.decl.output) {
|
|
|
|
Some(ty) => {
|
|
|
|
let fn_sig = tcx.typeck(def_id).liberated_fn_sigs()[hir_id];
|
|
|
|
// Typeck doesn't expect erased regions to be returned from `type_of`.
|
2022-06-27 13:55:03 +00:00
|
|
|
let fn_sig = tcx.fold_regions(fn_sig, |r, _| match *r {
|
2022-03-28 02:43:08 +00:00
|
|
|
ty::ReErased => tcx.lifetimes.re_static,
|
|
|
|
_ => r,
|
|
|
|
});
|
|
|
|
let fn_sig = ty::Binder::dummy(fn_sig);
|
|
|
|
|
|
|
|
let mut visitor = HirPlaceholderCollector::default();
|
|
|
|
visitor.visit_ty(ty);
|
|
|
|
let mut diag = bad_placeholder(tcx, visitor.0, "return type");
|
|
|
|
let ret_ty = fn_sig.skip_binder().output();
|
2022-07-22 00:28:03 +00:00
|
|
|
if ret_ty.is_suggestable(tcx, false) {
|
2022-04-25 03:11:51 +00:00
|
|
|
diag.span_suggestion(
|
|
|
|
ty.span,
|
|
|
|
"replace with the correct return type",
|
2022-06-13 06:48:40 +00:00
|
|
|
ret_ty,
|
2022-04-25 03:11:51 +00:00
|
|
|
Applicability::MachineApplicable,
|
|
|
|
);
|
|
|
|
} else if matches!(ret_ty.kind(), ty::FnDef(..)) {
|
|
|
|
let fn_sig = ret_ty.fn_sig(tcx);
|
2022-07-22 00:28:03 +00:00
|
|
|
if fn_sig
|
|
|
|
.skip_binder()
|
|
|
|
.inputs_and_output
|
|
|
|
.iter()
|
|
|
|
.all(|t| t.is_suggestable(tcx, false))
|
|
|
|
{
|
2022-03-28 02:43:08 +00:00
|
|
|
diag.span_suggestion(
|
|
|
|
ty.span,
|
|
|
|
"replace with the correct return type",
|
2022-06-13 06:48:40 +00:00
|
|
|
fn_sig,
|
2022-04-25 03:11:51 +00:00
|
|
|
Applicability::MachineApplicable,
|
2022-03-28 02:43:08 +00:00
|
|
|
);
|
|
|
|
}
|
2022-04-25 03:11:51 +00:00
|
|
|
} else if ret_ty.is_closure() {
|
|
|
|
// We're dealing with a closure, so we should suggest using `impl Fn` or trait bounds
|
|
|
|
// to prevent the user from getting a papercut while trying to use the unique closure
|
|
|
|
// syntax (e.g. `[closure@src/lib.rs:2:5: 2:9]`).
|
|
|
|
diag.help("consider using an `Fn`, `FnMut`, or `FnOnce` trait bound");
|
|
|
|
diag.note("for more information on `Fn` traits and closure types, see https://doc.rust-lang.org/book/ch13-01-closures.html");
|
2022-03-28 02:43:08 +00:00
|
|
|
}
|
|
|
|
diag.emit();
|
|
|
|
|
|
|
|
fn_sig
|
|
|
|
}
|
|
|
|
None => <dyn AstConv<'_>>::ty_of_fn(
|
|
|
|
icx,
|
|
|
|
hir_id,
|
|
|
|
sig.header.unsafety,
|
|
|
|
sig.header.abi,
|
|
|
|
sig.decl,
|
2022-02-07 21:58:30 +00:00
|
|
|
Some(generics),
|
2022-03-28 02:43:08 +00:00
|
|
|
None,
|
|
|
|
),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-06-21 21:49:03 +00:00
|
|
|
fn impl_trait_ref(tcx: TyCtxt<'_>, def_id: DefId) -> Option<ty::TraitRef<'_>> {
|
2017-02-14 09:32:00 +00:00
|
|
|
let icx = ItemCtxt::new(tcx, def_id);
|
2022-10-20 09:39:09 +00:00
|
|
|
let item = tcx.hir().expect_item(def_id.expect_local());
|
|
|
|
match item.kind {
|
2020-11-22 22:46:21 +00:00
|
|
|
hir::ItemKind::Impl(ref impl_) => impl_.of_trait.as_ref().map(|ast_trait_ref| {
|
2020-01-18 00:14:29 +00:00
|
|
|
let selfty = tcx.type_of(def_id);
|
2022-10-20 09:39:09 +00:00
|
|
|
<dyn AstConv<'_>>::instantiate_mono_trait_ref(
|
|
|
|
&icx,
|
|
|
|
ast_trait_ref,
|
|
|
|
selfty,
|
2022-10-25 18:28:04 +00:00
|
|
|
check_impl_constness(tcx, impl_.constness, ast_trait_ref),
|
2022-10-20 09:39:09 +00:00
|
|
|
)
|
2020-01-18 00:14:29 +00:00
|
|
|
}),
|
2018-08-19 16:34:21 +00:00
|
|
|
_ => bug!(),
|
2017-02-14 09:32:00 +00:00
|
|
|
}
|
2015-02-11 15:25:52 +00:00
|
|
|
}
|
|
|
|
|
2022-10-25 18:28:04 +00:00
|
|
|
fn check_impl_constness(
|
|
|
|
tcx: TyCtxt<'_>,
|
|
|
|
constness: hir::Constness,
|
|
|
|
ast_trait_ref: &hir::TraitRef<'_>,
|
|
|
|
) -> ty::BoundConstness {
|
|
|
|
match constness {
|
|
|
|
hir::Constness::Const => {
|
|
|
|
if let Some(trait_def_id) = ast_trait_ref.trait_def_id() && !tcx.has_attr(trait_def_id, sym::const_trait) {
|
|
|
|
let trait_name = tcx.item_name(trait_def_id).to_string();
|
|
|
|
tcx.sess.emit_err(errors::ConstImplForNonConstTrait {
|
|
|
|
trait_ref_span: ast_trait_ref.path.span,
|
|
|
|
trait_name,
|
|
|
|
local_trait_span: trait_def_id.as_local().map(|_| tcx.def_span(trait_def_id).shrink_to_lo()),
|
|
|
|
marking: (),
|
|
|
|
adding: (),
|
|
|
|
});
|
|
|
|
ty::BoundConstness::NotConst
|
|
|
|
} else {
|
|
|
|
ty::BoundConstness::ConstIfConst
|
|
|
|
}
|
|
|
|
},
|
|
|
|
hir::Constness::NotConst => ty::BoundConstness::NotConst,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-07-13 21:09:46 +00:00
|
|
|
fn impl_polarity(tcx: TyCtxt<'_>, def_id: DefId) -> ty::ImplPolarity {
|
|
|
|
let is_rustc_reservation = tcx.has_attr(def_id, sym::rustc_reservation_impl);
|
2021-10-20 20:38:10 +00:00
|
|
|
let item = tcx.hir().expect_item(def_id.expect_local());
|
2019-09-26 16:51:36 +00:00
|
|
|
match &item.kind {
|
2020-11-22 22:46:21 +00:00
|
|
|
hir::ItemKind::Impl(hir::Impl {
|
|
|
|
polarity: hir::ImplPolarity::Negative(span),
|
|
|
|
of_trait,
|
|
|
|
..
|
|
|
|
}) => {
|
2019-07-13 21:09:46 +00:00
|
|
|
if is_rustc_reservation {
|
2021-01-11 19:45:33 +00:00
|
|
|
let span = span.to(of_trait.as_ref().map_or(*span, |t| t.path.span));
|
2020-03-02 23:26:00 +00:00
|
|
|
tcx.sess.span_err(span, "reservation impls can't be negative");
|
2019-07-13 21:09:46 +00:00
|
|
|
}
|
|
|
|
ty::ImplPolarity::Negative
|
|
|
|
}
|
2020-11-22 22:46:21 +00:00
|
|
|
hir::ItemKind::Impl(hir::Impl {
|
|
|
|
polarity: hir::ImplPolarity::Positive,
|
|
|
|
of_trait: None,
|
|
|
|
..
|
|
|
|
}) => {
|
2019-07-13 21:09:46 +00:00
|
|
|
if is_rustc_reservation {
|
|
|
|
tcx.sess.span_err(item.span, "reservation impls can't be inherent");
|
|
|
|
}
|
|
|
|
ty::ImplPolarity::Positive
|
|
|
|
}
|
2020-11-22 22:46:21 +00:00
|
|
|
hir::ItemKind::Impl(hir::Impl {
|
|
|
|
polarity: hir::ImplPolarity::Positive,
|
|
|
|
of_trait: Some(_),
|
|
|
|
..
|
|
|
|
}) => {
|
2019-07-13 21:09:46 +00:00
|
|
|
if is_rustc_reservation {
|
|
|
|
ty::ImplPolarity::Reservation
|
|
|
|
} else {
|
|
|
|
ty::ImplPolarity::Positive
|
|
|
|
}
|
|
|
|
}
|
2020-11-22 22:46:21 +00:00
|
|
|
item => bug!("impl_polarity: {:?} not an impl", item),
|
2017-04-20 17:37:02 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-02-18 15:39:39 +00:00
|
|
|
/// Returns the early-bound lifetimes declared in this generics
|
2019-02-08 13:53:55 +00:00
|
|
|
/// listing. For anything other than fns/methods, this is just all
|
2015-02-18 15:39:39 +00: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`.
|
2019-06-11 19:03:44 +00:00
|
|
|
fn early_bound_lifetimes_from_generics<'a, 'tcx: 'a>(
|
2019-06-13 21:48:52 +00:00
|
|
|
tcx: TyCtxt<'tcx>,
|
2019-12-01 15:08:58 +00:00
|
|
|
generics: &'a hir::Generics<'a>,
|
|
|
|
) -> impl Iterator<Item = &'a hir::GenericParam<'a>> + Captures<'tcx> {
|
2018-08-19 16:34:21 +00:00
|
|
|
generics.params.iter().filter(move |param| match param.kind {
|
2022-05-26 06:59:15 +00:00
|
|
|
GenericParamKind::Lifetime { .. } => !tcx.is_late_bound(param.hir_id),
|
2018-08-19 16:34:21 +00:00
|
|
|
_ => false,
|
|
|
|
})
|
2015-02-18 15:39:39 +00:00
|
|
|
}
|
|
|
|
|
2019-02-08 13:53:55 +00:00
|
|
|
/// Returns a list of type predicates for the definition with ID `def_id`, including inferred
|
|
|
|
/// lifetime constraints. This includes all predicates returned by `explicit_predicates_of`, plus
|
|
|
|
/// inferred constraints concerning which regions outlive other regions.
|
2022-06-26 04:10:07 +00:00
|
|
|
#[instrument(level = "debug", skip(tcx))]
|
2019-10-18 00:14:57 +00:00
|
|
|
fn predicates_defined_on(tcx: TyCtxt<'_>, def_id: DefId) -> ty::GenericPredicates<'_> {
|
2018-11-08 06:14:13 +00:00
|
|
|
let mut result = tcx.explicit_predicates_of(def_id);
|
2018-11-16 13:25:46 +00:00
|
|
|
debug!("predicates_defined_on: explicit_predicates_of({:?}) = {:?}", def_id, result,);
|
2018-11-08 06:14:13 +00:00
|
|
|
let inferred_outlives = tcx.inferred_outlives_of(def_id);
|
|
|
|
if !inferred_outlives.is_empty() {
|
2018-11-16 13:25:46 +00:00
|
|
|
debug!(
|
|
|
|
"predicates_defined_on: inferred_outlives_of({:?}) = {:?}",
|
|
|
|
def_id, inferred_outlives,
|
|
|
|
);
|
2022-11-25 19:35:27 +00:00
|
|
|
let inferred_outlives_iter =
|
|
|
|
inferred_outlives.iter().map(|(clause, span)| ((*clause).to_predicate(tcx), *span));
|
2019-10-18 01:24:22 +00:00
|
|
|
if result.predicates.is_empty() {
|
2022-11-25 19:35:27 +00:00
|
|
|
result.predicates = tcx.arena.alloc_from_iter(inferred_outlives_iter);
|
2019-10-18 01:24:22 +00:00
|
|
|
} else {
|
2022-11-25 19:35:27 +00:00
|
|
|
result.predicates = tcx.arena.alloc_from_iter(
|
|
|
|
result.predicates.into_iter().copied().chain(inferred_outlives_iter),
|
|
|
|
);
|
2019-10-18 01:24:22 +00:00
|
|
|
}
|
2017-09-26 04:36:38 +00:00
|
|
|
}
|
2020-09-10 06:52:02 +00:00
|
|
|
|
2019-01-04 13:27:55 +00:00
|
|
|
debug!("predicates_defined_on({:?}) = {:?}", def_id, result);
|
2018-11-08 06:14:13 +00:00
|
|
|
result
|
2017-09-23 18:55:40 +00:00
|
|
|
}
|
|
|
|
|
2019-06-11 20:35:39 +00:00
|
|
|
fn compute_sig_of_foreign_fn_decl<'tcx>(
|
2019-06-13 21:48:52 +00:00
|
|
|
tcx: TyCtxt<'tcx>,
|
2016-08-08 20:39:49 +00:00
|
|
|
def_id: DefId,
|
2019-12-01 15:08:58 +00:00
|
|
|
decl: &'tcx hir::FnDecl<'tcx>,
|
2018-08-19 16:34:21 +00:00
|
|
|
abi: abi::Abi,
|
|
|
|
) -> ty::PolyFnSig<'tcx> {
|
2018-08-22 13:56:37 +00:00
|
|
|
let unsafety = if abi == abi::Abi::RustIntrinsic {
|
2022-08-17 11:43:59 +00:00
|
|
|
intrinsic_operation_unsafety(tcx, def_id)
|
2018-08-22 13:56:37 +00:00
|
|
|
} else {
|
|
|
|
hir::Unsafety::Unsafe
|
|
|
|
};
|
2020-10-26 18:18:31 +00:00
|
|
|
let hir_id = tcx.hir().local_def_id_to_hir_id(def_id.expect_local());
|
2021-03-07 15:47:39 +00:00
|
|
|
let fty = <dyn AstConv<'_>>::ty_of_fn(
|
2020-03-23 01:50:30 +00:00
|
|
|
&ItemCtxt::new(tcx, def_id),
|
2020-10-26 18:18:31 +00:00
|
|
|
hir_id,
|
2020-03-23 01:50:30 +00:00
|
|
|
unsafety,
|
|
|
|
abi,
|
|
|
|
decl,
|
2022-02-07 21:58:30 +00:00
|
|
|
None,
|
2021-02-10 15:49:23 +00:00
|
|
|
None,
|
2020-03-23 01:50:30 +00:00
|
|
|
);
|
2012-05-16 02:36:04 +00: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
|
2018-08-19 16:34:21 +00:00
|
|
|
if abi != abi::Abi::RustIntrinsic
|
|
|
|
&& abi != abi::Abi::PlatformIntrinsic
|
|
|
|
&& !tcx.features().simd_ffi
|
|
|
|
{
|
2019-12-01 15:08:58 +00:00
|
|
|
let check = |ast_ty: &hir::Ty<'_>, ty: Ty<'_>| {
|
2016-02-23 19:06:32 +00:00
|
|
|
if ty.is_simd() {
|
2020-03-24 01:44:41 +00:00
|
|
|
let snip = tcx
|
|
|
|
.sess
|
|
|
|
.source_map()
|
|
|
|
.span_to_snippet(ast_ty.span)
|
2021-02-23 22:02:05 +00:00
|
|
|
.map_or_else(|_| String::new(), |s| format!(" `{}`", s));
|
2018-08-19 16:34:21 +00:00
|
|
|
tcx.sess
|
2018-09-26 15:32:23 +00:00
|
|
|
.struct_span_err(
|
|
|
|
ast_ty.span,
|
|
|
|
&format!(
|
2020-03-24 01:44:41 +00:00
|
|
|
"use of SIMD type{} in FFI is highly experimental and \
|
2020-01-26 01:09:23 +00:00
|
|
|
may result in invalid code",
|
2020-03-24 01:44:41 +00:00
|
|
|
snip
|
2018-09-26 15:32:23 +00:00
|
|
|
),
|
|
|
|
)
|
2019-07-07 09:37:34 +00:00
|
|
|
.help("add `#![feature(simd_ffi)]` to the crate attributes to enable")
|
2018-09-26 15:32:23 +00:00
|
|
|
.emit();
|
2016-02-23 19:06:32 +00:00
|
|
|
}
|
|
|
|
};
|
2021-03-08 23:32:41 +00: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 03:13:38 +00:00
|
|
|
check(input, *ty)
|
2016-02-23 19:06:32 +00:00
|
|
|
}
|
2020-02-15 03:10:59 +00:00
|
|
|
if let hir::FnRetTy::Return(ref ty) = decl.output {
|
2021-09-30 17:38:50 +00:00
|
|
|
check(ty, fty.output().skip_binder())
|
2016-02-23 19:06:32 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-05-13 14:11:52 +00:00
|
|
|
fty
|
2012-05-16 02:36:04 +00:00
|
|
|
}
|
2017-04-14 14:51:22 +00:00
|
|
|
|
2019-06-21 21:49:03 +00:00
|
|
|
fn is_foreign_item(tcx: TyCtxt<'_>, def_id: DefId) -> bool {
|
2018-12-04 12:45:36 +00:00
|
|
|
match tcx.hir().get_if_local(def_id) {
|
2018-08-25 14:56:16 +00:00
|
|
|
Some(Node::ForeignItem(..)) => true,
|
2017-04-14 14:51:22 +00:00
|
|
|
Some(_) => false,
|
2018-08-19 16:34:21 +00:00
|
|
|
_ => bug!("is_foreign_item applied to non-local def-id {:?}", def_id),
|
2017-04-14 14:51:22 +00:00
|
|
|
}
|
|
|
|
}
|
2018-01-16 01:08:09 +00:00
|
|
|
|
2020-01-26 01:09:23 +00:00
|
|
|
fn generator_kind(tcx: TyCtxt<'_>, def_id: DefId) -> Option<hir::GeneratorKind> {
|
|
|
|
match tcx.hir().get_if_local(def_id) {
|
2020-02-08 22:33:50 +00:00
|
|
|
Some(Node::Expr(&rustc_hir::Expr {
|
2022-07-11 19:39:53 +00:00
|
|
|
kind: rustc_hir::ExprKind::Closure(&rustc_hir::Closure { body, .. }),
|
2020-02-08 22:33:50 +00:00
|
|
|
..
|
2022-06-11 19:25:25 +00:00
|
|
|
})) => tcx.hir().body(body).generator_kind(),
|
2020-01-26 01:09:23 +00:00
|
|
|
Some(_) => None,
|
|
|
|
_ => bug!("generator_kind applied to non-local def-id {:?}", def_id),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-02-28 01:12:32 +00:00
|
|
|
fn from_target_feature(
|
2019-06-13 21:48:52 +00:00
|
|
|
tcx: TyCtxt<'_>,
|
2018-02-28 01:12:32 +00:00
|
|
|
attr: &ast::Attribute,
|
2020-07-07 15:12:44 +00:00
|
|
|
supported_target_features: &FxHashMap<String, Option<Symbol>>,
|
2018-02-28 01:12:32 +00:00
|
|
|
target_features: &mut Vec<Symbol>,
|
|
|
|
) {
|
2022-02-18 23:44:45 +00:00
|
|
|
let Some(list) = attr.meta_item_list() else { return };
|
2019-05-22 00:47:23 +00:00
|
|
|
let bad_item = |span| {
|
|
|
|
let msg = "malformed `target_feature` attribute input";
|
2022-06-13 06:48:40 +00:00
|
|
|
let code = "enable = \"..\"";
|
2019-05-22 00:47:23 +00:00
|
|
|
tcx.sess
|
2021-09-30 17:38:50 +00:00
|
|
|
.struct_span_err(span, msg)
|
2019-05-22 00:47:23 +00:00
|
|
|
.span_suggestion(span, "must be of the form", code, Applicability::HasPlaceholders)
|
|
|
|
.emit();
|
|
|
|
};
|
2018-04-05 15:02:11 +00:00
|
|
|
let rust_features = tcx.features();
|
2018-02-28 01:12:32 +00:00
|
|
|
for item in list {
|
2019-03-16 00:04:02 +00:00
|
|
|
// Only `enable = ...` is accepted in the meta-item list.
|
2020-08-02 10:17:20 +00:00
|
|
|
if !item.has_name(sym::enable) {
|
2019-05-22 00:47:23 +00:00
|
|
|
bad_item(item.span());
|
2018-08-19 16:34:21 +00:00
|
|
|
continue;
|
2018-02-28 01:12:32 +00:00
|
|
|
}
|
2018-04-05 15:02:11 +00:00
|
|
|
|
2019-02-28 22:43:53 +00:00
|
|
|
// Must be of the form `enable = "..."` (a string).
|
2022-02-18 23:44:45 +00:00
|
|
|
let Some(value) = item.value_str() else {
|
|
|
|
bad_item(item.span());
|
|
|
|
continue;
|
2018-02-28 01:12:32 +00:00
|
|
|
};
|
|
|
|
|
2019-03-16 00:04:02 +00:00
|
|
|
// We allow comma separation to enable multiple features.
|
2018-09-26 15:32:23 +00:00
|
|
|
target_features.extend(value.as_str().split(',').filter_map(|feature| {
|
2022-02-18 23:44:45 +00:00
|
|
|
let Some(feature_gate) = supported_target_features.get(feature) else {
|
|
|
|
let msg =
|
|
|
|
format!("the feature named `{}` is not valid for this target", feature);
|
|
|
|
let mut err = tcx.sess.struct_span_err(item.span(), &msg);
|
|
|
|
err.span_label(
|
|
|
|
item.span(),
|
|
|
|
format!("`{}` is not valid for this target", feature),
|
|
|
|
);
|
|
|
|
if let Some(stripped) = feature.strip_prefix('+') {
|
|
|
|
let valid = supported_target_features.contains_key(stripped);
|
|
|
|
if valid {
|
|
|
|
err.help("consider removing the leading `+` in the feature name");
|
2018-04-05 15:02:11 +00:00
|
|
|
}
|
2018-02-28 01:12:32 +00:00
|
|
|
}
|
2022-02-18 23:44:45 +00:00
|
|
|
err.emit();
|
|
|
|
return None;
|
2018-04-05 15:02:11 +00:00
|
|
|
};
|
|
|
|
|
2019-03-16 00:04:02 +00:00
|
|
|
// Only allow features whose feature gates have been enabled.
|
2020-02-29 12:14:52 +00:00
|
|
|
let allowed = match feature_gate.as_ref().copied() {
|
2019-05-08 03:21:18 +00:00
|
|
|
Some(sym::arm_target_feature) => rust_features.arm_target_feature,
|
|
|
|
Some(sym::hexagon_target_feature) => rust_features.hexagon_target_feature,
|
|
|
|
Some(sym::powerpc_target_feature) => rust_features.powerpc_target_feature,
|
|
|
|
Some(sym::mips_target_feature) => rust_features.mips_target_feature,
|
2020-03-01 09:52:04 +00:00
|
|
|
Some(sym::riscv_target_feature) => rust_features.riscv_target_feature,
|
2019-05-08 03:21:18 +00:00
|
|
|
Some(sym::avx512_target_feature) => rust_features.avx512_target_feature,
|
|
|
|
Some(sym::sse4a_target_feature) => rust_features.sse4a_target_feature,
|
|
|
|
Some(sym::tbm_target_feature) => rust_features.tbm_target_feature,
|
|
|
|
Some(sym::wasm_target_feature) => rust_features.wasm_target_feature,
|
|
|
|
Some(sym::cmpxchg16b_target_feature) => rust_features.cmpxchg16b_target_feature,
|
|
|
|
Some(sym::movbe_target_feature) => rust_features.movbe_target_feature,
|
|
|
|
Some(sym::rtm_target_feature) => rust_features.rtm_target_feature,
|
|
|
|
Some(sym::f16c_target_feature) => rust_features.f16c_target_feature,
|
2020-10-26 10:46:54 +00:00
|
|
|
Some(sym::ermsb_target_feature) => rust_features.ermsb_target_feature,
|
2021-05-29 12:17:02 +00:00
|
|
|
Some(sym::bpf_target_feature) => rust_features.bpf_target_feature,
|
2022-02-10 16:43:45 +00:00
|
|
|
Some(sym::aarch64_ver_target_feature) => rust_features.aarch64_ver_target_feature,
|
2018-04-05 15:02:11 +00:00
|
|
|
Some(name) => bug!("unknown target feature gate {}", name),
|
|
|
|
None => true,
|
|
|
|
};
|
2022-04-27 08:22:08 +00:00
|
|
|
if !allowed {
|
2020-01-02 11:42:42 +00:00
|
|
|
feature_err(
|
2018-04-05 15:02:11 +00:00
|
|
|
&tcx.sess.parse_sess,
|
2019-05-08 03:21:18 +00:00
|
|
|
feature_gate.unwrap(),
|
2019-03-03 17:56:24 +00:00
|
|
|
item.span(),
|
2018-08-19 16:34:21 +00:00
|
|
|
&format!("the target feature `{}` is currently unstable", feature),
|
2019-11-30 06:40:28 +00:00
|
|
|
)
|
|
|
|
.emit();
|
2018-02-28 01:12:32 +00:00
|
|
|
}
|
2018-09-26 15:32:23 +00:00
|
|
|
Some(Symbol::intern(feature))
|
|
|
|
}));
|
2018-02-28 01:12:32 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-04-27 08:22:08 +00:00
|
|
|
fn linkage_by_name(tcx: TyCtxt<'_>, def_id: LocalDefId, name: &str) -> Linkage {
|
2020-03-29 14:41:09 +00:00
|
|
|
use rustc_middle::mir::mono::Linkage::*;
|
2018-02-28 03:08:46 +00:00
|
|
|
|
|
|
|
// Use the names from src/llvm/docs/LangRef.rst here. Most types are only
|
|
|
|
// applicable to variable declarations and may not really make sense for
|
2020-07-07 15:12:44 +00:00
|
|
|
// Rust code in the first place but allow them anyway and trust that the
|
2022-04-07 07:51:59 +00:00
|
|
|
// user knows what they're doing. Who knows, unanticipated use cases may pop
|
2020-07-07 15:12:44 +00:00
|
|
|
// up in the future.
|
2018-02-28 03:08:46 +00:00
|
|
|
//
|
|
|
|
// ghost, dllimport, dllexport and linkonce_odr_autohide are not supported
|
|
|
|
// and don't have to be, LLVM treats them as no-ops.
|
|
|
|
match name {
|
|
|
|
"appending" => Appending,
|
|
|
|
"available_externally" => AvailableExternally,
|
|
|
|
"common" => Common,
|
|
|
|
"extern_weak" => ExternalWeak,
|
|
|
|
"external" => External,
|
|
|
|
"internal" => Internal,
|
|
|
|
"linkonce" => LinkOnceAny,
|
|
|
|
"linkonce_odr" => LinkOnceODR,
|
|
|
|
"private" => Private,
|
|
|
|
"weak" => WeakAny,
|
|
|
|
"weak_odr" => WeakODR,
|
2022-04-27 08:22:08 +00:00
|
|
|
_ => tcx.sess.span_fatal(tcx.def_span(def_id), "invalid linkage specified"),
|
2018-02-28 03:08:46 +00:00
|
|
|
}
|
|
|
|
}
|
2022-04-27 12:50:50 +00:00
|
|
|
|
2022-04-27 08:22:08 +00:00
|
|
|
fn codegen_fn_attrs(tcx: TyCtxt<'_>, did: DefId) -> CodegenFnAttrs {
|
2022-05-04 09:18:37 +00:00
|
|
|
if cfg!(debug_assertions) {
|
|
|
|
let def_kind = tcx.def_kind(did);
|
|
|
|
assert!(
|
2022-05-09 15:47:02 +00:00
|
|
|
def_kind.has_codegen_attrs(),
|
2022-05-04 09:18:37 +00:00
|
|
|
"unexpected `def_kind` in `codegen_fn_attrs`: {def_kind:?}",
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
2022-04-27 08:22:08 +00:00
|
|
|
let did = did.expect_local();
|
|
|
|
let attrs = tcx.hir().attrs(tcx.hir().local_def_id_to_hir_id(did));
|
2018-05-08 13:10:16 +00:00
|
|
|
let mut codegen_fn_attrs = CodegenFnAttrs::new();
|
2022-04-27 08:22:08 +00:00
|
|
|
if tcx.should_inherit_track_caller(did) {
|
2020-02-17 23:36:36 +00:00
|
|
|
codegen_fn_attrs.flags |= CodegenFnAttrFlags::TRACK_CALLER;
|
|
|
|
}
|
2018-01-16 01:08:09 +00:00
|
|
|
|
2020-07-07 15:12:44 +00:00
|
|
|
let supported_target_features = tcx.supported_target_features(LOCAL_CRATE);
|
2018-02-28 01:12:32 +00:00
|
|
|
|
2018-03-27 18:42:04 +00:00
|
|
|
let mut inline_span = None;
|
2019-09-19 17:48:30 +00:00
|
|
|
let mut link_ordinal_span = None;
|
2020-01-12 00:00:00 +00:00
|
|
|
let mut no_sanitize_span = None;
|
2018-01-16 01:08:09 +00:00
|
|
|
for attr in attrs.iter() {
|
2021-07-29 17:00:41 +00:00
|
|
|
if attr.has_name(sym::cold) {
|
2018-05-08 13:10:16 +00:00
|
|
|
codegen_fn_attrs.flags |= CodegenFnAttrFlags::COLD;
|
2021-07-29 17:00:41 +00:00
|
|
|
} else if attr.has_name(sym::rustc_allocator) {
|
2018-05-08 13:10:16 +00:00
|
|
|
codegen_fn_attrs.flags |= CodegenFnAttrFlags::ALLOCATOR;
|
2021-07-29 17:00:41 +00:00
|
|
|
} else if attr.has_name(sym::ffi_returns_twice) {
|
2022-04-27 08:22:08 +00:00
|
|
|
if tcx.is_foreign_item(did) {
|
2019-02-09 14:55:30 +00:00
|
|
|
codegen_fn_attrs.flags |= CodegenFnAttrFlags::FFI_RETURNS_TWICE;
|
|
|
|
} else {
|
2019-02-28 22:43:53 +00:00
|
|
|
// `#[ffi_returns_twice]` is only allowed `extern fn`s.
|
2019-02-09 14:55:30 +00:00
|
|
|
struct_span_err!(
|
|
|
|
tcx.sess,
|
|
|
|
attr.span,
|
2019-02-23 15:24:14 +00:00
|
|
|
E0724,
|
2019-02-09 21:09:25 +00:00
|
|
|
"`#[ffi_returns_twice]` may only be used on foreign functions"
|
2019-02-09 14:55:30 +00:00
|
|
|
)
|
|
|
|
.emit();
|
|
|
|
}
|
2021-07-29 17:00:41 +00:00
|
|
|
} else if attr.has_name(sym::ffi_pure) {
|
2022-04-27 08:22:08 +00:00
|
|
|
if tcx.is_foreign_item(did) {
|
2021-07-29 17:00:41 +00:00
|
|
|
if attrs.iter().any(|a| a.has_name(sym::ffi_const)) {
|
2020-04-13 22:19:46 +00:00
|
|
|
// `#[ffi_const]` functions cannot be `#[ffi_pure]`
|
|
|
|
struct_span_err!(
|
|
|
|
tcx.sess,
|
|
|
|
attr.span,
|
|
|
|
E0757,
|
|
|
|
"`#[ffi_const]` function cannot be `#[ffi_pure]`"
|
|
|
|
)
|
|
|
|
.emit();
|
|
|
|
} else {
|
|
|
|
codegen_fn_attrs.flags |= CodegenFnAttrFlags::FFI_PURE;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
// `#[ffi_pure]` is only allowed on foreign functions
|
|
|
|
struct_span_err!(
|
|
|
|
tcx.sess,
|
|
|
|
attr.span,
|
|
|
|
E0755,
|
|
|
|
"`#[ffi_pure]` may only be used on foreign functions"
|
|
|
|
)
|
|
|
|
.emit();
|
|
|
|
}
|
2021-07-29 17:00:41 +00:00
|
|
|
} else if attr.has_name(sym::ffi_const) {
|
2022-04-27 08:22:08 +00:00
|
|
|
if tcx.is_foreign_item(did) {
|
2020-04-13 22:19:46 +00:00
|
|
|
codegen_fn_attrs.flags |= CodegenFnAttrFlags::FFI_CONST;
|
|
|
|
} else {
|
|
|
|
// `#[ffi_const]` is only allowed on foreign functions
|
|
|
|
struct_span_err!(
|
|
|
|
tcx.sess,
|
|
|
|
attr.span,
|
|
|
|
E0756,
|
|
|
|
"`#[ffi_const]` may only be used on foreign functions"
|
|
|
|
)
|
|
|
|
.emit();
|
|
|
|
}
|
2022-10-06 10:33:29 +00:00
|
|
|
} else if attr.has_name(sym::rustc_nounwind) {
|
2021-06-08 18:23:58 +00:00
|
|
|
codegen_fn_attrs.flags |= CodegenFnAttrFlags::NEVER_UNWIND;
|
2022-03-21 19:30:54 +00:00
|
|
|
} else if attr.has_name(sym::rustc_reallocator) {
|
|
|
|
codegen_fn_attrs.flags |= CodegenFnAttrFlags::REALLOCATOR;
|
|
|
|
} else if attr.has_name(sym::rustc_deallocator) {
|
|
|
|
codegen_fn_attrs.flags |= CodegenFnAttrFlags::DEALLOCATOR;
|
|
|
|
} else if attr.has_name(sym::rustc_allocator_zeroed) {
|
|
|
|
codegen_fn_attrs.flags |= CodegenFnAttrFlags::ALLOCATOR_ZEROED;
|
2021-07-29 17:00:41 +00:00
|
|
|
} else if attr.has_name(sym::naked) {
|
2018-05-08 13:10:16 +00:00
|
|
|
codegen_fn_attrs.flags |= CodegenFnAttrFlags::NAKED;
|
2021-07-29 17:00:41 +00:00
|
|
|
} else if attr.has_name(sym::no_mangle) {
|
2018-05-08 13:10:16 +00:00
|
|
|
codegen_fn_attrs.flags |= CodegenFnAttrFlags::NO_MANGLE;
|
2021-07-29 17:00:41 +00:00
|
|
|
} else if attr.has_name(sym::no_coverage) {
|
2021-05-03 15:47:43 +00:00
|
|
|
codegen_fn_attrs.flags |= CodegenFnAttrFlags::NO_COVERAGE;
|
2021-07-29 17:00:41 +00:00
|
|
|
} else if attr.has_name(sym::rustc_std_internal_symbol) {
|
2018-05-08 13:10:16 +00:00
|
|
|
codegen_fn_attrs.flags |= CodegenFnAttrFlags::RUSTC_STD_INTERNAL_SYMBOL;
|
2021-07-29 17:00:41 +00:00
|
|
|
} else if attr.has_name(sym::used) {
|
2021-11-22 12:14:54 +00:00
|
|
|
let inner = attr.meta_item_list();
|
|
|
|
match inner.as_deref() {
|
|
|
|
Some([item]) if item.has_name(sym::linker) => {
|
|
|
|
if !tcx.features().used_with_arg {
|
|
|
|
feature_err(
|
|
|
|
&tcx.sess.parse_sess,
|
|
|
|
sym::used_with_arg,
|
|
|
|
attr.span,
|
|
|
|
"`#[used(linker)]` is currently unstable",
|
|
|
|
)
|
|
|
|
.emit();
|
|
|
|
}
|
|
|
|
codegen_fn_attrs.flags |= CodegenFnAttrFlags::USED_LINKER;
|
|
|
|
}
|
|
|
|
Some([item]) if item.has_name(sym::compiler) => {
|
|
|
|
if !tcx.features().used_with_arg {
|
|
|
|
feature_err(
|
|
|
|
&tcx.sess.parse_sess,
|
|
|
|
sym::used_with_arg,
|
|
|
|
attr.span,
|
|
|
|
"`#[used(compiler)]` is currently unstable",
|
|
|
|
)
|
|
|
|
.emit();
|
|
|
|
}
|
|
|
|
codegen_fn_attrs.flags |= CodegenFnAttrFlags::USED;
|
|
|
|
}
|
|
|
|
Some(_) => {
|
2022-08-18 12:14:21 +00:00
|
|
|
tcx.sess.emit_err(errors::ExpectedUsedSymbol { span: attr.span });
|
2021-11-22 12:14:54 +00:00
|
|
|
}
|
2022-05-11 08:55:00 +00:00
|
|
|
None => {
|
|
|
|
// Unfortunately, unconditionally using `llvm.used` causes
|
|
|
|
// issues in handling `.init_array` with the gold linker,
|
|
|
|
// but using `llvm.compiler.used` caused a nontrival amount
|
|
|
|
// of unintentional ecosystem breakage -- particularly on
|
|
|
|
// Mach-O targets.
|
|
|
|
//
|
|
|
|
// As a result, we emit `llvm.compiler.used` only on ELF
|
|
|
|
// targets. This is somewhat ad-hoc, but actually follows
|
|
|
|
// our pre-LLVM 13 behavior (prior to the ecosystem
|
|
|
|
// breakage), and seems to match `clang`'s behavior as well
|
|
|
|
// (both before and after LLVM 13), possibly because they
|
|
|
|
// have similar compatibility concerns to us. See
|
|
|
|
// https://github.com/rust-lang/rust/issues/47384#issuecomment-1019080146
|
|
|
|
// and following comments for some discussion of this, as
|
|
|
|
// well as the comments in `rustc_codegen_llvm` where these
|
|
|
|
// flags are handled.
|
|
|
|
//
|
|
|
|
// Anyway, to be clear: this is still up in the air
|
|
|
|
// somewhat, and is subject to change in the future (which
|
|
|
|
// is a good thing, because this would ideally be a bit
|
|
|
|
// more firmed up).
|
|
|
|
let is_like_elf = !(tcx.sess.target.is_like_osx
|
|
|
|
|| tcx.sess.target.is_like_windows
|
|
|
|
|| tcx.sess.target.is_like_wasm);
|
2022-07-24 13:18:34 +00:00
|
|
|
codegen_fn_attrs.flags |= if is_like_elf {
|
2022-05-11 08:55:00 +00:00
|
|
|
CodegenFnAttrFlags::USED
|
|
|
|
} else {
|
|
|
|
CodegenFnAttrFlags::USED_LINKER
|
|
|
|
};
|
|
|
|
}
|
2021-11-22 12:14:54 +00:00
|
|
|
}
|
2021-07-29 17:00:41 +00:00
|
|
|
} else if attr.has_name(sym::cmse_nonsecure_entry) {
|
2022-04-27 08:22:08 +00:00
|
|
|
if !matches!(tcx.fn_sig(did).abi(), abi::Abi::C { .. }) {
|
2020-09-30 17:10:17 +00:00
|
|
|
struct_span_err!(
|
|
|
|
tcx.sess,
|
|
|
|
attr.span,
|
|
|
|
E0776,
|
|
|
|
"`#[cmse_nonsecure_entry]` requires C ABI"
|
|
|
|
)
|
|
|
|
.emit();
|
|
|
|
}
|
2020-10-15 09:44:00 +00:00
|
|
|
if !tcx.sess.target.llvm_target.contains("thumbv8m") {
|
2020-09-28 20:10:38 +00:00
|
|
|
struct_span_err!(tcx.sess, attr.span, E0775, "`#[cmse_nonsecure_entry]` is only valid for targets with the TrustZone-M extension")
|
|
|
|
.emit();
|
|
|
|
}
|
|
|
|
codegen_fn_attrs.flags |= CodegenFnAttrFlags::CMSE_NONSECURE_ENTRY;
|
2021-07-29 17:00:41 +00:00
|
|
|
} else if attr.has_name(sym::thread_local) {
|
2018-07-13 18:30:47 +00:00
|
|
|
codegen_fn_attrs.flags |= CodegenFnAttrFlags::THREAD_LOCAL;
|
2021-07-29 17:00:41 +00:00
|
|
|
} else if attr.has_name(sym::track_caller) {
|
2022-04-27 08:22:08 +00:00
|
|
|
if !tcx.is_closure(did.to_def_id()) && tcx.fn_sig(did).abi() != abi::Abi::Rust {
|
2019-10-27 20:32:18 +00:00
|
|
|
struct_span_err!(tcx.sess, attr.span, E0737, "`#[track_caller]` requires Rust ABI")
|
2019-07-20 00:55:58 +00:00
|
|
|
.emit();
|
|
|
|
}
|
2022-04-27 08:22:08 +00:00
|
|
|
if tcx.is_closure(did.to_def_id()) && !tcx.features().closure_track_caller {
|
Support `#[track_caller]` on closures and generators
This PR allows applying a `#[track_caller]` attribute to a
closure/generator expression. The attribute as interpreted as applying
to the compiler-generated implementation of the corresponding trait
method (`FnOnce::call_once`, `FnMut::call_mut`, `Fn::call`, or
`Generator::resume`).
This feature does not have its own feature gate - however, it requires
`#![feature(stmt_expr_attributes)]` in order to actually apply
an attribute to a closure or generator.
This is implemented in the same way as for functions - an extra
location argument is appended to the end of the ABI. For closures,
this argument is *not* part of the 'tupled' argument storing the
parameters - the final closure argument for `#[track_caller]` closures
is no longer a tuple.
For direct (monomorphized) calls, the necessary support was already
implemented - we just needeed to adjust some assertions around checking
the ABI and argument count to take closures into account.
For calls through a trait object, more work was needed.
When creating a `ReifyShim`, we need to create a shim
for the trait method (e.g. `FnOnce::call_mut`) - unlike normal
functions, closures are never invoked directly, and always go through a
trait method.
Additional handling was needed for `InstanceDef::ClosureOnceShim`. In
order to pass location information throgh a direct (monomorphized) call
to `FnOnce::call_once` on an `FnMut` closure, we need to make
`ClosureOnceShim` aware of `#[tracked_caller]`. A new field
`track_caller` is added to `ClosureOnceShim` - this is used by
`InstanceDef::requires_caller` location, allowing codegen to
pass through the extra location argument.
Since `ClosureOnceShim.track_caller` is only used by codegen,
we end up generating two identical MIR shims - one for
`track_caller == true`, and one for `track_caller == false`. However,
these two shims are used by the entire crate (i.e. it's two shims total,
not two shims per unique closure), so this shouldn't a big deal.
2021-06-27 19:01:11 +00:00
|
|
|
feature_err(
|
|
|
|
&tcx.sess.parse_sess,
|
|
|
|
sym::closure_track_caller,
|
|
|
|
attr.span,
|
|
|
|
"`#[track_caller]` on closures is currently unstable",
|
|
|
|
)
|
|
|
|
.emit();
|
|
|
|
}
|
2019-07-20 00:55:58 +00:00
|
|
|
codegen_fn_attrs.flags |= CodegenFnAttrFlags::TRACK_CALLER;
|
2021-07-29 17:00:41 +00:00
|
|
|
} else if attr.has_name(sym::export_name) {
|
2018-06-23 21:31:31 +00:00
|
|
|
if let Some(s) = attr.value_str() {
|
2020-02-26 12:03:46 +00:00
|
|
|
if s.as_str().contains('\0') {
|
2018-06-23 21:31:31 +00:00
|
|
|
// `#[export_name = ...]` will be converted to a null-terminated string,
|
|
|
|
// so it may not contain any null characters.
|
2018-08-19 16:34:21 +00:00
|
|
|
struct_span_err!(
|
|
|
|
tcx.sess,
|
|
|
|
attr.span,
|
|
|
|
E0648,
|
|
|
|
"`export_name` may not contain null characters"
|
|
|
|
)
|
|
|
|
.emit();
|
2018-06-23 21:31:31 +00:00
|
|
|
}
|
|
|
|
codegen_fn_attrs.export_name = Some(s);
|
2018-02-07 03:13:14 +00:00
|
|
|
}
|
2021-07-29 17:00:41 +00:00
|
|
|
} else if attr.has_name(sym::target_feature) {
|
2022-04-27 08:22:08 +00:00
|
|
|
if !tcx.is_closure(did.to_def_id())
|
|
|
|
&& tcx.fn_sig(did).unsafety() == hir::Unsafety::Normal
|
|
|
|
{
|
2021-06-04 01:56:31 +00:00
|
|
|
if tcx.sess.target.is_like_wasm || tcx.sess.opts.actually_rustdoc {
|
2021-05-06 14:50:40 +00:00
|
|
|
// The `#[target_feature]` attribute is allowed on
|
|
|
|
// WebAssembly targets on all functions, including safe
|
|
|
|
// ones. Other targets require that `#[target_feature]` is
|
2022-03-30 19:14:15 +00:00
|
|
|
// only applied to unsafe functions (pending the
|
2021-05-06 14:50:40 +00:00
|
|
|
// `target_feature_11` feature) because on most targets
|
|
|
|
// execution of instructions that are not supported is
|
|
|
|
// considered undefined behavior. For WebAssembly which is a
|
|
|
|
// 100% safe target at execution time it's not possible to
|
|
|
|
// execute undefined instructions, and even if a future
|
|
|
|
// feature was added in some form for this it would be a
|
|
|
|
// deterministic trap. There is no undefined behavior when
|
|
|
|
// executing WebAssembly so `#[target_feature]` is allowed
|
|
|
|
// on safe functions (but again, only for WebAssembly)
|
2021-06-04 01:56:31 +00:00
|
|
|
//
|
|
|
|
// Note that this is also allowed if `actually_rustdoc` so
|
|
|
|
// if a target is documenting some wasm-specific code then
|
|
|
|
// it's not spuriously denied.
|
2021-05-06 14:50:40 +00:00
|
|
|
} else if !tcx.features().target_feature_11 {
|
2020-06-14 04:47:42 +00:00
|
|
|
let mut err = feature_err(
|
|
|
|
&tcx.sess.parse_sess,
|
|
|
|
sym::target_feature_11,
|
|
|
|
attr.span,
|
|
|
|
"`#[target_feature(..)]` can only be applied to `unsafe` functions",
|
|
|
|
);
|
2022-04-27 08:22:08 +00:00
|
|
|
err.span_label(tcx.def_span(did), "not an `unsafe` function");
|
2020-06-14 04:47:42 +00:00
|
|
|
err.emit();
|
2022-04-27 08:22:08 +00:00
|
|
|
} else {
|
|
|
|
check_target_feature_trait_unsafe(tcx, did, attr.span);
|
2020-05-01 12:17:02 +00:00
|
|
|
}
|
2018-02-28 01:12:32 +00:00
|
|
|
}
|
2020-07-07 15:12:44 +00:00
|
|
|
from_target_feature(
|
|
|
|
tcx,
|
|
|
|
attr,
|
2021-09-30 17:38:50 +00:00
|
|
|
supported_target_features,
|
2020-07-07 15:12:44 +00:00
|
|
|
&mut codegen_fn_attrs.target_features,
|
|
|
|
);
|
2021-07-29 17:00:41 +00:00
|
|
|
} else if attr.has_name(sym::linkage) {
|
2018-02-28 03:08:46 +00:00
|
|
|
if let Some(val) = attr.value_str() {
|
Move linkage type check to HIR analysis and fix semantics issues.
This ensures that the error is printed even for unused variables,
as well as unifying the handling between the LLVM and GCC backends.
This also fixes unusual behavior around exported Rust-defined variables
with linkage attributes. With the previous behavior, it appears to be
impossible to define such a variable such that it can actually be imported
and used by another crate. This is because on the importing side, the
variable is required to be a pointer, but on the exporting side, the
type checker rejects static variables of pointer type because they do
not implement `Sync`. Even if it were possible to import such a type, it
appears that code generation on the importing side would add an unexpected
additional level of pointer indirection, which would break type safety.
This highlighted that the semantics of linkage on Rust-defined variables
is different to linkage on foreign items. As such, we now model the
difference with two different codegen attributes: linkage for Rust-defined
variables, and import_linkage for foreign items.
This change gives semantics to the test
src/test/ui/linkage-attr/auxiliary/def_illtyped_external.rs which was
previously expected to fail to compile. Therefore, convert it into a
test that is expected to successfully compile.
The update to the GCC backend is speculative and untested.
2022-11-24 02:13:30 +00:00
|
|
|
let linkage = Some(linkage_by_name(tcx, did, val.as_str()));
|
|
|
|
if tcx.is_foreign_item(did) {
|
|
|
|
codegen_fn_attrs.import_linkage = linkage;
|
|
|
|
} else {
|
|
|
|
codegen_fn_attrs.linkage = linkage;
|
|
|
|
}
|
2018-02-28 03:08:46 +00:00
|
|
|
}
|
2021-07-29 17:00:41 +00:00
|
|
|
} else if attr.has_name(sym::link_section) {
|
2018-07-13 18:30:47 +00:00
|
|
|
if let Some(val) = attr.value_str() {
|
|
|
|
if val.as_str().bytes().any(|b| b == 0) {
|
2018-08-19 16:34:21 +00:00
|
|
|
let msg = format!(
|
|
|
|
"illegal null byte in link_section \
|
|
|
|
value: `{}`",
|
|
|
|
&val
|
|
|
|
);
|
2018-07-13 18:30:47 +00:00
|
|
|
tcx.sess.span_err(attr.span, &msg);
|
|
|
|
} else {
|
|
|
|
codegen_fn_attrs.link_section = Some(val);
|
2018-06-01 17:20:00 +00:00
|
|
|
}
|
|
|
|
}
|
2021-07-29 17:00:41 +00:00
|
|
|
} else if attr.has_name(sym::link_name) {
|
2018-08-23 07:33:32 +00:00
|
|
|
codegen_fn_attrs.link_name = attr.value_str();
|
2021-07-29 17:00:41 +00:00
|
|
|
} else if attr.has_name(sym::link_ordinal) {
|
2019-09-19 17:48:30 +00:00
|
|
|
link_ordinal_span = Some(attr.span);
|
2019-09-18 14:40:08 +00:00
|
|
|
if let ordinal @ Some(_) = check_link_ordinal(tcx, attr) {
|
|
|
|
codegen_fn_attrs.link_ordinal = ordinal;
|
2019-08-28 17:54:25 +00:00
|
|
|
}
|
2021-07-29 17:00:41 +00:00
|
|
|
} else if attr.has_name(sym::no_sanitize) {
|
2020-01-12 00:00:00 +00:00
|
|
|
no_sanitize_span = Some(attr.span);
|
|
|
|
if let Some(list) = attr.meta_item_list() {
|
|
|
|
for item in list.iter() {
|
2020-08-02 10:17:20 +00:00
|
|
|
if item.has_name(sym::address) {
|
2020-06-14 00:00:00 +00:00
|
|
|
codegen_fn_attrs.no_sanitize |= SanitizerSet::ADDRESS;
|
2021-10-07 22:33:13 +00:00
|
|
|
} else if item.has_name(sym::cfi) {
|
|
|
|
codegen_fn_attrs.no_sanitize |= SanitizerSet::CFI;
|
2022-11-22 05:29:00 +00:00
|
|
|
} else if item.has_name(sym::kcfi) {
|
|
|
|
codegen_fn_attrs.no_sanitize |= SanitizerSet::KCFI;
|
2020-08-02 10:17:20 +00:00
|
|
|
} else if item.has_name(sym::memory) {
|
2020-06-14 00:00:00 +00:00
|
|
|
codegen_fn_attrs.no_sanitize |= SanitizerSet::MEMORY;
|
2021-12-03 21:11:13 +00:00
|
|
|
} else if item.has_name(sym::memtag) {
|
|
|
|
codegen_fn_attrs.no_sanitize |= SanitizerSet::MEMTAG;
|
2022-06-17 18:14:58 +00:00
|
|
|
} else if item.has_name(sym::shadow_call_stack) {
|
|
|
|
codegen_fn_attrs.no_sanitize |= SanitizerSet::SHADOWCALLSTACK;
|
2020-08-02 10:17:20 +00:00
|
|
|
} else if item.has_name(sym::thread) {
|
2020-06-14 00:00:00 +00:00
|
|
|
codegen_fn_attrs.no_sanitize |= SanitizerSet::THREAD;
|
2021-01-23 02:32:38 +00:00
|
|
|
} else if item.has_name(sym::hwaddress) {
|
|
|
|
codegen_fn_attrs.no_sanitize |= SanitizerSet::HWADDRESS;
|
2020-01-12 00:00:00 +00:00
|
|
|
} else {
|
|
|
|
tcx.sess
|
|
|
|
.struct_span_err(item.span(), "invalid argument for `no_sanitize`")
|
2022-11-22 05:29:00 +00:00
|
|
|
.note("expected one of: `address`, `cfi`, `hwaddress`, `kcfi`, `memory`, `memtag`, `shadow-call-stack`, or `thread`")
|
2020-01-12 00:00:00 +00:00
|
|
|
.emit();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2021-07-29 17:00:41 +00:00
|
|
|
} else if attr.has_name(sym::instruction_set) {
|
2021-12-26 15:47:08 +00:00
|
|
|
codegen_fn_attrs.instruction_set = match attr.meta_kind() {
|
2020-10-08 22:23:27 +00:00
|
|
|
Some(MetaItemKind::List(ref items)) => match items.as_slice() {
|
|
|
|
[NestedMetaItem::MetaItem(set)] => {
|
|
|
|
let segments =
|
|
|
|
set.path.segments.iter().map(|x| x.ident.name).collect::<Vec<_>>();
|
|
|
|
match segments.as_slice() {
|
|
|
|
[sym::arm, sym::a32] | [sym::arm, sym::t32] => {
|
2020-11-08 11:27:51 +00:00
|
|
|
if !tcx.sess.target.has_thumb_interworking {
|
2020-10-08 22:23:27 +00:00
|
|
|
struct_span_err!(
|
|
|
|
tcx.sess.diagnostic(),
|
|
|
|
attr.span,
|
|
|
|
E0779,
|
|
|
|
"target does not support `#[instruction_set]`"
|
|
|
|
)
|
|
|
|
.emit();
|
|
|
|
None
|
|
|
|
} else if segments[1] == sym::a32 {
|
|
|
|
Some(InstructionSetAttr::ArmA32)
|
|
|
|
} else if segments[1] == sym::t32 {
|
|
|
|
Some(InstructionSetAttr::ArmT32)
|
|
|
|
} else {
|
|
|
|
unreachable!()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
_ => {
|
|
|
|
struct_span_err!(
|
|
|
|
tcx.sess.diagnostic(),
|
|
|
|
attr.span,
|
|
|
|
E0779,
|
|
|
|
"invalid instruction set specified",
|
|
|
|
)
|
|
|
|
.emit();
|
|
|
|
None
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
[] => {
|
|
|
|
struct_span_err!(
|
|
|
|
tcx.sess.diagnostic(),
|
|
|
|
attr.span,
|
|
|
|
E0778,
|
|
|
|
"`#[instruction_set]` requires an argument"
|
|
|
|
)
|
|
|
|
.emit();
|
|
|
|
None
|
|
|
|
}
|
|
|
|
_ => {
|
|
|
|
struct_span_err!(
|
|
|
|
tcx.sess.diagnostic(),
|
|
|
|
attr.span,
|
|
|
|
E0779,
|
|
|
|
"cannot specify more than one instruction set"
|
|
|
|
)
|
|
|
|
.emit();
|
|
|
|
None
|
|
|
|
}
|
|
|
|
},
|
|
|
|
_ => {
|
|
|
|
struct_span_err!(
|
|
|
|
tcx.sess.diagnostic(),
|
|
|
|
attr.span,
|
|
|
|
E0778,
|
|
|
|
"must specify an instruction set"
|
|
|
|
)
|
|
|
|
.emit();
|
|
|
|
None
|
|
|
|
}
|
|
|
|
};
|
2021-07-29 17:00:41 +00:00
|
|
|
} else if attr.has_name(sym::repr) {
|
2021-01-21 02:49:04 +00:00
|
|
|
codegen_fn_attrs.alignment = match attr.meta_item_list() {
|
|
|
|
Some(items) => match items.as_slice() {
|
|
|
|
[item] => match item.name_value_literal() {
|
|
|
|
Some((sym::align, literal)) => {
|
|
|
|
let alignment = rustc_attr::parse_alignment(&literal.kind);
|
|
|
|
|
|
|
|
match alignment {
|
|
|
|
Ok(align) => Some(align),
|
|
|
|
Err(msg) => {
|
|
|
|
struct_span_err!(
|
|
|
|
tcx.sess.diagnostic(),
|
|
|
|
attr.span,
|
|
|
|
E0589,
|
|
|
|
"invalid `repr(align)` attribute: {}",
|
|
|
|
msg
|
|
|
|
)
|
|
|
|
.emit();
|
|
|
|
|
|
|
|
None
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
_ => None,
|
|
|
|
},
|
|
|
|
[] => None,
|
|
|
|
_ => None,
|
|
|
|
},
|
|
|
|
None => None,
|
|
|
|
};
|
2018-01-16 01:08:09 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-10-27 12:29:06 +00:00
|
|
|
codegen_fn_attrs.inline = attrs.iter().fold(InlineAttr::None, |ia, attr| {
|
2019-10-23 19:33:12 +00:00
|
|
|
if !attr.has_name(sym::inline) {
|
2018-10-27 12:29:06 +00:00
|
|
|
return ia;
|
|
|
|
}
|
2021-12-26 15:47:08 +00:00
|
|
|
match attr.meta_kind() {
|
2021-07-29 17:00:41 +00:00
|
|
|
Some(MetaItemKind::Word) => InlineAttr::Hint,
|
2018-10-27 12:29:06 +00:00
|
|
|
Some(MetaItemKind::List(ref items)) => {
|
|
|
|
inline_span = Some(attr.span);
|
|
|
|
if items.len() != 1 {
|
2019-12-31 20:25:16 +00:00
|
|
|
struct_span_err!(
|
|
|
|
tcx.sess.diagnostic(),
|
|
|
|
attr.span,
|
|
|
|
E0534,
|
|
|
|
"expected one argument"
|
|
|
|
)
|
|
|
|
.emit();
|
2018-10-27 12:29:06 +00:00
|
|
|
InlineAttr::None
|
2021-12-03 02:06:36 +00:00
|
|
|
} else if list_contains_name(&items, sym::always) {
|
2021-03-27 05:04:32 +00:00
|
|
|
InlineAttr::Always
|
2021-12-03 02:06:36 +00:00
|
|
|
} else if list_contains_name(&items, sym::never) {
|
2018-10-27 12:29:06 +00:00
|
|
|
InlineAttr::Never
|
|
|
|
} else {
|
2019-12-31 20:25:16 +00:00
|
|
|
struct_span_err!(
|
|
|
|
tcx.sess.diagnostic(),
|
|
|
|
items[0].span(),
|
|
|
|
E0535,
|
|
|
|
"invalid argument"
|
|
|
|
)
|
2022-09-16 14:49:43 +00:00
|
|
|
.help("valid inline arguments are `always` and `never`")
|
2019-12-31 20:25:16 +00:00
|
|
|
.emit();
|
2018-10-27 12:29:06 +00:00
|
|
|
|
|
|
|
InlineAttr::None
|
|
|
|
}
|
|
|
|
}
|
|
|
|
Some(MetaItemKind::NameValue(_)) => ia,
|
|
|
|
None => ia,
|
|
|
|
}
|
|
|
|
});
|
|
|
|
|
|
|
|
codegen_fn_attrs.optimize = attrs.iter().fold(OptimizeAttr::None, |ia, attr| {
|
2019-10-23 19:33:12 +00:00
|
|
|
if !attr.has_name(sym::optimize) {
|
2018-10-27 12:29:06 +00:00
|
|
|
return ia;
|
|
|
|
}
|
2019-12-31 20:25:16 +00:00
|
|
|
let err = |sp, s| struct_span_err!(tcx.sess.diagnostic(), sp, E0722, "{}", s).emit();
|
2021-12-26 15:47:08 +00:00
|
|
|
match attr.meta_kind() {
|
2018-10-27 12:29:06 +00:00
|
|
|
Some(MetaItemKind::Word) => {
|
|
|
|
err(attr.span, "expected one argument");
|
|
|
|
ia
|
|
|
|
}
|
|
|
|
Some(MetaItemKind::List(ref items)) => {
|
|
|
|
inline_span = Some(attr.span);
|
|
|
|
if items.len() != 1 {
|
|
|
|
err(attr.span, "expected one argument");
|
|
|
|
OptimizeAttr::None
|
2021-12-03 02:06:36 +00:00
|
|
|
} else if list_contains_name(&items, sym::size) {
|
2018-10-27 12:29:06 +00:00
|
|
|
OptimizeAttr::Size
|
2021-12-03 02:06:36 +00:00
|
|
|
} else if list_contains_name(&items, sym::speed) {
|
2018-10-27 12:29:06 +00:00
|
|
|
OptimizeAttr::Speed
|
|
|
|
} else {
|
2019-03-03 17:56:24 +00:00
|
|
|
err(items[0].span(), "invalid argument");
|
2018-10-27 12:29:06 +00:00
|
|
|
OptimizeAttr::None
|
|
|
|
}
|
|
|
|
}
|
|
|
|
Some(MetaItemKind::NameValue(_)) => ia,
|
|
|
|
None => ia,
|
|
|
|
}
|
|
|
|
});
|
|
|
|
|
2020-10-22 11:55:19 +00:00
|
|
|
// #73631: closures inherit `#[target_feature]` annotations
|
2022-04-27 08:22:08 +00:00
|
|
|
if tcx.features().target_feature_11 && tcx.is_closure(did.to_def_id()) {
|
|
|
|
let owner_id = tcx.parent(did.to_def_id());
|
2022-07-29 00:40:07 +00:00
|
|
|
if tcx.def_kind(owner_id).has_codegen_attrs() {
|
|
|
|
codegen_fn_attrs
|
|
|
|
.target_features
|
|
|
|
.extend(tcx.codegen_fn_attrs(owner_id).target_features.iter().copied());
|
|
|
|
}
|
2020-10-22 11:55:19 +00:00
|
|
|
}
|
|
|
|
|
2018-03-27 18:42:04 +00:00
|
|
|
// If a function uses #[target_feature] it can't be inlined into general
|
|
|
|
// purpose functions as they wouldn't have the right target features
|
|
|
|
// enabled. For that reason we also forbid #[inline(always)] as it can't be
|
|
|
|
// respected.
|
2020-02-28 13:20:33 +00:00
|
|
|
if !codegen_fn_attrs.target_features.is_empty() {
|
2018-05-08 13:10:16 +00:00
|
|
|
if codegen_fn_attrs.inline == InlineAttr::Always {
|
2018-03-27 18:42:04 +00:00
|
|
|
if let Some(span) = inline_span {
|
2018-08-19 16:34:21 +00:00
|
|
|
tcx.sess.span_err(
|
|
|
|
span,
|
2019-07-07 09:37:34 +00:00
|
|
|
"cannot use `#[inline(always)]` with \
|
|
|
|
`#[target_feature]`",
|
2018-08-19 16:34:21 +00:00
|
|
|
);
|
2018-03-27 18:42:04 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-06-14 00:00:00 +00:00
|
|
|
if !codegen_fn_attrs.no_sanitize.is_empty() {
|
2020-01-12 00:00:00 +00:00
|
|
|
if codegen_fn_attrs.inline == InlineAttr::Always {
|
|
|
|
if let (Some(no_sanitize_span), Some(inline_span)) = (no_sanitize_span, inline_span) {
|
2022-04-27 08:22:08 +00:00
|
|
|
let hir_id = tcx.hir().local_def_id_to_hir_id(did);
|
2020-01-12 00:00:00 +00:00
|
|
|
tcx.struct_span_lint_hir(
|
|
|
|
lint::builtin::INLINE_NO_SANITIZE,
|
|
|
|
hir_id,
|
|
|
|
no_sanitize_span,
|
2022-09-16 07:01:02 +00:00
|
|
|
"`no_sanitize` will have no effect after inlining",
|
|
|
|
|lint| lint.span_note(inline_span, "inlining requested here"),
|
2020-01-12 00:00:00 +00:00
|
|
|
)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-12-02 00:00:00 +00:00
|
|
|
if codegen_fn_attrs.flags.contains(CodegenFnAttrFlags::NAKED) {
|
|
|
|
codegen_fn_attrs.flags |= CodegenFnAttrFlags::NO_COVERAGE;
|
2022-12-02 00:00:00 +00:00
|
|
|
codegen_fn_attrs.inline = InlineAttr::Never;
|
2022-12-02 00:00:00 +00:00
|
|
|
}
|
|
|
|
|
2018-08-23 07:33:32 +00:00
|
|
|
// Weak lang items have the same semantics as "std internal" symbols in the
|
|
|
|
// sense that they're preserved through all our LTO passes and only
|
|
|
|
// strippable by the linker.
|
|
|
|
//
|
|
|
|
// Additionally weak lang items have predetermined symbol names.
|
2022-10-26 21:18:59 +00:00
|
|
|
if WEAK_LANG_ITEMS.iter().any(|&l| tcx.lang_items().get(l) == Some(did.to_def_id())) {
|
2018-08-23 07:33:32 +00:00
|
|
|
codegen_fn_attrs.flags |= CodegenFnAttrFlags::RUSTC_STD_INTERNAL_SYMBOL;
|
|
|
|
}
|
2022-10-26 21:18:59 +00:00
|
|
|
if let Some((name, _)) = lang_items::extract(attrs)
|
|
|
|
&& let Some(lang_item) = LangItem::from_name(name)
|
|
|
|
&& let Some(link_name) = lang_item.link_name()
|
|
|
|
{
|
|
|
|
codegen_fn_attrs.export_name = Some(link_name);
|
|
|
|
codegen_fn_attrs.link_name = Some(link_name);
|
2018-08-23 07:33:32 +00:00
|
|
|
}
|
2019-09-19 17:48:30 +00:00
|
|
|
check_link_name_xor_ordinal(tcx, &codegen_fn_attrs, link_ordinal_span);
|
2018-08-23 07:33:32 +00:00
|
|
|
|
|
|
|
// Internal symbols to the standard library all have no_mangle semantics in
|
|
|
|
// that they have defined symbol names present in the function name. This
|
|
|
|
// also applies to weak symbols where they all have known symbol names.
|
|
|
|
if codegen_fn_attrs.flags.contains(CodegenFnAttrFlags::RUSTC_STD_INTERNAL_SYMBOL) {
|
|
|
|
codegen_fn_attrs.flags |= CodegenFnAttrFlags::NO_MANGLE;
|
|
|
|
}
|
|
|
|
|
2021-06-08 18:23:58 +00:00
|
|
|
// Any linkage to LLVM intrinsics for now forcibly marks them all as never
|
|
|
|
// unwinds since LLVM sometimes can't handle codegen which `invoke`s
|
|
|
|
// intrinsic functions.
|
|
|
|
if let Some(name) = &codegen_fn_attrs.link_name {
|
|
|
|
if name.as_str().starts_with("llvm.") {
|
|
|
|
codegen_fn_attrs.flags |= CodegenFnAttrFlags::NEVER_UNWIND;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-05-08 13:10:16 +00:00
|
|
|
codegen_fn_attrs
|
2018-01-16 01:08:09 +00:00
|
|
|
}
|
2019-09-18 14:40:08 +00:00
|
|
|
|
2022-02-17 18:16:04 +00:00
|
|
|
/// Computes the set of target features used in a function for the purposes of
|
|
|
|
/// inline assembly.
|
2022-05-04 09:18:37 +00:00
|
|
|
fn asm_target_features<'tcx>(tcx: TyCtxt<'tcx>, did: DefId) -> &'tcx FxHashSet<Symbol> {
|
2022-07-11 13:26:58 +00:00
|
|
|
let mut target_features = tcx.sess.unstable_target_features.clone();
|
2022-05-09 15:47:02 +00:00
|
|
|
if tcx.def_kind(did).has_codegen_attrs() {
|
2022-05-04 09:18:37 +00:00
|
|
|
let attrs = tcx.codegen_fn_attrs(did);
|
|
|
|
target_features.extend(&attrs.target_features);
|
|
|
|
match attrs.instruction_set {
|
|
|
|
None => {}
|
|
|
|
Some(InstructionSetAttr::ArmA32) => {
|
|
|
|
target_features.remove(&sym::thumb_mode);
|
|
|
|
}
|
|
|
|
Some(InstructionSetAttr::ArmT32) => {
|
|
|
|
target_features.insert(sym::thumb_mode);
|
|
|
|
}
|
2022-02-17 18:16:04 +00:00
|
|
|
}
|
|
|
|
}
|
2022-05-04 09:18:37 +00:00
|
|
|
|
2022-02-17 18:16:04 +00:00
|
|
|
tcx.arena.alloc(target_features)
|
|
|
|
}
|
|
|
|
|
2020-02-17 23:36:36 +00:00
|
|
|
/// Checks if the provided DefId is a method in a trait impl for a trait which has track_caller
|
|
|
|
/// applied to the method prototype.
|
|
|
|
fn should_inherit_track_caller(tcx: TyCtxt<'_>, def_id: DefId) -> bool {
|
2022-02-26 10:43:47 +00:00
|
|
|
if let Some(impl_item) = tcx.opt_associated_item(def_id)
|
2022-03-12 23:52:25 +00:00
|
|
|
&& let ty::AssocItemContainer::ImplContainer = impl_item.container
|
2022-02-26 10:43:47 +00:00
|
|
|
&& let Some(trait_item) = impl_item.trait_item_def_id
|
|
|
|
{
|
|
|
|
return tcx
|
|
|
|
.codegen_fn_attrs(trait_item)
|
|
|
|
.flags
|
|
|
|
.intersects(CodegenFnAttrFlags::TRACK_CALLER);
|
2020-02-17 23:36:36 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
false
|
|
|
|
}
|
|
|
|
|
2021-09-11 00:34:09 +00:00
|
|
|
fn check_link_ordinal(tcx: TyCtxt<'_>, attr: &ast::Attribute) -> Option<u16> {
|
2022-11-23 04:39:42 +00:00
|
|
|
use rustc_ast::{LitIntType, LitKind, MetaItemLit};
|
2022-07-29 18:18:07 +00:00
|
|
|
if !tcx.features().raw_dylib && tcx.sess.target.arch == "x86" {
|
|
|
|
feature_err(
|
|
|
|
&tcx.sess.parse_sess,
|
|
|
|
sym::raw_dylib,
|
|
|
|
attr.span,
|
|
|
|
"`#[link_ordinal]` is unstable on x86",
|
|
|
|
)
|
|
|
|
.emit();
|
|
|
|
}
|
2019-09-18 14:40:08 +00:00
|
|
|
let meta_item_list = attr.meta_item_list();
|
2022-11-16 21:58:58 +00:00
|
|
|
let meta_item_list = meta_item_list.as_deref();
|
2019-09-18 14:40:08 +00:00
|
|
|
let sole_meta_list = match meta_item_list {
|
2022-11-24 04:00:09 +00:00
|
|
|
Some([item]) => item.lit(),
|
2021-09-11 00:34:09 +00:00
|
|
|
Some(_) => {
|
|
|
|
tcx.sess
|
|
|
|
.struct_span_err(attr.span, "incorrect number of arguments to `#[link_ordinal]`")
|
|
|
|
.note("the attribute requires exactly one argument")
|
|
|
|
.emit();
|
|
|
|
return None;
|
|
|
|
}
|
2019-09-18 14:40:08 +00:00
|
|
|
_ => None,
|
|
|
|
};
|
2022-11-23 04:39:42 +00:00
|
|
|
if let Some(MetaItemLit { kind: LitKind::Int(ordinal, LitIntType::Unsuffixed), .. }) =
|
|
|
|
sole_meta_list
|
|
|
|
{
|
2021-09-11 00:34:09 +00:00
|
|
|
// According to the table at https://docs.microsoft.com/en-us/windows/win32/debug/pe-format#import-header,
|
|
|
|
// the ordinal must fit into 16 bits. Similarly, the Ordinal field in COFFShortExport (defined
|
|
|
|
// in llvm/include/llvm/Object/COFFImportFile.h), which we use to communicate import information
|
|
|
|
// to LLVM for `#[link(kind = "raw-dylib"_])`, is also defined to be uint16_t.
|
|
|
|
//
|
|
|
|
// FIXME: should we allow an ordinal of 0? The MSVC toolchain has inconsistent support for this:
|
|
|
|
// both LINK.EXE and LIB.EXE signal errors and abort when given a .DEF file that specifies
|
|
|
|
// a zero ordinal. However, llvm-dlltool is perfectly happy to generate an import library
|
|
|
|
// for such a .DEF file, and MSVC's LINK.EXE is also perfectly happy to consume an import
|
|
|
|
// library produced by LLVM with an ordinal of 0, and it generates an .EXE. (I don't know yet
|
|
|
|
// if the resulting EXE runs, as I haven't yet built the necessary DLL -- see earlier comment
|
|
|
|
// about LINK.EXE failing.)
|
|
|
|
if *ordinal <= u16::MAX as u128 {
|
|
|
|
Some(*ordinal as u16)
|
2019-09-18 14:40:08 +00:00
|
|
|
} else {
|
2019-09-19 17:48:30 +00:00
|
|
|
let msg = format!("ordinal value in `link_ordinal` is too large: `{}`", &ordinal);
|
|
|
|
tcx.sess
|
|
|
|
.struct_span_err(attr.span, &msg)
|
2021-09-11 00:34:09 +00:00
|
|
|
.note("the value may not exceed `u16::MAX`")
|
2019-09-19 17:48:30 +00:00
|
|
|
.emit();
|
2019-09-18 14:40:08 +00:00
|
|
|
None
|
|
|
|
}
|
|
|
|
} else {
|
2019-09-19 17:48:30 +00:00
|
|
|
tcx.sess
|
|
|
|
.struct_span_err(attr.span, "illegal ordinal format in `link_ordinal`")
|
|
|
|
.note("an unsuffixed integer value, e.g., `1`, is expected")
|
|
|
|
.emit();
|
2019-09-18 14:40:08 +00:00
|
|
|
None
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
fn check_link_name_xor_ordinal(
|
|
|
|
tcx: TyCtxt<'_>,
|
|
|
|
codegen_fn_attrs: &CodegenFnAttrs,
|
|
|
|
inline_span: Option<Span>,
|
|
|
|
) {
|
|
|
|
if codegen_fn_attrs.link_name.is_none() || codegen_fn_attrs.link_ordinal.is_none() {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
let msg = "cannot use `#[link_name]` with `#[link_ordinal]`";
|
|
|
|
if let Some(span) = inline_span {
|
|
|
|
tcx.sess.span_err(span, msg);
|
|
|
|
} else {
|
|
|
|
tcx.sess.err(msg);
|
|
|
|
}
|
|
|
|
}
|
2020-05-01 12:17:02 +00:00
|
|
|
|
|
|
|
/// Checks the function annotated with `#[target_feature]` is not a safe
|
|
|
|
/// trait method implementation, reporting an error if it is.
|
|
|
|
fn check_target_feature_trait_unsafe(tcx: TyCtxt<'_>, id: LocalDefId, attr_span: Span) {
|
2020-08-12 10:22:56 +00:00
|
|
|
let hir_id = tcx.hir().local_def_id_to_hir_id(id);
|
2020-05-01 12:17:02 +00:00
|
|
|
let node = tcx.hir().get(hir_id);
|
|
|
|
if let Node::ImplItem(hir::ImplItem { kind: hir::ImplItemKind::Fn(..), .. }) = node {
|
2021-10-21 17:41:47 +00:00
|
|
|
let parent_id = tcx.hir().get_parent_item(hir_id);
|
2022-09-20 05:11:23 +00:00
|
|
|
let parent_item = tcx.hir().expect_item(parent_id.def_id);
|
2020-11-22 22:46:21 +00:00
|
|
|
if let hir::ItemKind::Impl(hir::Impl { of_trait: Some(_), .. }) = parent_item.kind {
|
2020-05-01 12:17:02 +00:00
|
|
|
tcx.sess
|
|
|
|
.struct_span_err(
|
|
|
|
attr_span,
|
|
|
|
"`#[target_feature(..)]` cannot be applied to safe trait method",
|
|
|
|
)
|
|
|
|
.span_label(attr_span, "cannot be applied to safe trait method")
|
|
|
|
.span_label(tcx.def_span(id), "not an `unsafe` function")
|
|
|
|
.emit();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|