summaryrefslogtreecommitdiffstats
path: root/compiler/rustc_hir_analysis/src/collect
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-17 12:18:58 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-17 12:18:58 +0000
commita4b7ed7a42c716ab9f05e351f003d589124fd55d (patch)
treeb620cd3f223850b28716e474e80c58059dca5dd4 /compiler/rustc_hir_analysis/src/collect
parentAdding upstream version 1.67.1+dfsg1. (diff)
downloadrustc-a4b7ed7a42c716ab9f05e351f003d589124fd55d.tar.xz
rustc-a4b7ed7a42c716ab9f05e351f003d589124fd55d.zip
Adding upstream version 1.68.2+dfsg1.upstream/1.68.2+dfsg1
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to '')
-rw-r--r--compiler/rustc_hir_analysis/src/collect.rs1033
-rw-r--r--compiler/rustc_hir_analysis/src/collect/generics_of.rs30
-rw-r--r--compiler/rustc_hir_analysis/src/collect/item_bounds.rs24
-rw-r--r--compiler/rustc_hir_analysis/src/collect/lifetimes.rs82
-rw-r--r--compiler/rustc_hir_analysis/src/collect/predicates_of.rs117
-rw-r--r--compiler/rustc_hir_analysis/src/collect/type_of.rs54
6 files changed, 306 insertions, 1034 deletions
diff --git a/compiler/rustc_hir_analysis/src/collect.rs b/compiler/rustc_hir_analysis/src/collect.rs
index 1183a26d5..c17778ce8 100644
--- a/compiler/rustc_hir_analysis/src/collect.rs
+++ b/compiler/rustc_hir_analysis/src/collect.rs
@@ -17,29 +17,26 @@
use crate::astconv::AstConv;
use crate::check::intrinsic::intrinsic_operation_unsafety;
use crate::errors;
-use rustc_ast as ast;
-use rustc_ast::{MetaItemKind, NestedMetaItem};
-use rustc_attr::{list_contains_name, InlineAttr, InstructionSetAttr, OptimizeAttr};
+use hir::def::DefKind;
use rustc_data_structures::captures::Captures;
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
use rustc_errors::{struct_span_err, Applicability, DiagnosticBuilder, ErrorGuaranteed, StashKey};
use rustc_hir as hir;
-use rustc_hir::def_id::{DefId, LocalDefId, LOCAL_CRATE};
+use rustc_hir::def_id::{DefId, LocalDefId};
use rustc_hir::intravisit::{self, Visitor};
-use rustc_hir::weak_lang_items::WEAK_LANG_ITEMS;
-use rustc_hir::{lang_items, GenericParamKind, LangItem, Node};
+use rustc_hir::{GenericParamKind, Node};
+use rustc_infer::infer::TyCtxtInferExt;
+use rustc_infer::traits::ObligationCause;
use rustc_middle::hir::nested_filter;
-use rustc_middle::middle::codegen_fn_attrs::{CodegenFnAttrFlags, CodegenFnAttrs};
-use rustc_middle::mir::mono::Linkage;
use rustc_middle::ty::query::Providers;
use rustc_middle::ty::util::{Discr, IntTypeExt};
-use rustc_middle::ty::{self, AdtKind, Const, DefIdTree, IsSuggestable, ToPredicate, Ty, TyCtxt};
-use rustc_session::lint;
-use rustc_session::parse::feature_err;
+use rustc_middle::ty::{self, AdtKind, Const, IsSuggestable, ToPredicate, Ty, TyCtxt};
use rustc_span::symbol::{kw, sym, Ident, Symbol};
use rustc_span::Span;
-use rustc_target::spec::{abi, SanitizerSet};
+use rustc_target::spec::abi;
+use rustc_trait_selection::infer::InferCtxtExt;
use rustc_trait_selection::traits::error_reporting::suggestions::NextTypeParamName;
+use rustc_trait_selection::traits::ObligationCtxt;
use std::iter;
mod generics_of;
@@ -78,10 +75,7 @@ pub fn provide(providers: &mut Providers) {
impl_polarity,
is_foreign_item,
generator_kind,
- codegen_fn_attrs,
- asm_target_features,
collect_mod_item_types,
- should_inherit_track_caller,
is_type_alias_impl_trait,
..*providers
};
@@ -220,7 +214,7 @@ pub(crate) fn placeholder_type_error_diag<'tcx>(
is_fn = true;
// Check if parent is const or static
- let parent_id = tcx.hir().get_parent_node(hir_ty.hir_id);
+ let parent_id = tcx.hir().parent_id(hir_ty.hir_id);
let parent_node = tcx.hir().get(parent_id);
is_const_or_static = matches!(
@@ -358,7 +352,7 @@ impl<'tcx> ItemCtxt<'tcx> {
}
pub fn to_ty(&self, ast_ty: &hir::Ty<'_>) -> Ty<'tcx> {
- <dyn AstConv<'_>>::ast_ty_to_ty(self, ast_ty)
+ self.astconv().ast_ty_to_ty(ast_ty)
}
pub fn hir_id(&self) -> hir::HirId {
@@ -420,8 +414,7 @@ impl<'tcx> AstConv<'tcx> for ItemCtxt<'tcx> {
poly_trait_ref: ty::PolyTraitRef<'tcx>,
) -> Ty<'tcx> {
if let Some(trait_ref) = poly_trait_ref.no_bound_vars() {
- let item_substs = <dyn AstConv<'tcx>>::create_substs_for_associated_item(
- self,
+ let item_substs = self.astconv().create_substs_for_associated_item(
span,
item_def_id,
item_segment,
@@ -501,7 +494,7 @@ impl<'tcx> AstConv<'tcx> for ItemCtxt<'tcx> {
format!(
"{}::",
// Erase named lt, we want `<A as B<'_>::C`, not `<A as B<'a>::C`.
- self.tcx.anonymize_late_bound_regions(poly_trait_ref).skip_binder(),
+ self.tcx.anonymize_bound_vars(poly_trait_ref).skip_binder(),
),
Applicability::MaybeIncorrect,
);
@@ -512,9 +505,9 @@ impl<'tcx> AstConv<'tcx> for ItemCtxt<'tcx> {
}
}
- fn normalize_ty(&self, _span: Span, ty: Ty<'tcx>) -> Ty<'tcx> {
- // Types in item signatures are not normalized to avoid undue dependencies.
- ty
+ fn probe_adt(&self, _span: Span, ty: Ty<'tcx>) -> Option<ty::AdtDef<'tcx>> {
+ // FIXME(#103640): Should we handle the case where `ty` is a projection?
+ ty.ty_adt_def()
}
fn set_tainted_by_errors(&self, _: ErrorGuaranteed) {
@@ -568,7 +561,7 @@ fn convert_item(tcx: TyCtxt<'_>, item_id: hir::ItemId) {
debug!("convert: item {} with id {}", it.ident, it.hir_id());
let def_id = item_id.owner_id.def_id;
- match it.kind {
+ match &it.kind {
// These don't define types.
hir::ItemKind::ExternCrate(_)
| hir::ItemKind::Use(..)
@@ -576,7 +569,7 @@ fn convert_item(tcx: TyCtxt<'_>, item_id: hir::ItemId) {
| hir::ItemKind::Mod(_)
| hir::ItemKind::GlobalAsm(_) => {}
hir::ItemKind::ForeignMod { items, .. } => {
- for item in items {
+ for item in *items {
let item = tcx.hir().foreign_item(item.id);
tcx.ensure().generics_of(item.owner_id);
tcx.ensure().type_of(item.owner_id);
@@ -626,7 +619,7 @@ fn convert_item(tcx: TyCtxt<'_>, item_id: hir::ItemId) {
tcx.at(it.span).super_predicates_of(def_id);
tcx.ensure().predicates_of(def_id);
}
- hir::ItemKind::Struct(ref struct_def, _) | hir::ItemKind::Union(ref struct_def, _) => {
+ hir::ItemKind::Struct(struct_def, _) | hir::ItemKind::Union(struct_def, _) => {
tcx.ensure().generics_of(def_id);
tcx.ensure().type_of(def_id);
tcx.ensure().predicates_of(def_id);
@@ -851,7 +844,7 @@ fn convert_variant(
)
}
-fn adt_def<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId) -> ty::AdtDef<'tcx> {
+fn adt_def(tcx: TyCtxt<'_>, def_id: DefId) -> ty::AdtDef<'_> {
use rustc_hir::*;
let def_id = def_id.expect_local();
@@ -861,14 +854,14 @@ fn adt_def<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId) -> ty::AdtDef<'tcx> {
};
let repr = tcx.repr_options_of_def(def_id.to_def_id());
- let (kind, variants) = match item.kind {
- ItemKind::Enum(ref def, _) => {
+ let (kind, variants) = match &item.kind {
+ ItemKind::Enum(def, _) => {
let mut distance_from_explicit = 0;
let variants = def
.variants
.iter()
.map(|v| {
- let discr = if let Some(ref e) = v.disr_expr {
+ let discr = if let Some(e) = &v.disr_expr {
distance_from_explicit = 0;
ty::VariantDiscr::Explicit(e.def_id.to_def_id())
} else {
@@ -890,7 +883,7 @@ fn adt_def<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId) -> ty::AdtDef<'tcx> {
(AdtKind::Enum, variants)
}
- ItemKind::Struct(ref def, _) | ItemKind::Union(ref def, _) => {
+ ItemKind::Struct(def, _) | ItemKind::Union(def, _) => {
let adt_kind = match item.kind {
ItemKind::Struct(..) => AdtKind::Struct,
_ => AdtKind::Union,
@@ -956,7 +949,7 @@ fn trait_def(tcx: TyCtxt<'_>, def_id: DefId) -> ty::TraitDef {
.struct_span_err(
attr.span,
"the `#[rustc_must_implement_one_of]` attribute must be \
- used with at least 2 args",
+ used with at least 2 args",
)
.emit();
@@ -988,7 +981,7 @@ fn trait_def(tcx: TyCtxt<'_>, def_id: DefId) -> ty::TraitDef {
tcx.sess
.struct_span_err(
item.span,
- "This function doesn't have a default implementation",
+ "function doesn't have a default implementation",
)
.span_note(attr_span, "required by this annotation")
.emit();
@@ -1000,17 +993,17 @@ fn trait_def(tcx: TyCtxt<'_>, def_id: DefId) -> ty::TraitDef {
}
Some(item) => {
tcx.sess
- .struct_span_err(item.span, "Not a function")
+ .struct_span_err(item.span, "not a function")
.span_note(attr_span, "required by this annotation")
.note(
- "All `#[rustc_must_implement_one_of]` arguments \
- must be associated function names",
+ "all `#[rustc_must_implement_one_of]` arguments must be associated \
+ function names",
)
.emit();
}
None => {
tcx.sess
- .struct_span_err(ident.span, "Function not found in this trait")
+ .struct_span_err(ident.span, "function not found in this trait")
.emit();
}
}
@@ -1028,11 +1021,8 @@ fn trait_def(tcx: TyCtxt<'_>, def_id: DefId) -> ty::TraitDef {
for ident in &*list {
if let Some(dup) = set.insert(ident.name, ident.span) {
tcx.sess
- .struct_span_err(vec![dup, ident.span], "Functions names are duplicated")
- .note(
- "All `#[rustc_must_implement_one_of]` arguments \
- must be unique",
- )
+ .struct_span_err(vec![dup, ident.span], "functions names are duplicated")
+ .note("all `#[rustc_must_implement_one_of]` arguments must be unique")
.emit();
no_dups = false;
@@ -1074,7 +1064,7 @@ fn is_suggestable_infer_ty(ty: &hir::Ty<'_>) -> bool {
is_suggestable_infer_ty(ty) || matches!(length, hir::ArrayLen::Infer(_, _))
}
Tup(tys) => tys.iter().any(is_suggestable_infer_ty),
- Ptr(mut_ty) | Rptr(_, mut_ty) => is_suggestable_infer_ty(mut_ty.ty),
+ Ptr(mut_ty) | Ref(_, mut_ty) => is_suggestable_infer_ty(mut_ty.ty),
OpaqueDef(_, generic_args, _) => are_suggestable_generic_args(generic_args),
Path(hir::QPath::TypeRelative(ty, segment)) => {
is_suggestable_infer_ty(ty) || are_suggestable_generic_args(segment.args().args)
@@ -1119,11 +1109,10 @@ fn fn_sig(tcx: TyCtxt<'_>, def_id: DefId) -> ty::PolyFnSig<'_> {
ImplItem(hir::ImplItem { kind: ImplItemKind::Fn(sig, _), generics, .. }) => {
// Do not try to infer the return type for a impl method coming from a trait
if let Item(hir::Item { kind: ItemKind::Impl(i), .. }) =
- tcx.hir().get(tcx.hir().get_parent_node(hir_id))
+ tcx.hir().get_parent(hir_id)
&& i.of_trait.is_some()
{
- <dyn AstConv<'_>>::ty_of_fn(
- &icx,
+ icx.astconv().ty_of_fn(
hir_id,
sig.header.unsafety,
sig.header.abi,
@@ -1140,15 +1129,9 @@ fn fn_sig(tcx: TyCtxt<'_>, def_id: DefId) -> ty::PolyFnSig<'_> {
kind: TraitItemKind::Fn(FnSig { header, decl, span: _ }, _),
generics,
..
- }) => <dyn AstConv<'_>>::ty_of_fn(
- &icx,
- hir_id,
- header.unsafety,
- header.abi,
- decl,
- Some(generics),
- None,
- ),
+ }) => {
+ icx.astconv().ty_of_fn(hir_id, header.unsafety, header.abi, decl, Some(generics), None)
+ }
ForeignItem(&hir::ForeignItem { kind: ForeignItemKind::Fn(fn_decl, _, _), .. }) => {
let abi = tcx.hir().get_foreign_abi(hir_id);
@@ -1206,12 +1189,11 @@ fn infer_return_ty_for_fn_sig<'tcx>(
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();
+ let ret_ty = fn_sig.output();
if ret_ty.is_suggestable(tcx, false) {
diag.span_suggestion(
ty.span,
@@ -1234,19 +1216,28 @@ fn infer_return_ty_for_fn_sig<'tcx>(
Applicability::MachineApplicable,
);
}
+ } else if let Some(sugg) = suggest_impl_trait(tcx, ret_ty, ty.span, hir_id, def_id) {
+ diag.span_suggestion(
+ ty.span,
+ "replace with an appropriate return type",
+ sugg,
+ Applicability::MachineApplicable,
+ );
} 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");
+ }
+ // Also note how `Fn` traits work just in case!
+ if ret_ty.is_closure() {
+ diag.note(
+ "for more information on `Fn` traits and closure types, see \
+ https://doc.rust-lang.org/book/ch13-01-closures.html",
+ );
}
diag.emit();
- fn_sig
+ ty::Binder::dummy(fn_sig)
}
- None => <dyn AstConv<'_>>::ty_of_fn(
- icx,
+ None => icx.astconv().ty_of_fn(
hir_id,
sig.header.unsafety,
sig.header.abi,
@@ -1257,21 +1248,114 @@ fn infer_return_ty_for_fn_sig<'tcx>(
}
}
-fn impl_trait_ref(tcx: TyCtxt<'_>, def_id: DefId) -> Option<ty::TraitRef<'_>> {
+fn suggest_impl_trait<'tcx>(
+ tcx: TyCtxt<'tcx>,
+ ret_ty: Ty<'tcx>,
+ span: Span,
+ hir_id: hir::HirId,
+ def_id: LocalDefId,
+) -> Option<String> {
+ let format_as_assoc: fn(_, _, _, _, _) -> _ =
+ |tcx: TyCtxt<'tcx>,
+ _: ty::SubstsRef<'tcx>,
+ trait_def_id: DefId,
+ assoc_item_def_id: DefId,
+ item_ty: Ty<'tcx>| {
+ let trait_name = tcx.item_name(trait_def_id);
+ let assoc_name = tcx.item_name(assoc_item_def_id);
+ Some(format!("impl {trait_name}<{assoc_name} = {item_ty}>"))
+ };
+ let format_as_parenthesized: fn(_, _, _, _, _) -> _ =
+ |tcx: TyCtxt<'tcx>,
+ substs: ty::SubstsRef<'tcx>,
+ trait_def_id: DefId,
+ _: DefId,
+ item_ty: Ty<'tcx>| {
+ let trait_name = tcx.item_name(trait_def_id);
+ let args_tuple = substs.type_at(1);
+ let ty::Tuple(types) = *args_tuple.kind() else { return None; };
+ if !types.is_suggestable(tcx, false) {
+ return None;
+ }
+ let maybe_ret =
+ if item_ty.is_unit() { String::new() } else { format!(" -> {item_ty}") };
+ Some(format!(
+ "impl {trait_name}({}){maybe_ret}",
+ types.iter().map(|ty| ty.to_string()).collect::<Vec<_>>().join(", ")
+ ))
+ };
+
+ for (trait_def_id, assoc_item_def_id, formatter) in [
+ (
+ tcx.get_diagnostic_item(sym::Iterator),
+ tcx.get_diagnostic_item(sym::IteratorItem),
+ format_as_assoc,
+ ),
+ (
+ tcx.lang_items().future_trait(),
+ tcx.get_diagnostic_item(sym::FutureOutput),
+ format_as_assoc,
+ ),
+ (tcx.lang_items().fn_trait(), tcx.lang_items().fn_once_output(), format_as_parenthesized),
+ (
+ tcx.lang_items().fn_mut_trait(),
+ tcx.lang_items().fn_once_output(),
+ format_as_parenthesized,
+ ),
+ (
+ tcx.lang_items().fn_once_trait(),
+ tcx.lang_items().fn_once_output(),
+ format_as_parenthesized,
+ ),
+ ] {
+ let Some(trait_def_id) = trait_def_id else { continue; };
+ let Some(assoc_item_def_id) = assoc_item_def_id else { continue; };
+ if tcx.def_kind(assoc_item_def_id) != DefKind::AssocTy {
+ continue;
+ }
+ let param_env = tcx.param_env(def_id);
+ let infcx = tcx.infer_ctxt().build();
+ let substs = ty::InternalSubsts::for_item(tcx, trait_def_id, |param, _| {
+ if param.index == 0 { ret_ty.into() } else { infcx.var_for_def(span, param) }
+ });
+ if !infcx.type_implements_trait(trait_def_id, substs, param_env).must_apply_modulo_regions()
+ {
+ continue;
+ }
+ let ocx = ObligationCtxt::new_in_snapshot(&infcx);
+ let item_ty = ocx.normalize(
+ &ObligationCause::misc(span, hir_id),
+ param_env,
+ tcx.mk_projection(assoc_item_def_id, substs),
+ );
+ // FIXME(compiler-errors): We may benefit from resolving regions here.
+ if ocx.select_where_possible().is_empty()
+ && let item_ty = infcx.resolve_vars_if_possible(item_ty)
+ && item_ty.is_suggestable(tcx, false)
+ && let Some(sugg) = formatter(tcx, infcx.resolve_vars_if_possible(substs), trait_def_id, assoc_item_def_id, item_ty)
+ {
+ return Some(sugg);
+ }
+ }
+ None
+}
+
+fn impl_trait_ref(tcx: TyCtxt<'_>, def_id: DefId) -> Option<ty::EarlyBinder<ty::TraitRef<'_>>> {
let icx = ItemCtxt::new(tcx, def_id);
let item = tcx.hir().expect_item(def_id.expect_local());
- match item.kind {
- hir::ItemKind::Impl(ref impl_) => impl_.of_trait.as_ref().map(|ast_trait_ref| {
+ let hir::ItemKind::Impl(impl_) = item.kind else { bug!() };
+ impl_
+ .of_trait
+ .as_ref()
+ .map(|ast_trait_ref| {
let selfty = tcx.type_of(def_id);
- <dyn AstConv<'_>>::instantiate_mono_trait_ref(
- &icx,
+ icx.astconv().instantiate_mono_trait_ref(
ast_trait_ref,
selfty,
check_impl_constness(tcx, impl_.constness, ast_trait_ref),
)
- }),
- _ => bug!(),
- }
+ })
+ .map(ty::EarlyBinder)
}
fn check_impl_constness(
@@ -1394,15 +1478,8 @@ fn compute_sig_of_foreign_fn_decl<'tcx>(
hir::Unsafety::Unsafe
};
let hir_id = tcx.hir().local_def_id_to_hir_id(def_id.expect_local());
- let fty = <dyn AstConv<'_>>::ty_of_fn(
- &ItemCtxt::new(tcx, def_id),
- hir_id,
- unsafety,
- abi,
- decl,
- None,
- None,
- );
+ let fty =
+ ItemCtxt::new(tcx, def_id).astconv().ty_of_fn(hir_id, unsafety, abi, decl, None, None);
// Feature gate SIMD types in FFI, since I am not sure that the
// ABIs are handled at all correctly. -huonw
@@ -1433,7 +1510,7 @@ fn compute_sig_of_foreign_fn_decl<'tcx>(
for (input, ty) in iter::zip(decl.inputs, fty.inputs().skip_binder()) {
check(input, *ty)
}
- if let hir::FnRetTy::Return(ref ty) = decl.output {
+ if let hir::FnRetTy::Return(ty) = decl.output {
check(ty, fty.output().skip_binder())
}
}
@@ -1460,798 +1537,6 @@ fn generator_kind(tcx: TyCtxt<'_>, def_id: DefId) -> Option<hir::GeneratorKind>
}
}
-fn from_target_feature(
- tcx: TyCtxt<'_>,
- attr: &ast::Attribute,
- supported_target_features: &FxHashMap<String, Option<Symbol>>,
- target_features: &mut Vec<Symbol>,
-) {
- let Some(list) = attr.meta_item_list() else { return };
- let bad_item = |span| {
- let msg = "malformed `target_feature` attribute input";
- let code = "enable = \"..\"";
- tcx.sess
- .struct_span_err(span, msg)
- .span_suggestion(span, "must be of the form", code, Applicability::HasPlaceholders)
- .emit();
- };
- let rust_features = tcx.features();
- for item in list {
- // Only `enable = ...` is accepted in the meta-item list.
- if !item.has_name(sym::enable) {
- bad_item(item.span());
- continue;
- }
-
- // Must be of the form `enable = "..."` (a string).
- let Some(value) = item.value_str() else {
- bad_item(item.span());
- continue;
- };
-
- // We allow comma separation to enable multiple features.
- target_features.extend(value.as_str().split(',').filter_map(|feature| {
- 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");
- }
- }
- err.emit();
- return None;
- };
-
- // Only allow features whose feature gates have been enabled.
- let allowed = match feature_gate.as_ref().copied() {
- 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,
- Some(sym::riscv_target_feature) => rust_features.riscv_target_feature,
- 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,
- Some(sym::ermsb_target_feature) => rust_features.ermsb_target_feature,
- Some(sym::bpf_target_feature) => rust_features.bpf_target_feature,
- Some(sym::aarch64_ver_target_feature) => rust_features.aarch64_ver_target_feature,
- Some(name) => bug!("unknown target feature gate {}", name),
- None => true,
- };
- if !allowed {
- feature_err(
- &tcx.sess.parse_sess,
- feature_gate.unwrap(),
- item.span(),
- &format!("the target feature `{}` is currently unstable", feature),
- )
- .emit();
- }
- Some(Symbol::intern(feature))
- }));
- }
-}
-
-fn linkage_by_name(tcx: TyCtxt<'_>, def_id: LocalDefId, name: &str) -> Linkage {
- use rustc_middle::mir::mono::Linkage::*;
-
- // 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
- // Rust code in the first place but allow them anyway and trust that the
- // user knows what they're doing. Who knows, unanticipated use cases may pop
- // up in the future.
- //
- // 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,
- _ => tcx.sess.span_fatal(tcx.def_span(def_id), "invalid linkage specified"),
- }
-}
-
-fn codegen_fn_attrs(tcx: TyCtxt<'_>, did: DefId) -> CodegenFnAttrs {
- if cfg!(debug_assertions) {
- let def_kind = tcx.def_kind(did);
- assert!(
- def_kind.has_codegen_attrs(),
- "unexpected `def_kind` in `codegen_fn_attrs`: {def_kind:?}",
- );
- }
-
- let did = did.expect_local();
- let attrs = tcx.hir().attrs(tcx.hir().local_def_id_to_hir_id(did));
- let mut codegen_fn_attrs = CodegenFnAttrs::new();
- if tcx.should_inherit_track_caller(did) {
- codegen_fn_attrs.flags |= CodegenFnAttrFlags::TRACK_CALLER;
- }
-
- let supported_target_features = tcx.supported_target_features(LOCAL_CRATE);
-
- let mut inline_span = None;
- let mut link_ordinal_span = None;
- let mut no_sanitize_span = None;
- for attr in attrs.iter() {
- if attr.has_name(sym::cold) {
- codegen_fn_attrs.flags |= CodegenFnAttrFlags::COLD;
- } else if attr.has_name(sym::rustc_allocator) {
- codegen_fn_attrs.flags |= CodegenFnAttrFlags::ALLOCATOR;
- } else if attr.has_name(sym::ffi_returns_twice) {
- if tcx.is_foreign_item(did) {
- codegen_fn_attrs.flags |= CodegenFnAttrFlags::FFI_RETURNS_TWICE;
- } else {
- // `#[ffi_returns_twice]` is only allowed `extern fn`s.
- struct_span_err!(
- tcx.sess,
- attr.span,
- E0724,
- "`#[ffi_returns_twice]` may only be used on foreign functions"
- )
- .emit();
- }
- } else if attr.has_name(sym::ffi_pure) {
- if tcx.is_foreign_item(did) {
- if attrs.iter().any(|a| a.has_name(sym::ffi_const)) {
- // `#[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();
- }
- } else if attr.has_name(sym::ffi_const) {
- if tcx.is_foreign_item(did) {
- 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();
- }
- } else if attr.has_name(sym::rustc_nounwind) {
- codegen_fn_attrs.flags |= CodegenFnAttrFlags::NEVER_UNWIND;
- } 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;
- } else if attr.has_name(sym::naked) {
- codegen_fn_attrs.flags |= CodegenFnAttrFlags::NAKED;
- } else if attr.has_name(sym::no_mangle) {
- codegen_fn_attrs.flags |= CodegenFnAttrFlags::NO_MANGLE;
- } else if attr.has_name(sym::no_coverage) {
- codegen_fn_attrs.flags |= CodegenFnAttrFlags::NO_COVERAGE;
- } else if attr.has_name(sym::rustc_std_internal_symbol) {
- codegen_fn_attrs.flags |= CodegenFnAttrFlags::RUSTC_STD_INTERNAL_SYMBOL;
- } else if attr.has_name(sym::used) {
- 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(_) => {
- tcx.sess.emit_err(errors::ExpectedUsedSymbol { span: attr.span });
- }
- 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);
- codegen_fn_attrs.flags |= if is_like_elf {
- CodegenFnAttrFlags::USED
- } else {
- CodegenFnAttrFlags::USED_LINKER
- };
- }
- }
- } else if attr.has_name(sym::cmse_nonsecure_entry) {
- if !matches!(tcx.fn_sig(did).abi(), abi::Abi::C { .. }) {
- struct_span_err!(
- tcx.sess,
- attr.span,
- E0776,
- "`#[cmse_nonsecure_entry]` requires C ABI"
- )
- .emit();
- }
- if !tcx.sess.target.llvm_target.contains("thumbv8m") {
- 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;
- } else if attr.has_name(sym::thread_local) {
- codegen_fn_attrs.flags |= CodegenFnAttrFlags::THREAD_LOCAL;
- } else if attr.has_name(sym::track_caller) {
- if !tcx.is_closure(did.to_def_id()) && tcx.fn_sig(did).abi() != abi::Abi::Rust {
- struct_span_err!(tcx.sess, attr.span, E0737, "`#[track_caller]` requires Rust ABI")
- .emit();
- }
- if tcx.is_closure(did.to_def_id()) && !tcx.features().closure_track_caller {
- feature_err(
- &tcx.sess.parse_sess,
- sym::closure_track_caller,
- attr.span,
- "`#[track_caller]` on closures is currently unstable",
- )
- .emit();
- }
- codegen_fn_attrs.flags |= CodegenFnAttrFlags::TRACK_CALLER;
- } else if attr.has_name(sym::export_name) {
- if let Some(s) = attr.value_str() {
- if s.as_str().contains('\0') {
- // `#[export_name = ...]` will be converted to a null-terminated string,
- // so it may not contain any null characters.
- struct_span_err!(
- tcx.sess,
- attr.span,
- E0648,
- "`export_name` may not contain null characters"
- )
- .emit();
- }
- codegen_fn_attrs.export_name = Some(s);
- }
- } else if attr.has_name(sym::target_feature) {
- if !tcx.is_closure(did.to_def_id())
- && tcx.fn_sig(did).unsafety() == hir::Unsafety::Normal
- {
- if tcx.sess.target.is_like_wasm || tcx.sess.opts.actually_rustdoc {
- // The `#[target_feature]` attribute is allowed on
- // WebAssembly targets on all functions, including safe
- // ones. Other targets require that `#[target_feature]` is
- // only applied to unsafe functions (pending the
- // `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)
- //
- // 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.
- } else if !tcx.features().target_feature_11 {
- let mut err = feature_err(
- &tcx.sess.parse_sess,
- sym::target_feature_11,
- attr.span,
- "`#[target_feature(..)]` can only be applied to `unsafe` functions",
- );
- err.span_label(tcx.def_span(did), "not an `unsafe` function");
- err.emit();
- } else {
- check_target_feature_trait_unsafe(tcx, did, attr.span);
- }
- }
- from_target_feature(
- tcx,
- attr,
- supported_target_features,
- &mut codegen_fn_attrs.target_features,
- );
- } else if attr.has_name(sym::linkage) {
- if let Some(val) = attr.value_str() {
- 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;
- }
- }
- } else if attr.has_name(sym::link_section) {
- if let Some(val) = attr.value_str() {
- if val.as_str().bytes().any(|b| b == 0) {
- let msg = format!(
- "illegal null byte in link_section \
- value: `{}`",
- &val
- );
- tcx.sess.span_err(attr.span, &msg);
- } else {
- codegen_fn_attrs.link_section = Some(val);
- }
- }
- } else if attr.has_name(sym::link_name) {
- codegen_fn_attrs.link_name = attr.value_str();
- } else if attr.has_name(sym::link_ordinal) {
- link_ordinal_span = Some(attr.span);
- if let ordinal @ Some(_) = check_link_ordinal(tcx, attr) {
- codegen_fn_attrs.link_ordinal = ordinal;
- }
- } else if attr.has_name(sym::no_sanitize) {
- no_sanitize_span = Some(attr.span);
- if let Some(list) = attr.meta_item_list() {
- for item in list.iter() {
- if item.has_name(sym::address) {
- codegen_fn_attrs.no_sanitize |= SanitizerSet::ADDRESS;
- } else if item.has_name(sym::cfi) {
- codegen_fn_attrs.no_sanitize |= SanitizerSet::CFI;
- } else if item.has_name(sym::memory) {
- codegen_fn_attrs.no_sanitize |= SanitizerSet::MEMORY;
- } else if item.has_name(sym::memtag) {
- codegen_fn_attrs.no_sanitize |= SanitizerSet::MEMTAG;
- } else if item.has_name(sym::shadow_call_stack) {
- codegen_fn_attrs.no_sanitize |= SanitizerSet::SHADOWCALLSTACK;
- } else if item.has_name(sym::thread) {
- codegen_fn_attrs.no_sanitize |= SanitizerSet::THREAD;
- } else if item.has_name(sym::hwaddress) {
- codegen_fn_attrs.no_sanitize |= SanitizerSet::HWADDRESS;
- } else {
- tcx.sess
- .struct_span_err(item.span(), "invalid argument for `no_sanitize`")
- .note("expected one of: `address`, `cfi`, `hwaddress`, `memory`, `memtag`, `shadow-call-stack`, or `thread`")
- .emit();
- }
- }
- }
- } else if attr.has_name(sym::instruction_set) {
- codegen_fn_attrs.instruction_set = match attr.meta_kind() {
- 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] => {
- if !tcx.sess.target.has_thumb_interworking {
- 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
- }
- };
- } else if attr.has_name(sym::repr) {
- 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,
- };
- }
- }
-
- codegen_fn_attrs.inline = attrs.iter().fold(InlineAttr::None, |ia, attr| {
- if !attr.has_name(sym::inline) {
- return ia;
- }
- match attr.meta_kind() {
- Some(MetaItemKind::Word) => InlineAttr::Hint,
- Some(MetaItemKind::List(ref items)) => {
- inline_span = Some(attr.span);
- if items.len() != 1 {
- struct_span_err!(
- tcx.sess.diagnostic(),
- attr.span,
- E0534,
- "expected one argument"
- )
- .emit();
- InlineAttr::None
- } else if list_contains_name(&items, sym::always) {
- InlineAttr::Always
- } else if list_contains_name(&items, sym::never) {
- InlineAttr::Never
- } else {
- struct_span_err!(
- tcx.sess.diagnostic(),
- items[0].span(),
- E0535,
- "invalid argument"
- )
- .help("valid inline arguments are `always` and `never`")
- .emit();
-
- InlineAttr::None
- }
- }
- Some(MetaItemKind::NameValue(_)) => ia,
- None => ia,
- }
- });
-
- codegen_fn_attrs.optimize = attrs.iter().fold(OptimizeAttr::None, |ia, attr| {
- if !attr.has_name(sym::optimize) {
- return ia;
- }
- let err = |sp, s| struct_span_err!(tcx.sess.diagnostic(), sp, E0722, "{}", s).emit();
- match attr.meta_kind() {
- 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
- } else if list_contains_name(&items, sym::size) {
- OptimizeAttr::Size
- } else if list_contains_name(&items, sym::speed) {
- OptimizeAttr::Speed
- } else {
- err(items[0].span(), "invalid argument");
- OptimizeAttr::None
- }
- }
- Some(MetaItemKind::NameValue(_)) => ia,
- None => ia,
- }
- });
-
- // #73631: closures inherit `#[target_feature]` annotations
- if tcx.features().target_feature_11 && tcx.is_closure(did.to_def_id()) {
- let owner_id = tcx.parent(did.to_def_id());
- 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());
- }
- }
-
- // 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.
- if !codegen_fn_attrs.target_features.is_empty() {
- if codegen_fn_attrs.inline == InlineAttr::Always {
- if let Some(span) = inline_span {
- tcx.sess.span_err(
- span,
- "cannot use `#[inline(always)]` with \
- `#[target_feature]`",
- );
- }
- }
- }
-
- if !codegen_fn_attrs.no_sanitize.is_empty() {
- if codegen_fn_attrs.inline == InlineAttr::Always {
- if let (Some(no_sanitize_span), Some(inline_span)) = (no_sanitize_span, inline_span) {
- let hir_id = tcx.hir().local_def_id_to_hir_id(did);
- tcx.struct_span_lint_hir(
- lint::builtin::INLINE_NO_SANITIZE,
- hir_id,
- no_sanitize_span,
- "`no_sanitize` will have no effect after inlining",
- |lint| lint.span_note(inline_span, "inlining requested here"),
- )
- }
- }
- }
-
- if codegen_fn_attrs.flags.contains(CodegenFnAttrFlags::NAKED) {
- codegen_fn_attrs.flags |= CodegenFnAttrFlags::NO_COVERAGE;
- codegen_fn_attrs.inline = InlineAttr::Never;
- }
-
- // 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.
- if WEAK_LANG_ITEMS.iter().any(|&l| tcx.lang_items().get(l) == Some(did.to_def_id())) {
- codegen_fn_attrs.flags |= CodegenFnAttrFlags::RUSTC_STD_INTERNAL_SYMBOL;
- }
- 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);
- }
- check_link_name_xor_ordinal(tcx, &codegen_fn_attrs, link_ordinal_span);
-
- // 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;
- }
-
- // 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;
- }
- }
-
- codegen_fn_attrs
-}
-
-/// Computes the set of target features used in a function for the purposes of
-/// inline assembly.
-fn asm_target_features<'tcx>(tcx: TyCtxt<'tcx>, did: DefId) -> &'tcx FxHashSet<Symbol> {
- let mut target_features = tcx.sess.unstable_target_features.clone();
- if tcx.def_kind(did).has_codegen_attrs() {
- 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);
- }
- }
- }
-
- tcx.arena.alloc(target_features)
-}
-
-/// 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 {
- if let Some(impl_item) = tcx.opt_associated_item(def_id)
- && let ty::AssocItemContainer::ImplContainer = impl_item.container
- && let Some(trait_item) = impl_item.trait_item_def_id
- {
- return tcx
- .codegen_fn_attrs(trait_item)
- .flags
- .intersects(CodegenFnAttrFlags::TRACK_CALLER);
- }
-
- false
-}
-
-fn check_link_ordinal(tcx: TyCtxt<'_>, attr: &ast::Attribute) -> Option<u16> {
- use rustc_ast::{LitIntType, LitKind, MetaItemLit};
- 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();
- }
- let meta_item_list = attr.meta_item_list();
- let meta_item_list = meta_item_list.as_deref();
- let sole_meta_list = match meta_item_list {
- Some([item]) => item.lit(),
- 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;
- }
- _ => None,
- };
- if let Some(MetaItemLit { kind: LitKind::Int(ordinal, LitIntType::Unsuffixed), .. }) =
- sole_meta_list
- {
- // 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)
- } else {
- let msg = format!("ordinal value in `link_ordinal` is too large: `{}`", &ordinal);
- tcx.sess
- .struct_span_err(attr.span, &msg)
- .note("the value may not exceed `u16::MAX`")
- .emit();
- None
- }
- } else {
- tcx.sess
- .struct_span_err(attr.span, "illegal ordinal format in `link_ordinal`")
- .note("an unsuffixed integer value, e.g., `1`, is expected")
- .emit();
- 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);
- }
-}
-
-/// 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) {
- let hir_id = tcx.hir().local_def_id_to_hir_id(id);
- let node = tcx.hir().get(hir_id);
- if let Node::ImplItem(hir::ImplItem { kind: hir::ImplItemKind::Fn(..), .. }) = node {
- let parent_id = tcx.hir().get_parent_item(hir_id);
- let parent_item = tcx.hir().expect_item(parent_id.def_id);
- if let hir::ItemKind::Impl(hir::Impl { of_trait: Some(_), .. }) = parent_item.kind {
- 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();
- }
- }
-}
-
fn is_type_alias_impl_trait<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId) -> bool {
match tcx.hir().get_if_local(def_id) {
Some(Node::Item(hir::Item { kind: hir::ItemKind::OpaqueTy(opaque), .. })) => {
diff --git a/compiler/rustc_hir_analysis/src/collect/generics_of.rs b/compiler/rustc_hir_analysis/src/collect/generics_of.rs
index 639f81f20..014ee9fcc 100644
--- a/compiler/rustc_hir_analysis/src/collect/generics_of.rs
+++ b/compiler/rustc_hir_analysis/src/collect/generics_of.rs
@@ -79,7 +79,7 @@ pub(super) fn generics_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::Generics {
let generics = tcx.generics_of(parent_def_id.to_def_id());
let param_def_idx = generics.param_def_id_to_index[&param_id.to_def_id()];
// In the above example this would be .params[..N#0]
- let params = generics.params[..param_def_idx as usize].to_owned();
+ let params = generics.params_to(param_def_idx as usize, tcx).to_owned();
let param_def_id_to_index =
params.iter().map(|param| (param.def_id, param.index)).collect();
@@ -104,18 +104,18 @@ pub(super) fn generics_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::Generics {
// `min_const_generics`.
Some(parent_def_id.to_def_id())
} else {
- let parent_node = tcx.hir().get(tcx.hir().get_parent_node(hir_id));
+ let parent_node = tcx.hir().get_parent(hir_id);
match parent_node {
// HACK(eddyb) this provides the correct generics for repeat
// expressions' count (i.e. `N` in `[x; N]`), and explicit
// `enum` discriminants (i.e. `D` in `enum Foo { Bar = D }`),
// as they shouldn't be able to cause query cycle errors.
- Node::Expr(&Expr { kind: ExprKind::Repeat(_, ref constant), .. })
+ Node::Expr(Expr { kind: ExprKind::Repeat(_, constant), .. })
if constant.hir_id() == hir_id =>
{
Some(parent_def_id.to_def_id())
}
- Node::Variant(Variant { disr_expr: Some(ref constant), .. })
+ Node::Variant(Variant { disr_expr: Some(constant), .. })
if constant.hir_id == hir_id =>
{
Some(parent_def_id.to_def_id())
@@ -259,7 +259,7 @@ pub(super) fn generics_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::Generics {
params.extend(ast_generics.params.iter().filter_map(|param| match param.kind {
GenericParamKind::Lifetime { .. } => None,
- GenericParamKind::Type { ref default, synthetic, .. } => {
+ GenericParamKind::Type { default, synthetic, .. } => {
if default.is_some() {
match allow_defaults {
Defaults::Allowed => {}
@@ -334,7 +334,7 @@ pub(super) fn generics_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::Generics {
// provide junk type parameter defs for const blocks.
if let Node::AnonConst(_) = node {
- let parent_node = tcx.hir().get(tcx.hir().get_parent_node(hir_id));
+ let parent_node = tcx.hir().get_parent(hir_id);
if let Node::Expr(&Expr { kind: ExprKind::ConstBlock(_), .. }) = parent_node {
params.push(ty::GenericParamDef {
index: next_index(),
@@ -426,26 +426,22 @@ fn has_late_bound_regions<'tcx>(tcx: TyCtxt<'tcx>, node: Node<'tcx>) -> Option<S
}
match node {
- Node::TraitItem(item) => match item.kind {
- hir::TraitItemKind::Fn(ref sig, _) => {
- has_late_bound_regions(tcx, &item.generics, sig.decl)
- }
+ Node::TraitItem(item) => match &item.kind {
+ hir::TraitItemKind::Fn(sig, _) => has_late_bound_regions(tcx, &item.generics, sig.decl),
_ => None,
},
- Node::ImplItem(item) => match item.kind {
- hir::ImplItemKind::Fn(ref sig, _) => {
- has_late_bound_regions(tcx, &item.generics, sig.decl)
- }
+ Node::ImplItem(item) => match &item.kind {
+ hir::ImplItemKind::Fn(sig, _) => has_late_bound_regions(tcx, &item.generics, sig.decl),
_ => None,
},
Node::ForeignItem(item) => match item.kind {
- hir::ForeignItemKind::Fn(fn_decl, _, ref generics) => {
+ hir::ForeignItemKind::Fn(fn_decl, _, generics) => {
has_late_bound_regions(tcx, generics, fn_decl)
}
_ => None,
},
- Node::Item(item) => match item.kind {
- hir::ItemKind::Fn(ref sig, .., ref generics, _) => {
+ Node::Item(item) => match &item.kind {
+ hir::ItemKind::Fn(sig, .., generics, _) => {
has_late_bound_regions(tcx, generics, sig.decl)
}
_ => None,
diff --git a/compiler/rustc_hir_analysis/src/collect/item_bounds.rs b/compiler/rustc_hir_analysis/src/collect/item_bounds.rs
index 0542e2c8f..8d479f1c3 100644
--- a/compiler/rustc_hir_analysis/src/collect/item_bounds.rs
+++ b/compiler/rustc_hir_analysis/src/collect/item_bounds.rs
@@ -26,9 +26,9 @@ fn associated_type_bounds<'tcx>(
);
let icx = ItemCtxt::new(tcx, assoc_item_def_id);
- let mut bounds = <dyn AstConv<'_>>::compute_bounds(&icx, item_ty, ast_bounds);
+ let mut bounds = icx.astconv().compute_bounds(item_ty, ast_bounds);
// Associated types are implicitly sized unless a `?Sized` bound is found
- <dyn AstConv<'_>>::add_implicitly_sized(&icx, &mut bounds, ast_bounds, None, span);
+ icx.astconv().add_implicitly_sized(&mut bounds, item_ty, ast_bounds, None, span);
let trait_def_id = tcx.parent(assoc_item_def_id);
let trait_predicates = tcx.trait_explicit_predicates_and_bounds(trait_def_id.expect_local());
@@ -44,9 +44,7 @@ fn associated_type_bounds<'tcx>(
}
});
- let all_bounds = tcx
- .arena
- .alloc_from_iter(bounds.predicates(tcx, item_ty).into_iter().chain(bounds_from_parent));
+ let all_bounds = tcx.arena.alloc_from_iter(bounds.predicates().chain(bounds_from_parent));
debug!("associated_type_bounds({}) = {:?}", tcx.def_path_str(assoc_item_def_id), all_bounds);
all_bounds
}
@@ -72,12 +70,12 @@ fn opaque_type_bounds<'tcx>(
};
let icx = ItemCtxt::new(tcx, opaque_def_id);
- let mut bounds = <dyn AstConv<'_>>::compute_bounds(&icx, item_ty, ast_bounds);
+ let mut bounds = icx.astconv().compute_bounds(item_ty, ast_bounds);
// Opaque types are implicitly sized unless a `?Sized` bound is found
- <dyn AstConv<'_>>::add_implicitly_sized(&icx, &mut bounds, ast_bounds, None, span);
+ icx.astconv().add_implicitly_sized(&mut bounds, item_ty, ast_bounds, None, span);
debug!(?bounds);
- tcx.arena.alloc_from_iter(bounds.predicates(tcx, item_ty))
+ tcx.arena.alloc_from_iter(bounds.predicates())
})
}
@@ -101,12 +99,16 @@ pub(super) fn explicit_item_bounds(
}
}
-pub(super) fn item_bounds(tcx: TyCtxt<'_>, def_id: DefId) -> &'_ ty::List<ty::Predicate<'_>> {
- tcx.mk_predicates(
+pub(super) fn item_bounds(
+ tcx: TyCtxt<'_>,
+ def_id: DefId,
+) -> ty::EarlyBinder<&'_ ty::List<ty::Predicate<'_>>> {
+ let bounds = tcx.mk_predicates(
util::elaborate_predicates(
tcx,
tcx.explicit_item_bounds(def_id).iter().map(|&(bound, _span)| bound),
)
.map(|obligation| obligation.predicate),
- )
+ );
+ ty::EarlyBinder(bounds)
}
diff --git a/compiler/rustc_hir_analysis/src/collect/lifetimes.rs b/compiler/rustc_hir_analysis/src/collect/lifetimes.rs
index e4fe3e90e..359122d4e 100644
--- a/compiler/rustc_hir_analysis/src/collect/lifetimes.rs
+++ b/compiler/rustc_hir_analysis/src/collect/lifetimes.rs
@@ -1,9 +1,9 @@
//! Resolution of early vs late bound lifetimes.
//!
-//! Name resolution for lifetimes is performed on the AST and embedded into HIR. From this
+//! Name resolution for lifetimes is performed on the AST and embedded into HIR. From this
//! information, typechecking needs to transform the lifetime parameters into bound lifetimes.
-//! Lifetimes can be early-bound or late-bound. Construction of typechecking terms needs to visit
-//! the types in HIR to identify late-bound lifetimes and assign their Debruijn indices. This file
+//! Lifetimes can be early-bound or late-bound. Construction of typechecking terms needs to visit
+//! the types in HIR to identify late-bound lifetimes and assign their Debruijn indices. This file
//! is also responsible for assigning their semantics to implicit lifetimes in trait objects.
use rustc_ast::walk_list;
@@ -70,7 +70,7 @@ impl RegionExt for Region {
/// that it corresponds to.
///
/// FIXME. This struct gets converted to a `ResolveLifetimes` for
-/// actual use. It has the same data, but indexed by `LocalDefId`. This
+/// actual use. It has the same data, but indexed by `LocalDefId`. This
/// is silly.
#[derive(Debug, Default)]
struct NamedRegionMap {
@@ -276,7 +276,7 @@ fn resolve_lifetimes(tcx: TyCtxt<'_>, local_def_id: hir::OwnerId) -> ResolveLife
rl
}
-fn late_region_as_bound_region<'tcx>(tcx: TyCtxt<'tcx>, region: &Region) -> ty::BoundVariableKind {
+fn late_region_as_bound_region(tcx: TyCtxt<'_>, region: &Region) -> ty::BoundVariableKind {
match region {
Region::LateBound(_, _, def_id) => {
let name = tcx.hir().name(tcx.hir().local_def_id_to_hir_id(def_id.expect_local()));
@@ -428,7 +428,7 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
_ => {}
}
match item.kind {
- hir::ItemKind::Fn(_, ref generics, _) => {
+ hir::ItemKind::Fn(_, generics, _) => {
self.visit_early_late(item.hir_id(), generics, |this| {
intravisit::walk_item(this, item);
});
@@ -508,13 +508,13 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
this.with(scope, |this| intravisit::walk_item(this, item))
});
}
- hir::ItemKind::TyAlias(_, ref generics)
- | hir::ItemKind::Enum(_, ref generics)
- | hir::ItemKind::Struct(_, ref generics)
- | hir::ItemKind::Union(_, ref generics)
- | hir::ItemKind::Trait(_, _, ref generics, ..)
- | hir::ItemKind::TraitAlias(ref generics, ..)
- | hir::ItemKind::Impl(hir::Impl { ref generics, .. }) => {
+ hir::ItemKind::TyAlias(_, generics)
+ | hir::ItemKind::Enum(_, generics)
+ | hir::ItemKind::Struct(_, generics)
+ | hir::ItemKind::Union(_, generics)
+ | hir::ItemKind::Trait(_, _, generics, ..)
+ | hir::ItemKind::TraitAlias(generics, ..)
+ | hir::ItemKind::Impl(&hir::Impl { generics, .. }) => {
// These kinds of items have only early-bound lifetime parameters.
let lifetimes = generics
.params
@@ -544,7 +544,7 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
fn visit_foreign_item(&mut self, item: &'tcx hir::ForeignItem<'tcx>) {
match item.kind {
- hir::ForeignItemKind::Fn(_, _, ref generics) => {
+ hir::ForeignItemKind::Fn(_, _, generics) => {
self.visit_early_late(item.hir_id(), generics, |this| {
intravisit::walk_foreign_item(this, item);
})
@@ -561,7 +561,7 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
#[instrument(level = "debug", skip(self))]
fn visit_ty(&mut self, ty: &'tcx hir::Ty<'tcx>) {
match ty.kind {
- hir::TyKind::BareFn(ref c) => {
+ hir::TyKind::BareFn(c) => {
let (lifetimes, binders): (FxIndexMap<LocalDefId, Region>, Vec<_>) = c
.generic_params
.iter()
@@ -587,7 +587,7 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
intravisit::walk_ty(this, ty);
});
}
- hir::TyKind::TraitObject(bounds, ref lifetime, _) => {
+ hir::TyKind::TraitObject(bounds, lifetime, _) => {
debug!(?bounds, ?lifetime, "TraitObject");
let scope = Scope::TraitRefBoundary { s: self.scope };
self.with(scope, |this| {
@@ -617,7 +617,7 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
LifetimeName::Error => {}
}
}
- hir::TyKind::Rptr(ref lifetime_ref, ref mt) => {
+ hir::TyKind::Ref(lifetime_ref, ref mt) => {
self.visit_lifetime(lifetime_ref);
let scope = Scope::ObjectLifetimeDefault {
lifetime: self.map.defs.get(&lifetime_ref.hir_id).cloned(),
@@ -632,7 +632,7 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
// ^ ^ this gets resolved in the scope of
// the opaque_ty generics
let opaque_ty = self.tcx.hir().item(item_id);
- match opaque_ty.kind {
+ match &opaque_ty.kind {
hir::ItemKind::OpaqueTy(hir::OpaqueTy {
origin: hir::OpaqueTyOrigin::TyAlias,
..
@@ -655,7 +655,7 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
origin: hir::OpaqueTyOrigin::FnReturn(..) | hir::OpaqueTyOrigin::AsyncFn(..),
..
}) => {}
- ref i => bug!("`impl Trait` pointed to non-opaque type?? {:#?}", i),
+ i => bug!("`impl Trait` pointed to non-opaque type?? {:#?}", i),
};
// Resolve the lifetimes that are applied to the opaque type.
@@ -682,7 +682,7 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
};
let hir_id = self.tcx.hir().local_def_id_to_hir_id(def_id);
// Ensure that the parent of the def is an item, not HRTB
- let parent_id = self.tcx.hir().get_parent_node(hir_id);
+ let parent_id = self.tcx.hir().parent_id(hir_id);
if !parent_id.is_owner() {
struct_span_err!(
self.tcx.sess,
@@ -720,7 +720,7 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
intravisit::walk_trait_item(this, trait_item)
});
}
- Type(bounds, ref ty) => {
+ Type(bounds, ty) => {
let generics = &trait_item.generics;
let lifetimes = generics
.params
@@ -766,7 +766,7 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
Fn(..) => self.visit_early_late(impl_item.hir_id(), &impl_item.generics, |this| {
intravisit::walk_impl_item(this, impl_item)
}),
- Type(ref ty) => {
+ Type(ty) => {
let generics = &impl_item.generics;
let lifetimes: FxIndexMap<LocalDefId, Region> = generics
.params
@@ -817,7 +817,7 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
fn visit_path(&mut self, path: &hir::Path<'tcx>, _: hir::HirId) {
for (i, segment) in path.segments.iter().enumerate() {
let depth = path.segments.len() - i - 1;
- if let Some(ref args) = segment.args {
+ if let Some(args) = segment.args {
self.visit_segment_args(path.res, depth, args);
}
}
@@ -833,7 +833,7 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
) {
let output = match fd.output {
hir::FnRetTy::DefaultReturn(_) => None,
- hir::FnRetTy::Return(ref ty) => Some(&**ty),
+ hir::FnRetTy::Return(ty) => Some(ty),
};
self.visit_fn_like_elision(&fd.inputs, output, matches!(fk, intravisit::FnKind::Closure));
intravisit::walk_fn_kind(self, fk);
@@ -846,13 +846,13 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
for param in generics.params {
match param.kind {
GenericParamKind::Lifetime { .. } => {}
- GenericParamKind::Type { ref default, .. } => {
- if let Some(ref ty) = default {
- this.visit_ty(&ty);
+ GenericParamKind::Type { default, .. } => {
+ if let Some(ty) = default {
+ this.visit_ty(ty);
}
}
- GenericParamKind::Const { ref ty, default } => {
- this.visit_ty(&ty);
+ GenericParamKind::Const { ty, default } => {
+ this.visit_ty(ty);
if let Some(default) = default {
this.visit_body(this.tcx.hir().body(default.body));
}
@@ -863,9 +863,9 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
match predicate {
&hir::WherePredicate::BoundPredicate(hir::WhereBoundPredicate {
hir_id,
- ref bounded_ty,
+ bounded_ty,
bounds,
- ref bound_generic_params,
+ bound_generic_params,
origin,
..
}) => {
@@ -905,7 +905,7 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
})
}
&hir::WherePredicate::RegionPredicate(hir::WhereRegionPredicate {
- ref lifetime,
+ lifetime,
bounds,
..
}) => {
@@ -914,7 +914,7 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
if lifetime.res != hir::LifetimeName::Static {
for bound in bounds {
- let hir::GenericBound::Outlives(ref lt) = bound else {
+ let hir::GenericBound::Outlives(lt) = bound else {
continue;
};
if lt.res != hir::LifetimeName::Static {
@@ -939,8 +939,8 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
}
}
&hir::WherePredicate::EqPredicate(hir::WhereEqPredicate {
- ref lhs_ty,
- ref rhs_ty,
+ lhs_ty,
+ rhs_ty,
..
}) => {
this.visit_ty(lhs_ty);
@@ -1018,7 +1018,7 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
}
}
-fn object_lifetime_default<'tcx>(tcx: TyCtxt<'tcx>, param_def_id: DefId) -> ObjectLifetimeDefault {
+fn object_lifetime_default(tcx: TyCtxt<'_>, param_def_id: DefId) -> ObjectLifetimeDefault {
debug_assert_eq!(tcx.def_kind(param_def_id), DefKind::TyParam);
let param_def_id = param_def_id.expect_local();
let parent_def_id = tcx.local_parent(param_def_id);
@@ -1042,7 +1042,7 @@ fn object_lifetime_default<'tcx>(tcx: TyCtxt<'tcx>, param_def_id: DefId) -> Obje
}
for bound in bound.bounds {
- if let hir::GenericBound::Outlives(ref lifetime) = *bound {
+ if let hir::GenericBound::Outlives(lifetime) = bound {
set.insert(lifetime.res);
}
}
@@ -1283,7 +1283,7 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {
// We may fail to resolve higher-ranked lifetimes that are mentioned by APIT.
// AST-based resolution does not care for impl-trait desugaring, which are the
- // responibility of lowering. This may create a mismatch between the resolution
+ // responibility of lowering. This may create a mismatch between the resolution
// AST found (`region_def_id`) which points to HRTB, and what HIR allows.
// ```
// fn foo(x: impl for<'a> Trait<'a, Assoc = impl Copy + 'a>) {}
@@ -1434,7 +1434,7 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {
DefKind::ConstParam => Some(ObjectLifetimeDefault::Empty),
DefKind::TyParam => Some(self.tcx.object_lifetime_default(param.def_id)),
// We may also get a `Trait` or `TraitAlias` because of how generics `Self` parameter
- // works. Ignore it because it can't have a meaningful lifetime default.
+ // works. Ignore it because it can't have a meaningful lifetime default.
DefKind::LifetimeParam | DefKind::Trait | DefKind::TraitAlias => None,
dk => bug!("unexpected def_kind {:?}", dk),
}
@@ -1751,7 +1751,7 @@ fn is_late_bound_map(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Option<&FxIndexSet<
ty::Param(param_ty) => {
self.arg_is_constrained[param_ty.index as usize] = true;
}
- ty::Projection(_) => return ControlFlow::Continue(()),
+ ty::Alias(ty::Projection, _) => return ControlFlow::Continue(()),
_ => (),
}
t.super_visit_with(self)
@@ -1828,7 +1828,7 @@ fn is_late_bound_map(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Option<&FxIndexSet<
}
}
- hir::TyKind::Path(hir::QPath::Resolved(None, ref path)) => {
+ hir::TyKind::Path(hir::QPath::Resolved(None, path)) => {
// consider only the lifetimes on the final
// segment; I am not sure it's even currently
// valid to have them elsewhere, but even if it
diff --git a/compiler/rustc_hir_analysis/src/collect/predicates_of.rs b/compiler/rustc_hir_analysis/src/collect/predicates_of.rs
index 45e241f4e..46b277d98 100644
--- a/compiler/rustc_hir_analysis/src/collect/predicates_of.rs
+++ b/compiler/rustc_hir_analysis/src/collect/predicates_of.rs
@@ -75,7 +75,7 @@ fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::GenericP
const NO_GENERICS: &hir::Generics<'_> = hir::Generics::empty();
- // We use an `IndexSet` to preserves order of insertion.
+ // We use an `IndexSet` to preserve order of insertion.
// Preserving the order of insertion is important here so as not to break UI tests.
let mut predicates: FxIndexSet<(ty::Predicate<'_>, Span)> = FxIndexSet::default();
@@ -85,33 +85,30 @@ fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::GenericP
Node::ImplItem(item) => item.generics,
Node::Item(item) => match item.kind {
- ItemKind::Impl(ref impl_) => {
+ ItemKind::Impl(impl_) => {
if impl_.defaultness.is_default() {
- is_default_impl_trait = tcx.impl_trait_ref(def_id).map(ty::Binder::dummy);
+ is_default_impl_trait =
+ tcx.impl_trait_ref(def_id).map(|t| ty::Binder::dummy(t.subst_identity()));
}
- &impl_.generics
+ impl_.generics
}
- ItemKind::Fn(.., ref generics, _)
- | ItemKind::TyAlias(_, ref generics)
- | ItemKind::Enum(_, ref generics)
- | ItemKind::Struct(_, ref generics)
- | ItemKind::Union(_, ref generics) => *generics,
+ ItemKind::Fn(.., generics, _)
+ | ItemKind::TyAlias(_, generics)
+ | ItemKind::Enum(_, generics)
+ | ItemKind::Struct(_, generics)
+ | ItemKind::Union(_, generics) => generics,
- ItemKind::Trait(_, _, ref generics, ..) => {
+ ItemKind::Trait(_, _, generics, ..) | ItemKind::TraitAlias(generics, _) => {
is_trait = Some(ty::TraitRef::identity(tcx, def_id));
- *generics
+ generics
}
- ItemKind::TraitAlias(ref generics, _) => {
- is_trait = Some(ty::TraitRef::identity(tcx, def_id));
- *generics
- }
- ItemKind::OpaqueTy(OpaqueTy { ref generics, .. }) => generics,
+ ItemKind::OpaqueTy(OpaqueTy { generics, .. }) => generics,
_ => NO_GENERICS,
},
Node::ForeignItem(item) => match item.kind {
ForeignItemKind::Static(..) => NO_GENERICS,
- ForeignItemKind::Fn(_, _, ref generics) => *generics,
+ ForeignItemKind::Fn(_, _, generics) => generics,
ForeignItemKind::Type => NO_GENERICS,
},
@@ -166,15 +163,15 @@ fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::GenericP
let mut bounds = Bounds::default();
// Params are implicitly sized unless a `?Sized` bound is found
- <dyn AstConv<'_>>::add_implicitly_sized(
- &icx,
+ icx.astconv().add_implicitly_sized(
&mut bounds,
+ param_ty,
&[],
Some((param.def_id, ast_generics.predicates)),
param.span,
);
trace!(?bounds);
- predicates.extend(bounds.predicates(tcx, param_ty));
+ predicates.extend(bounds.predicates());
trace!(?predicates);
}
GenericParamKind::Const { .. } => {
@@ -214,22 +211,16 @@ fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::GenericP
}
let mut bounds = Bounds::default();
- <dyn AstConv<'_>>::add_bounds(
- &icx,
- ty,
- bound_pred.bounds.iter(),
- &mut bounds,
- bound_vars,
- );
- predicates.extend(bounds.predicates(tcx, ty));
+ icx.astconv().add_bounds(ty, bound_pred.bounds.iter(), &mut bounds, bound_vars);
+ predicates.extend(bounds.predicates());
}
hir::WherePredicate::RegionPredicate(region_pred) => {
- let r1 = <dyn AstConv<'_>>::ast_region_to_region(&icx, &region_pred.lifetime, None);
+ let r1 = icx.astconv().ast_region_to_region(&region_pred.lifetime, None);
predicates.extend(region_pred.bounds.iter().map(|bound| {
let (r2, span) = match bound {
hir::GenericBound::Outlives(lt) => {
- (<dyn AstConv<'_>>::ast_region_to_region(&icx, lt, None), lt.ident.span)
+ (icx.astconv().ast_region_to_region(lt, None), lt.ident.span)
}
_ => bug!(),
};
@@ -256,12 +247,12 @@ fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::GenericP
// Subtle: before we store the predicates into the tcx, we
// sort them so that predicates like `T: Foo<Item=U>` come
- // before uses of `U`. This avoids false ambiguity errors
+ // before uses of `U`. This avoids false ambiguity errors
// in trait checking. See `setup_constraining_predicates`
// for details.
if let Node::Item(&Item { kind: ItemKind::Impl { .. }, .. }) = node {
let self_ty = tcx.type_of(def_id);
- let trait_ref = tcx.impl_trait_ref(def_id);
+ let trait_ref = tcx.impl_trait_ref(def_id).map(ty::EarlyBinder::subst_identity);
cgp::setup_constraining_predicates(
tcx,
&mut predicates,
@@ -274,7 +265,7 @@ fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::GenericP
// We create bi-directional Outlives predicates between the original
// and the duplicated parameter, to ensure that they do not get out of sync.
if let Node::Item(&Item { kind: ItemKind::OpaqueTy(..), .. }) = node {
- let opaque_ty_id = tcx.hir().get_parent_node(hir_id);
+ let opaque_ty_id = tcx.hir().parent_id(hir_id);
let opaque_ty_node = tcx.hir().get(opaque_ty_id);
let Node::Ty(&Ty { kind: TyKind::OpaqueDef(_, lifetimes, _), .. }) = opaque_ty_node else {
bug!("unexpected {opaque_ty_node:?}")
@@ -282,7 +273,7 @@ fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::GenericP
debug!(?lifetimes);
for (arg, duplicate) in std::iter::zip(lifetimes, ast_generics.params) {
let hir::GenericArg::Lifetime(arg) = arg else { bug!() };
- let orig_region = <dyn AstConv<'_>>::ast_region_to_region(&icx, &arg, None);
+ let orig_region = icx.astconv().ast_region_to_region(&arg, None);
if !matches!(orig_region.kind(), ty::ReEarlyBound(..)) {
// Only early-bound regions can point to the original generic parameter.
continue;
@@ -322,10 +313,10 @@ fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::GenericP
}
}
-fn const_evaluatable_predicates_of<'tcx>(
- tcx: TyCtxt<'tcx>,
+fn const_evaluatable_predicates_of(
+ tcx: TyCtxt<'_>,
def_id: LocalDefId,
-) -> FxIndexSet<(ty::Predicate<'tcx>, Span)> {
+) -> FxIndexSet<(ty::Predicate<'_>, Span)> {
struct ConstCollector<'tcx> {
tcx: TyCtxt<'tcx>,
preds: FxIndexSet<(ty::Predicate<'tcx>, Span)>,
@@ -359,7 +350,7 @@ fn const_evaluatable_predicates_of<'tcx>(
let node = tcx.hir().get(hir_id);
let mut collector = ConstCollector { tcx, preds: FxIndexSet::default() };
- if let hir::Node::Item(item) = node && let hir::ItemKind::Impl(ref impl_) = item.kind {
+ if let hir::Node::Item(item) = node && let hir::ItemKind::Impl(impl_) = item.kind {
if let Some(of_trait) = &impl_.of_trait {
debug!("const_evaluatable_predicates_of({:?}): visit impl trait_ref", def_id);
collector.visit_trait_ref(of_trait);
@@ -406,14 +397,15 @@ pub(super) fn explicit_predicates_of<'tcx>(
// For a predicate from a where clause to become a bound on an
// associated type:
// * It must use the identity substs of the item.
- // * Since any generic parameters on the item are not in scope,
- // this means that the item is not a GAT, and its identity
- // substs are the same as the trait's.
+ // * We're in the scope of the trait, so we can't name any
+ // parameters of the GAT. That means that all we need to
+ // check are that the substs of the projection are the
+ // identity substs of the trait.
// * It must be an associated type for this trait (*not* a
// supertrait).
- if let ty::Projection(projection) = ty.kind() {
+ if let ty::Alias(ty::Projection, projection) = ty.kind() {
projection.substs == trait_identity_substs
- && tcx.associated_item(projection.item_def_id).container_id(tcx) == def_id
+ && tcx.associated_item(projection.def_id).container_id(tcx) == def_id
} else {
false
}
@@ -519,8 +511,8 @@ pub(super) fn super_predicates_that_define_assoc_type(
};
let (generics, bounds) = match item.kind {
- hir::ItemKind::Trait(.., ref generics, ref supertraits, _) => (generics, supertraits),
- hir::ItemKind::TraitAlias(ref generics, ref supertraits) => (generics, supertraits),
+ hir::ItemKind::Trait(.., generics, supertraits, _) => (generics, supertraits),
+ hir::ItemKind::TraitAlias(generics, supertraits) => (generics, supertraits),
_ => span_bug!(item.span, "super_predicates invoked on non-trait"),
};
@@ -529,17 +521,12 @@ pub(super) fn super_predicates_that_define_assoc_type(
// Convert the bounds that follow the colon, e.g., `Bar + Zed` in `trait Foo: Bar + Zed`.
let self_param_ty = tcx.types.self_param;
let superbounds1 = if let Some(assoc_name) = assoc_name {
- <dyn AstConv<'_>>::compute_bounds_that_match_assoc_type(
- &icx,
- self_param_ty,
- bounds,
- assoc_name,
- )
+ icx.astconv().compute_bounds_that_match_assoc_type(self_param_ty, bounds, assoc_name)
} else {
- <dyn AstConv<'_>>::compute_bounds(&icx, self_param_ty, bounds)
+ icx.astconv().compute_bounds(self_param_ty, bounds)
};
- let superbounds1 = superbounds1.predicates(tcx, self_param_ty);
+ let superbounds1 = superbounds1.predicates();
// Convert any explicit superbounds in the where-clause,
// e.g., `trait Foo where Self: Bar`.
@@ -625,18 +612,18 @@ pub(super) fn type_param_predicates(
Node::Item(item) => {
match item.kind {
- ItemKind::Fn(.., ref generics, _)
- | ItemKind::Impl(hir::Impl { ref generics, .. })
- | ItemKind::TyAlias(_, ref generics)
+ ItemKind::Fn(.., generics, _)
+ | ItemKind::Impl(&hir::Impl { generics, .. })
+ | ItemKind::TyAlias(_, generics)
| ItemKind::OpaqueTy(OpaqueTy {
- ref generics,
+ generics,
origin: hir::OpaqueTyOrigin::TyAlias,
..
})
- | ItemKind::Enum(_, ref generics)
- | ItemKind::Struct(_, ref generics)
- | ItemKind::Union(_, ref generics) => generics,
- ItemKind::Trait(_, _, ref generics, ..) => {
+ | ItemKind::Enum(_, generics)
+ | ItemKind::Struct(_, generics)
+ | ItemKind::Union(_, generics) => generics,
+ ItemKind::Trait(_, _, generics, ..) => {
// Implied `Self: Trait` and supertrait bounds.
if param_id == item_hir_id {
let identity_trait_ref = ty::TraitRef::identity(tcx, item_def_id);
@@ -650,7 +637,7 @@ pub(super) fn type_param_predicates(
}
Node::ForeignItem(item) => match item.kind {
- ForeignItemKind::Fn(_, _, ref generics) => generics,
+ ForeignItemKind::Fn(_, _, generics) => generics,
_ => return result,
},
@@ -694,8 +681,8 @@ impl<'tcx> ItemCtxt<'tcx> {
ast_generics
.predicates
.iter()
- .filter_map(|wp| match *wp {
- hir::WherePredicate::BoundPredicate(ref bp) => Some(bp),
+ .filter_map(|wp| match wp {
+ hir::WherePredicate::BoundPredicate(bp) => Some(bp),
_ => None,
})
.flat_map(|bp| {
@@ -748,5 +735,5 @@ fn predicates_from_bound<'tcx>(
) -> Vec<(ty::Predicate<'tcx>, Span)> {
let mut bounds = Bounds::default();
astconv.add_bounds(param_ty, [bound].into_iter(), &mut bounds, bound_vars);
- bounds.predicates(astconv.tcx(), param_ty).collect()
+ bounds.predicates().collect()
}
diff --git a/compiler/rustc_hir_analysis/src/collect/type_of.rs b/compiler/rustc_hir_analysis/src/collect/type_of.rs
index 9bd1715ce..5e388a2f2 100644
--- a/compiler/rustc_hir_analysis/src/collect/type_of.rs
+++ b/compiler/rustc_hir_analysis/src/collect/type_of.rs
@@ -5,6 +5,7 @@ use rustc_hir::intravisit;
use rustc_hir::intravisit::Visitor;
use rustc_hir::{HirId, Node};
use rustc_middle::hir::nested_filter;
+use rustc_middle::ty::print::with_forced_trimmed_paths;
use rustc_middle::ty::subst::InternalSubsts;
use rustc_middle::ty::util::IntTypeExt;
use rustc_middle::ty::{self, DefIdTree, Ty, TyCtxt, TypeFolder, TypeSuperFoldable, TypeVisitable};
@@ -27,7 +28,7 @@ pub(super) fn opt_const_param_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Option<
_ => return None,
};
- let parent_node_id = tcx.hir().get_parent_node(hir_id);
+ let parent_node_id = tcx.hir().parent_id(hir_id);
let parent_node = tcx.hir().get(parent_node_id);
let (generics, arg_idx) = match parent_node {
@@ -52,7 +53,7 @@ pub(super) fn opt_const_param_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Option<
// Using the ItemCtxt convert the HIR for the unresolved assoc type into a
// ty which is a fully resolved projection.
// For the code example above, this would mean converting Self::Assoc<3>
- // into a ty::Projection(<Self as Foo>::Assoc<3>)
+ // into a ty::Alias(ty::Projection, <Self as Foo>::Assoc<3>)
let item_hir_id = tcx
.hir()
.parent_iter(hir_id)
@@ -68,8 +69,8 @@ pub(super) fn opt_const_param_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Option<
// the def_id that this query was called with. We filter to only type and const args here
// as a precaution for if it's ever allowed to elide lifetimes in GAT's. It currently isn't
// but it can't hurt to be safe ^^
- if let ty::Projection(projection) = ty.kind() {
- let generics = tcx.generics_of(projection.item_def_id);
+ if let ty::Alias(ty::Projection, projection) = ty.kind() {
+ let generics = tcx.generics_of(projection.def_id);
let arg_index = segment
.args
@@ -378,7 +379,7 @@ pub(super) fn type_of(tcx: TyCtxt<'_>, def_id: DefId) -> Ty<'_> {
ForeignItemKind::Type => tcx.mk_foreign(def_id.to_def_id()),
},
- Node::Ctor(&ref def) | Node::Variant(Variant { data: ref def, .. }) => match *def {
+ Node::Ctor(def) | Node::Variant(Variant { data: def, .. }) => match def {
VariantData::Unit(..) | VariantData::Struct(..) => {
tcx.type_of(tcx.hir().get_parent_item(hir_id))
}
@@ -401,19 +402,19 @@ pub(super) fn type_of(tcx: TyCtxt<'_>, def_id: DefId) -> Ty<'_> {
}
Node::AnonConst(_) => {
- let parent_node = tcx.hir().get(tcx.hir().get_parent_node(hir_id));
+ let parent_node = tcx.hir().get_parent(hir_id);
match parent_node {
- Node::Ty(&Ty { kind: TyKind::Array(_, ref constant), .. })
- | Node::Expr(&Expr { kind: ExprKind::Repeat(_, ref constant), .. })
+ Node::Ty(Ty { kind: TyKind::Array(_, constant), .. })
+ | Node::Expr(Expr { kind: ExprKind::Repeat(_, constant), .. })
if constant.hir_id() == hir_id =>
{
tcx.types.usize
}
- Node::Ty(&Ty { kind: TyKind::Typeof(ref e), .. }) if e.hir_id == hir_id => {
+ Node::Ty(Ty { kind: TyKind::Typeof(e), .. }) if e.hir_id == hir_id => {
tcx.typeck(def_id).node_type(e.hir_id)
}
- Node::Expr(&Expr { kind: ExprKind::ConstBlock(ref anon_const), .. })
+ Node::Expr(Expr { kind: ExprKind::ConstBlock(anon_const), .. })
if anon_const.hir_id == hir_id =>
{
let substs = InternalSubsts::identity_for_item(tcx, def_id.to_def_id());
@@ -433,18 +434,19 @@ pub(super) fn type_of(tcx: TyCtxt<'_>, def_id: DefId) -> Ty<'_> {
tcx.typeck(def_id).node_type(hir_id)
}
- Node::Variant(Variant { disr_expr: Some(ref e), .. }) if e.hir_id == hir_id => {
+ Node::Variant(Variant { disr_expr: Some(e), .. }) if e.hir_id == hir_id => {
tcx.adt_def(tcx.hir().get_parent_item(hir_id)).repr().discr_type().to_ty(tcx)
}
Node::TypeBinding(
- binding @ &TypeBinding {
+ TypeBinding {
hir_id: binding_id,
- kind: TypeBindingKind::Equality { term: Term::Const(ref e) },
+ kind: TypeBindingKind::Equality { term: Term::Const(e) },
+ ident,
..
},
) if let Node::TraitRef(trait_ref) =
- tcx.hir().get(tcx.hir().get_parent_node(binding_id))
+ tcx.hir().get_parent(*binding_id)
&& e.hir_id == hir_id =>
{
let Some(trait_def_id) = trait_ref.trait_def_id() else {
@@ -453,7 +455,7 @@ pub(super) fn type_of(tcx: TyCtxt<'_>, def_id: DefId) -> Ty<'_> {
let assoc_items = tcx.associated_items(trait_def_id);
let assoc_item = assoc_items.find_by_name_and_kind(
tcx,
- binding.ident,
+ *ident,
ty::AssocKind::Const,
def_id.to_def_id(),
);
@@ -469,9 +471,9 @@ pub(super) fn type_of(tcx: TyCtxt<'_>, def_id: DefId) -> Ty<'_> {
}
Node::TypeBinding(
- binding @ &TypeBinding { hir_id: binding_id, gen_args, ref kind, .. },
+ TypeBinding { hir_id: binding_id, gen_args, kind, ident, .. },
) if let Node::TraitRef(trait_ref) =
- tcx.hir().get(tcx.hir().get_parent_node(binding_id))
+ tcx.hir().get_parent(*binding_id)
&& let Some((idx, _)) =
gen_args.args.iter().enumerate().find(|(_, arg)| {
if let GenericArg::Const(ct) = arg {
@@ -487,7 +489,7 @@ pub(super) fn type_of(tcx: TyCtxt<'_>, def_id: DefId) -> Ty<'_> {
let assoc_items = tcx.associated_items(trait_def_id);
let assoc_item = assoc_items.find_by_name_and_kind(
tcx,
- binding.ident,
+ *ident,
match kind {
// I think `<A: T>` type bindings requires that `A` is a type
TypeBindingKind::Constraint { .. }
@@ -666,7 +668,7 @@ fn find_opaque_ty_constraints_for_tait(tcx: TyCtxt<'_>, def_id: LocalDefId) -> T
let hir_id = tcx.hir().local_def_id_to_hir_id(def_id);
let scope = tcx.hir().get_defining_scope(hir_id);
- let mut locator = ConstraintLocator { def_id: def_id, tcx, found: None, typeck_types: vec![] };
+ let mut locator = ConstraintLocator { def_id, tcx, found: None, typeck_types: vec![] };
debug!(?scope);
@@ -803,7 +805,7 @@ fn find_opaque_ty_constraints_for_rpit(
if let Some(concrete) = concrete {
let scope = tcx.hir().local_def_id_to_hir_id(owner_def_id);
debug!(?scope);
- let mut locator = ConstraintChecker { def_id: def_id, tcx, found: concrete };
+ let mut locator = ConstraintChecker { def_id, tcx, found: concrete };
match tcx.hir().get(scope) {
Node::Item(it) => intravisit::walk_item(&mut locator, it),
@@ -907,10 +909,10 @@ fn infer_placeholder_type<'a>(
Applicability::MachineApplicable,
);
} else {
- err.span_note(
+ with_forced_trimmed_paths!(err.span_note(
tcx.hir().body(body_id).value.span,
- &format!("however, the inferred type `{}` cannot be named", ty),
- );
+ &format!("however, the inferred type `{ty}` cannot be named"),
+ ));
}
}
@@ -931,10 +933,10 @@ fn infer_placeholder_type<'a>(
Applicability::MaybeIncorrect,
);
} else {
- diag.span_note(
+ with_forced_trimmed_paths!(diag.span_note(
tcx.hir().body(body_id).value.span,
- &format!("however, the inferred type `{}` cannot be named", ty),
- );
+ &format!("however, the inferred type `{ty}` cannot be named"),
+ ));
}
}