summaryrefslogtreecommitdiffstats
path: root/compiler/rustc_passes
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-05-30 18:31:44 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-05-30 18:31:44 +0000
commitc23a457e72abe608715ac76f076f47dc42af07a5 (patch)
tree2772049aaf84b5c9d0ed12ec8d86812f7a7904b6 /compiler/rustc_passes
parentReleasing progress-linux version 1.73.0+dfsg1-1~progress7.99u1. (diff)
downloadrustc-c23a457e72abe608715ac76f076f47dc42af07a5.tar.xz
rustc-c23a457e72abe608715ac76f076f47dc42af07a5.zip
Merging upstream version 1.74.1+dfsg1.
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'compiler/rustc_passes')
-rw-r--r--compiler/rustc_passes/messages.ftl73
-rw-r--r--compiler/rustc_passes/src/abi_test.rs197
-rw-r--r--compiler/rustc_passes/src/check_attr.rs122
-rw-r--r--compiler/rustc_passes/src/check_const.rs4
-rw-r--r--compiler/rustc_passes/src/dead.rs4
-rw-r--r--compiler/rustc_passes/src/errors.rs92
-rw-r--r--compiler/rustc_passes/src/hir_stats.rs2
-rw-r--r--compiler/rustc_passes/src/lang_items.rs12
-rw-r--r--compiler/rustc_passes/src/layout_test.rs97
-rw-r--r--compiler/rustc_passes/src/lib.rs1
-rw-r--r--compiler/rustc_passes/src/reachable.rs4
11 files changed, 501 insertions, 107 deletions
diff --git a/compiler/rustc_passes/messages.ftl b/compiler/rustc_passes/messages.ftl
index 6eacbebe7..214c6d709 100644
--- a/compiler/rustc_passes/messages.ftl
+++ b/compiler/rustc_passes/messages.ftl
@@ -4,11 +4,14 @@
-passes_see_issue =
see issue #{$issue} <https://github.com/rust-lang/rust/issues/{$issue}> for more information
-passes_abi =
- abi: {$abi}
-
-passes_align =
- align: {$align}
+passes_abi_invalid_attribute =
+ `#[rustc_abi]` can only be applied to function items, type aliases, and associated functions
+passes_abi_ne =
+ ABIs are not compatible
+ left ABI = {$left}
+ right ABI = {$right}
+passes_abi_of =
+ fn_abi_of({$fn_name}) = {$fn_abi}
passes_allow_incoherent_impl =
`rustc_allow_incoherent_impl` attribute should be applied to impl items.
@@ -101,15 +104,24 @@ passes_collapse_debuginfo =
passes_confusables = attribute should be applied to an inherent method
.label = not an inherent method
-passes_const_impl_const_trait =
- const `impl`s must be for traits marked with `#[const_trait]`
- .note = this trait must be annotated with `#[const_trait]`
-
passes_continue_labeled_block =
`continue` pointing to a labeled block
.label = labeled blocks cannot be `continue`'d
.block_label = labeled block the `continue` points to
+passes_coverage_fn_defn =
+ `#[coverage]` may only be applied to function definitions
+
+passes_coverage_ignored_function_prototype =
+ `#[coverage]` is ignored on function prototypes
+
+passes_coverage_not_coverable =
+ `#[coverage]` must be applied to coverable code
+ .label = not coverable code
+
+passes_coverage_propagate =
+ `#[coverage]` does not propagate into items and must be applied to the contained functions directly
+
passes_dead_codes =
{ $multiple ->
*[true] multiple {$descr}s are
@@ -141,6 +153,9 @@ passes_deprecated_annotation_has_no_effect =
passes_deprecated_attribute =
deprecated attribute must be paired with either stable or unstable attribute
+passes_diagnostic_diagnostic_on_unimplemented_only_for_traits =
+ `#[diagnostic::on_unimplemented]` can only be applied to trait definitions
+
passes_diagnostic_item_first_defined =
the diagnostic item is first defined here
@@ -315,9 +330,6 @@ passes_has_incoherent_inherent_impl =
`rustc_has_incoherent_inherent_impls` attribute should be applied to types or traits.
.label = only adts, extern types and traits are supported
-passes_homogeneous_aggregate =
- homogeneous_aggregate: {$homogeneous_aggregate}
-
passes_ignored_attr =
`#[{$sym}]` is ignored on struct fields and match arms
.warn = {-passes_previously_accepted}
@@ -395,15 +407,28 @@ passes_invalid_stability =
.label = invalid stability version
.item = the stability attribute annotates this item
+passes_lang_item_fn_with_target_feature =
+ `{$name}` language item function is not allowed to have `#[target_feature]`
+ .label = `{$name}` language item function is not allowed to have `#[target_feature]`
+
passes_lang_item_on_incorrect_target =
`{$name}` language item must be applied to a {$expected_target}
.label = attribute should be applied to a {$expected_target}, not a {$actual_target}
passes_layout =
layout error: {$layout_error}
-
+passes_layout_abi =
+ abi: {$abi}
+passes_layout_align =
+ align: {$align}
+passes_layout_homogeneous_aggregate =
+ homogeneous_aggregate: {$homogeneous_aggregate}
+passes_layout_invalid_attribute =
+ `#[rustc_layout]` can only be applied to `struct`/`enum`/`union` declarations and type aliases
passes_layout_of =
layout_of({$normalized_ty}) = {$ty_layout}
+passes_layout_size =
+ size: {$size}
passes_link =
attribute should be applied to an `extern` block with non-Rust ABI
@@ -494,19 +519,6 @@ passes_naked_functions_operands =
passes_naked_tracked_caller =
cannot use `#[track_caller]` with `#[naked]`
-passes_no_coverage_fn_defn =
- `#[no_coverage]` may only be applied to function definitions
-
-passes_no_coverage_ignored_function_prototype =
- `#[no_coverage]` is ignored on function prototypes
-
-passes_no_coverage_not_coverable =
- `#[no_coverage]` must be applied to coverable code
- .label = not coverable code
-
-passes_no_coverage_propagate =
- `#[no_coverage]` does not propagate into items and must be applied to the contained functions directly
-
passes_no_link =
attribute should be applied to an `extern crate` item
.label = not an `extern crate` item
@@ -636,6 +648,10 @@ passes_rustc_lint_opt_ty =
`#[rustc_lint_opt_ty]` should be applied to a struct
.label = not a struct
+passes_rustc_safe_intrinsic =
+ attribute should be applied to intrinsic functions
+ .label = not an intrinsic function
+
passes_rustc_std_internal_symbol =
attribute should be applied to functions or statics
.label = not a function or static
@@ -659,9 +675,6 @@ passes_should_be_applied_to_trait =
attribute should be applied to a trait
.label = not a trait
-passes_size =
- size: {$size}
-
passes_skipping_const_checks = skipping const checks
passes_stability_promotable =
@@ -721,7 +734,7 @@ passes_unrecognized_field =
passes_unrecognized_repr_hint =
unrecognized representation hint
- .help = valid reprs are `C`, `align`, `packed`, `transparent`, `simd`, `i8`, `u8`, `i16`, `u16`, `i32`, `u32`, `i64`, `u64`, `i128`, `u128`, `isize`, `usize`
+ .help = valid reprs are `Rust` (default), `C`, `align`, `packed`, `transparent`, `simd`, `i8`, `u8`, `i16`, `u16`, `i32`, `u32`, `i64`, `u64`, `i128`, `u128`, `isize`, `usize`
passes_unused =
unused attribute
diff --git a/compiler/rustc_passes/src/abi_test.rs b/compiler/rustc_passes/src/abi_test.rs
new file mode 100644
index 000000000..153c39977
--- /dev/null
+++ b/compiler/rustc_passes/src/abi_test.rs
@@ -0,0 +1,197 @@
+use rustc_ast::Attribute;
+use rustc_hir::def::DefKind;
+use rustc_hir::def_id::LocalDefId;
+use rustc_middle::ty::layout::{FnAbiError, LayoutError};
+use rustc_middle::ty::{self, GenericArgs, Instance, Ty, TyCtxt};
+use rustc_span::source_map::Spanned;
+use rustc_span::symbol::sym;
+use rustc_target::abi::call::FnAbi;
+
+use super::layout_test::ensure_wf;
+use crate::errors::{AbiInvalidAttribute, AbiNe, AbiOf, UnrecognizedField};
+
+pub fn test_abi(tcx: TyCtxt<'_>) {
+ if !tcx.features().rustc_attrs {
+ // if the `rustc_attrs` feature is not enabled, don't bother testing ABI
+ return;
+ }
+ for id in tcx.hir_crate_items(()).definitions() {
+ for attr in tcx.get_attrs(id, sym::rustc_abi) {
+ match tcx.def_kind(id) {
+ DefKind::Fn | DefKind::AssocFn => {
+ dump_abi_of_fn_item(tcx, id, attr);
+ }
+ DefKind::TyAlias => {
+ dump_abi_of_fn_type(tcx, id, attr);
+ }
+ _ => {
+ tcx.sess.emit_err(AbiInvalidAttribute { span: tcx.def_span(id) });
+ }
+ }
+ }
+ }
+}
+
+fn unwrap_fn_abi<'tcx>(
+ abi: Result<&'tcx FnAbi<'tcx, Ty<'tcx>>, &'tcx FnAbiError<'tcx>>,
+ tcx: TyCtxt<'tcx>,
+ item_def_id: LocalDefId,
+) -> &'tcx FnAbi<'tcx, Ty<'tcx>> {
+ match abi {
+ Ok(abi) => abi,
+ Err(FnAbiError::Layout(layout_error)) => {
+ tcx.sess.emit_fatal(Spanned {
+ node: layout_error.into_diagnostic(),
+ span: tcx.def_span(item_def_id),
+ });
+ }
+ Err(FnAbiError::AdjustForForeignAbi(e)) => {
+ // Sadly there seems to be no `into_diagnostic` for this case... and I am not sure if
+ // this can even be reached. Anyway this is a perma-unstable debug attribute, an ICE
+ // isn't the worst thing. Also this matches what codegen does.
+ span_bug!(
+ tcx.def_span(item_def_id),
+ "error computing fn_abi_of_instance, cannot adjust for foreign ABI: {e:?}",
+ )
+ }
+ }
+}
+
+fn dump_abi_of_fn_item(tcx: TyCtxt<'_>, item_def_id: LocalDefId, attr: &Attribute) {
+ let param_env = tcx.param_env(item_def_id);
+ let args = GenericArgs::identity_for_item(tcx, item_def_id);
+ let instance = match Instance::resolve(tcx, param_env, item_def_id.into(), args) {
+ Ok(Some(instance)) => instance,
+ Ok(None) => {
+ // Not sure what to do here, but `LayoutError::Unknown` seems reasonable?
+ let ty = tcx.type_of(item_def_id).instantiate_identity();
+ tcx.sess.emit_fatal(Spanned {
+ node: LayoutError::Unknown(ty).into_diagnostic(),
+
+ span: tcx.def_span(item_def_id),
+ });
+ }
+ Err(_guaranteed) => return,
+ };
+ let abi = unwrap_fn_abi(
+ tcx.fn_abi_of_instance(param_env.and((instance, /* extra_args */ ty::List::empty()))),
+ tcx,
+ item_def_id,
+ );
+
+ // Check out the `#[rustc_abi(..)]` attribute to tell what to dump.
+ // The `..` are the names of fields to dump.
+ let meta_items = attr.meta_item_list().unwrap_or_default();
+ for meta_item in meta_items {
+ match meta_item.name_or_empty() {
+ sym::debug => {
+ let fn_name = tcx.item_name(item_def_id.into());
+ tcx.sess.emit_err(AbiOf {
+ span: tcx.def_span(item_def_id),
+ fn_name,
+ // FIXME: using the `Debug` impl here isn't ideal.
+ fn_abi: format!("{:#?}", abi),
+ });
+ }
+
+ name => {
+ tcx.sess.emit_err(UnrecognizedField { span: meta_item.span(), name });
+ }
+ }
+ }
+}
+
+fn test_abi_eq<'tcx>(abi1: &'tcx FnAbi<'tcx, Ty<'tcx>>, abi2: &'tcx FnAbi<'tcx, Ty<'tcx>>) -> bool {
+ if abi1.conv != abi2.conv
+ || abi1.args.len() != abi2.args.len()
+ || abi1.c_variadic != abi2.c_variadic
+ || abi1.fixed_count != abi2.fixed_count
+ || abi1.can_unwind != abi2.can_unwind
+ {
+ return false;
+ }
+
+ abi1.ret.eq_abi(&abi2.ret)
+ && abi1.args.iter().zip(abi2.args.iter()).all(|(arg1, arg2)| arg1.eq_abi(arg2))
+}
+
+fn dump_abi_of_fn_type(tcx: TyCtxt<'_>, item_def_id: LocalDefId, attr: &Attribute) {
+ let param_env = tcx.param_env(item_def_id);
+ let ty = tcx.type_of(item_def_id).instantiate_identity();
+ let span = tcx.def_span(item_def_id);
+ if !ensure_wf(tcx, param_env, ty, item_def_id, span) {
+ return;
+ }
+ let meta_items = attr.meta_item_list().unwrap_or_default();
+ for meta_item in meta_items {
+ match meta_item.name_or_empty() {
+ sym::debug => {
+ let ty::FnPtr(sig) = ty.kind() else {
+ span_bug!(
+ meta_item.span(),
+ "`#[rustc_abi(debug)]` on a type alias requires function pointer type"
+ );
+ };
+ let abi = unwrap_fn_abi(
+ tcx.fn_abi_of_fn_ptr(param_env.and((*sig, /* extra_args */ ty::List::empty()))),
+ tcx,
+ item_def_id,
+ );
+
+ let fn_name = tcx.item_name(item_def_id.into());
+ tcx.sess.emit_err(AbiOf { span, fn_name, fn_abi: format!("{:#?}", abi) });
+ }
+ sym::assert_eq => {
+ let ty::Tuple(fields) = ty.kind() else {
+ span_bug!(
+ meta_item.span(),
+ "`#[rustc_abi(assert_eq)]` on a type alias requires pair type"
+ );
+ };
+ let [field1, field2] = ***fields else {
+ span_bug!(
+ meta_item.span(),
+ "`#[rustc_abi(assert_eq)]` on a type alias requires pair type"
+ );
+ };
+ let ty::FnPtr(sig1) = field1.kind() else {
+ span_bug!(
+ meta_item.span(),
+ "`#[rustc_abi(assert_eq)]` on a type alias requires pair of function pointer types"
+ );
+ };
+ let abi1 = unwrap_fn_abi(
+ tcx.fn_abi_of_fn_ptr(
+ param_env.and((*sig1, /* extra_args */ ty::List::empty())),
+ ),
+ tcx,
+ item_def_id,
+ );
+ let ty::FnPtr(sig2) = field2.kind() else {
+ span_bug!(
+ meta_item.span(),
+ "`#[rustc_abi(assert_eq)]` on a type alias requires pair of function pointer types"
+ );
+ };
+ let abi2 = unwrap_fn_abi(
+ tcx.fn_abi_of_fn_ptr(
+ param_env.and((*sig2, /* extra_args */ ty::List::empty())),
+ ),
+ tcx,
+ item_def_id,
+ );
+
+ if !test_abi_eq(abi1, abi2) {
+ tcx.sess.emit_err(AbiNe {
+ span,
+ left: format!("{:#?}", abi1),
+ right: format!("{:#?}", abi2),
+ });
+ }
+ }
+ name => {
+ tcx.sess.emit_err(UnrecognizedField { span: meta_item.span(), name });
+ }
+ }
+ }
+}
diff --git a/compiler/rustc_passes/src/check_attr.rs b/compiler/rustc_passes/src/check_attr.rs
index 197b335bd..d92923e78 100644
--- a/compiler/rustc_passes/src/check_attr.rs
+++ b/compiler/rustc_passes/src/check_attr.rs
@@ -16,6 +16,7 @@ use rustc_hir::{
self, FnSig, ForeignItem, HirId, Item, ItemKind, TraitItem, CRATE_HIR_ID, CRATE_OWNER_ID,
};
use rustc_hir::{MethodKind, Target, Unsafety};
+use rustc_macros::LintDiagnostic;
use rustc_middle::hir::nested_filter;
use rustc_middle::middle::resolve_bound_vars::ObjectLifetimeDefault;
use rustc_middle::query::Providers;
@@ -24,7 +25,7 @@ use rustc_middle::ty::error::{ExpectedFound, TypeError};
use rustc_middle::ty::{self, TyCtxt};
use rustc_session::lint::builtin::{
CONFLICTING_REPR_HINTS, INVALID_DOC_ATTRIBUTES, INVALID_MACRO_EXPORT_ARGUMENTS,
- UNUSED_ATTRIBUTES,
+ UNKNOWN_OR_MALFORMED_DIAGNOSTIC_ATTRIBUTES, UNUSED_ATTRIBUTES,
};
use rustc_session::parse::feature_err;
use rustc_span::symbol::{kw, sym, Symbol};
@@ -36,6 +37,10 @@ use rustc_trait_selection::traits::ObligationCtxt;
use std::cell::Cell;
use std::collections::hash_map::Entry;
+#[derive(LintDiagnostic)]
+#[diag(passes_diagnostic_diagnostic_on_unimplemented_only_for_traits)]
+pub struct DiagnosticOnUnimplementedOnlyForTraits;
+
pub(crate) fn target_from_impl_item<'tcx>(
tcx: TyCtxt<'tcx>,
impl_item: &hir::ImplItem<'_>,
@@ -104,13 +109,16 @@ impl CheckAttrVisitor<'_> {
let mut seen = FxHashMap::default();
let attrs = self.tcx.hir().attrs(hir_id);
for attr in attrs {
+ if attr.path_matches(&[sym::diagnostic, sym::on_unimplemented]) {
+ self.check_diagnostic_on_unimplemented(attr.span, hir_id, target);
+ }
match attr.name_or_empty() {
sym::do_not_recommend => self.check_do_not_recommend(attr.span, target),
sym::inline => self.check_inline(hir_id, attr, span, target),
- sym::no_coverage => self.check_no_coverage(hir_id, attr, span, target),
+ sym::coverage => self.check_coverage(hir_id, attr, span, target),
sym::non_exhaustive => self.check_non_exhaustive(hir_id, attr, span, target),
sym::marker => self.check_marker(hir_id, attr, span, target),
- sym::target_feature => self.check_target_feature(hir_id, attr, span, target),
+ sym::target_feature => self.check_target_feature(hir_id, attr, span, target, attrs),
sym::thread_local => self.check_thread_local(attr, span, target),
sym::track_caller => {
self.check_track_caller(hir_id, attr.span, attrs, span, target)
@@ -139,6 +147,9 @@ impl CheckAttrVisitor<'_> {
self.check_rustc_std_internal_symbol(&attr, span, target)
}
sym::naked => self.check_naked(hir_id, attr, span, target),
+ sym::rustc_never_returns_null_ptr => {
+ self.check_applied_to_fn_or_method(hir_id, attr, span, target)
+ }
sym::rustc_legacy_const_generics => {
self.check_rustc_legacy_const_generics(hir_id, &attr, span, target, item)
}
@@ -184,6 +195,9 @@ impl CheckAttrVisitor<'_> {
| sym::rustc_promotable => self.check_stability_promotable(&attr, span, target),
sym::link_ordinal => self.check_link_ordinal(&attr, span, target),
sym::rustc_confusables => self.check_confusables(&attr, target),
+ sym::rustc_safe_intrinsic => {
+ self.check_rustc_safe_intrinsic(hir_id, attr, span, target)
+ }
_ => true,
};
@@ -284,6 +298,18 @@ impl CheckAttrVisitor<'_> {
}
}
+ /// Checks if `#[diagnostic::on_unimplemented]` is applied to a trait definition
+ fn check_diagnostic_on_unimplemented(&self, attr_span: Span, hir_id: HirId, target: Target) {
+ if !matches!(target, Target::Trait) {
+ self.tcx.emit_spanned_lint(
+ UNKNOWN_OR_MALFORMED_DIAGNOSTIC_ATTRIBUTES,
+ hir_id,
+ attr_span,
+ DiagnosticOnUnimplementedOnlyForTraits,
+ );
+ }
+ }
+
/// Checks if an `#[inline]` is applied to a function or a closure. Returns `true` if valid.
fn check_inline(&self, hir_id: HirId, attr: &Attribute, span: Span, target: Target) -> bool {
match target {
@@ -327,16 +353,10 @@ impl CheckAttrVisitor<'_> {
}
}
- /// Checks if a `#[no_coverage]` is applied directly to a function
- fn check_no_coverage(
- &self,
- hir_id: HirId,
- attr: &Attribute,
- span: Span,
- target: Target,
- ) -> bool {
+ /// Checks if a `#[coverage]` is applied directly to a function
+ fn check_coverage(&self, hir_id: HirId, attr: &Attribute, span: Span, target: Target) -> bool {
match target {
- // no_coverage on function is fine
+ // #[coverage] on function is fine
Target::Fn
| Target::Closure
| Target::Method(MethodKind::Trait { body: true } | MethodKind::Inherent) => true,
@@ -347,7 +367,7 @@ impl CheckAttrVisitor<'_> {
UNUSED_ATTRIBUTES,
hir_id,
attr.span,
- errors::IgnoredNoCoverageFnProto,
+ errors::IgnoredCoverageFnProto,
);
true
}
@@ -357,7 +377,7 @@ impl CheckAttrVisitor<'_> {
UNUSED_ATTRIBUTES,
hir_id,
attr.span,
- errors::IgnoredNoCoveragePropagate,
+ errors::IgnoredCoveragePropagate,
);
true
}
@@ -367,13 +387,13 @@ impl CheckAttrVisitor<'_> {
UNUSED_ATTRIBUTES,
hir_id,
attr.span,
- errors::IgnoredNoCoverageFnDefn,
+ errors::IgnoredCoverageFnDefn,
);
true
}
_ => {
- self.tcx.sess.emit_err(errors::IgnoredNoCoverageNotCoverable {
+ self.tcx.sess.emit_err(errors::IgnoredCoverageNotCoverable {
attr_span: attr.span,
defn_span: span,
});
@@ -574,10 +594,36 @@ impl CheckAttrVisitor<'_> {
attr: &Attribute,
span: Span,
target: Target,
+ attrs: &[Attribute],
) -> bool {
match target {
- Target::Fn
- | Target::Method(MethodKind::Trait { body: true } | MethodKind::Inherent) => true,
+ Target::Fn => {
+ // `#[target_feature]` is not allowed in language items.
+ if let Some((lang_item, _)) = hir::lang_items::extract(attrs)
+ // Calling functions with `#[target_feature]` is
+ // not unsafe on WASM, see #84988
+ && !self.tcx.sess.target.is_like_wasm
+ && !self.tcx.sess.opts.actually_rustdoc
+ {
+ let hir::Node::Item(item) = self.tcx.hir().get(hir_id) else {
+ unreachable!();
+ };
+ let hir::ItemKind::Fn(sig, _, _) = item.kind else {
+ // target is `Fn`
+ unreachable!();
+ };
+
+ self.tcx.sess.emit_err(errors::LangItemWithTargetFeature {
+ attr_span: attr.span,
+ name: lang_item,
+ sig_span: sig.span,
+ });
+ false
+ } else {
+ true
+ }
+ }
+ Target::Method(MethodKind::Trait { body: true } | MethodKind::Inherent) => true,
// FIXME: #[target_feature] was previously erroneously allowed on statements and some
// crates used this, so only emit a warning.
Target::Statement => {
@@ -1721,6 +1767,7 @@ impl CheckAttrVisitor<'_> {
.collect();
let mut int_reprs = 0;
+ let mut is_explicit_rust = false;
let mut is_c = false;
let mut is_simd = false;
let mut is_transparent = false;
@@ -1732,6 +1779,9 @@ impl CheckAttrVisitor<'_> {
}
match hint.name_or_empty() {
+ sym::Rust => {
+ is_explicit_rust = true;
+ }
sym::C => {
is_c = true;
match target {
@@ -1841,12 +1891,16 @@ impl CheckAttrVisitor<'_> {
// Error on repr(transparent, <anything else>).
if is_transparent && hints.len() > 1 {
- let hint_spans: Vec<_> = hint_spans.clone().collect();
+ let hint_spans = hint_spans.clone().collect();
self.tcx.sess.emit_err(errors::TransparentIncompatible {
hint_spans,
target: target.to_string(),
});
}
+ if is_explicit_rust && (int_reprs > 0 || is_c || is_simd) {
+ let hint_spans = hint_spans.clone().collect();
+ self.tcx.sess.emit_err(errors::ReprConflicting { hint_spans });
+ }
// Warn on repr(u8, u16), repr(C, simd), and c-like-enum-repr(C, u8)
if (int_reprs > 1)
|| (is_simd && is_c)
@@ -1863,7 +1917,7 @@ impl CheckAttrVisitor<'_> {
CONFLICTING_REPR_HINTS,
hir_id,
hint_spans.collect::<Vec<Span>>(),
- errors::ReprConflicting,
+ errors::ReprConflictingLint,
);
}
}
@@ -1998,6 +2052,29 @@ impl CheckAttrVisitor<'_> {
}
}
+ fn check_rustc_safe_intrinsic(
+ &self,
+ hir_id: HirId,
+ attr: &Attribute,
+ span: Span,
+ target: Target,
+ ) -> bool {
+ let hir = self.tcx.hir();
+
+ if let Target::ForeignFn = target
+ && let Some(parent) = hir.opt_parent_id(hir_id)
+ && let hir::Node::Item(Item {
+ kind: ItemKind::ForeignMod { abi: Abi::RustIntrinsic | Abi::PlatformIntrinsic, .. },
+ ..
+ }) = hir.get(parent)
+ {
+ return true;
+ }
+
+ self.tcx.sess.emit_err(errors::RustcSafeIntrinsic { attr_span: attr.span, span });
+ false
+ }
+
fn check_rustc_std_internal_symbol(
&self,
attr: &Attribute,
@@ -2289,7 +2366,10 @@ impl CheckAttrVisitor<'_> {
&mut diag,
&cause,
None,
- Some(ValuePairs::Sigs(ExpectedFound { expected: expected_sig, found: sig })),
+ Some(ValuePairs::PolySigs(ExpectedFound {
+ expected: ty::Binder::dummy(expected_sig),
+ found: ty::Binder::dummy(sig),
+ })),
terr,
false,
false,
diff --git a/compiler/rustc_passes/src/check_const.rs b/compiler/rustc_passes/src/check_const.rs
index 8437e9a40..6d176af80 100644
--- a/compiler/rustc_passes/src/check_const.rs
+++ b/compiler/rustc_passes/src/check_const.rs
@@ -193,12 +193,12 @@ impl<'tcx> Visitor<'tcx> for CheckConstVisitor<'tcx> {
}
fn visit_anon_const(&mut self, anon: &'tcx hir::AnonConst) {
- let kind = Some(hir::ConstContext::Const);
+ let kind = Some(hir::ConstContext::Const { inline: false });
self.recurse_into(kind, None, |this| intravisit::walk_anon_const(this, anon));
}
fn visit_inline_const(&mut self, block: &'tcx hir::ConstBlock) {
- let kind = Some(hir::ConstContext::Const);
+ let kind = Some(hir::ConstContext::Const { inline: true });
self.recurse_into(kind, None, |this| intravisit::walk_inline_const(this, block));
}
diff --git a/compiler/rustc_passes/src/dead.rs b/compiler/rustc_passes/src/dead.rs
index d1c3bcf38..493daf314 100644
--- a/compiler/rustc_passes/src/dead.rs
+++ b/compiler/rustc_passes/src/dead.rs
@@ -96,7 +96,7 @@ impl<'tcx> MarkSymbolVisitor<'tcx> {
fn handle_res(&mut self, res: Res) {
match res {
- Res::Def(DefKind::Const | DefKind::AssocConst | DefKind::TyAlias { .. }, def_id) => {
+ Res::Def(DefKind::Const | DefKind::AssocConst | DefKind::TyAlias, def_id) => {
self.check_def_id(def_id);
}
_ if self.in_pat => {}
@@ -923,7 +923,7 @@ impl<'tcx> DeadVisitor<'tcx> {
| DefKind::Fn
| DefKind::Static(_)
| DefKind::Const
- | DefKind::TyAlias { .. }
+ | DefKind::TyAlias
| DefKind::Enum
| DefKind::Union
| DefKind::ForeignTy => self.warn_dead_code(def_id, "used"),
diff --git a/compiler/rustc_passes/src/errors.rs b/compiler/rustc_passes/src/errors.rs
index 683717344..f4a6bf017 100644
--- a/compiler/rustc_passes/src/errors.rs
+++ b/compiler/rustc_passes/src/errors.rs
@@ -64,20 +64,20 @@ pub struct InlineNotFnOrClosure {
}
#[derive(LintDiagnostic)]
-#[diag(passes_no_coverage_ignored_function_prototype)]
-pub struct IgnoredNoCoverageFnProto;
+#[diag(passes_coverage_ignored_function_prototype)]
+pub struct IgnoredCoverageFnProto;
#[derive(LintDiagnostic)]
-#[diag(passes_no_coverage_propagate)]
-pub struct IgnoredNoCoveragePropagate;
+#[diag(passes_coverage_propagate)]
+pub struct IgnoredCoveragePropagate;
#[derive(LintDiagnostic)]
-#[diag(passes_no_coverage_fn_defn)]
-pub struct IgnoredNoCoverageFnDefn;
+#[diag(passes_coverage_fn_defn)]
+pub struct IgnoredCoverageFnDefn;
#[derive(Diagnostic)]
-#[diag(passes_no_coverage_not_coverable, code = "E0788")]
-pub struct IgnoredNoCoverageNotCoverable {
+#[diag(passes_coverage_not_coverable, code = "E0788")]
+pub struct IgnoredCoverageNotCoverable {
#[primary_span]
pub attr_span: Span,
#[label]
@@ -558,9 +558,16 @@ pub struct ReprIdent {
pub span: Span,
}
+#[derive(Diagnostic)]
+#[diag(passes_repr_conflicting, code = "E0566")]
+pub struct ReprConflicting {
+ #[primary_span]
+ pub hint_spans: Vec<Span>,
+}
+
#[derive(LintDiagnostic)]
#[diag(passes_repr_conflicting, code = "E0566")]
-pub struct ReprConflicting;
+pub struct ReprConflictingLint;
#[derive(Diagnostic)]
#[diag(passes_used_static)]
@@ -621,6 +628,15 @@ pub struct RustcAllowConstFnUnstable {
}
#[derive(Diagnostic)]
+#[diag(passes_rustc_safe_intrinsic)]
+pub struct RustcSafeIntrinsic {
+ #[primary_span]
+ pub attr_span: Span,
+ #[label]
+ pub span: Span,
+}
+
+#[derive(Diagnostic)]
#[diag(passes_rustc_std_internal_symbol)]
pub struct RustcStdInternalSymbol {
#[primary_span]
@@ -809,6 +825,16 @@ pub struct MissingLangItem {
}
#[derive(Diagnostic)]
+#[diag(passes_lang_item_fn_with_target_feature)]
+pub struct LangItemWithTargetFeature {
+ #[primary_span]
+ pub attr_span: Span,
+ pub name: Symbol,
+ #[label]
+ pub sig_span: Span,
+}
+
+#[derive(Diagnostic)]
#[diag(passes_lang_item_on_incorrect_target, code = "E0718")]
pub struct LangItemOnIncorrectTarget {
#[primary_span]
@@ -873,32 +899,32 @@ pub struct DuplicateDiagnosticItemInCrate {
}
#[derive(Diagnostic)]
-#[diag(passes_abi)]
-pub struct Abi {
+#[diag(passes_layout_abi)]
+pub struct LayoutAbi {
#[primary_span]
pub span: Span,
pub abi: String,
}
#[derive(Diagnostic)]
-#[diag(passes_align)]
-pub struct Align {
+#[diag(passes_layout_align)]
+pub struct LayoutAlign {
#[primary_span]
pub span: Span,
pub align: String,
}
#[derive(Diagnostic)]
-#[diag(passes_size)]
-pub struct Size {
+#[diag(passes_layout_size)]
+pub struct LayoutSize {
#[primary_span]
pub span: Span,
pub size: String,
}
#[derive(Diagnostic)]
-#[diag(passes_homogeneous_aggregate)]
-pub struct HomogeneousAggregate {
+#[diag(passes_layout_homogeneous_aggregate)]
+pub struct LayoutHomogeneousAggregate {
#[primary_span]
pub span: Span,
pub homogeneous_aggregate: String,
@@ -914,6 +940,38 @@ pub struct LayoutOf {
}
#[derive(Diagnostic)]
+#[diag(passes_layout_invalid_attribute)]
+pub struct LayoutInvalidAttribute {
+ #[primary_span]
+ pub span: Span,
+}
+
+#[derive(Diagnostic)]
+#[diag(passes_abi_of)]
+pub struct AbiOf {
+ #[primary_span]
+ pub span: Span,
+ pub fn_name: Symbol,
+ pub fn_abi: String,
+}
+
+#[derive(Diagnostic)]
+#[diag(passes_abi_ne)]
+pub struct AbiNe {
+ #[primary_span]
+ pub span: Span,
+ pub left: String,
+ pub right: String,
+}
+
+#[derive(Diagnostic)]
+#[diag(passes_abi_invalid_attribute)]
+pub struct AbiInvalidAttribute {
+ #[primary_span]
+ pub span: Span,
+}
+
+#[derive(Diagnostic)]
#[diag(passes_unrecognized_field)]
pub struct UnrecognizedField {
#[primary_span]
diff --git a/compiler/rustc_passes/src/hir_stats.rs b/compiler/rustc_passes/src/hir_stats.rs
index 5aa8aef6a..24087a4ea 100644
--- a/compiler/rustc_passes/src/hir_stats.rs
+++ b/compiler/rustc_passes/src/hir_stats.rs
@@ -587,6 +587,8 @@ impl<'v> ast_visit::Visitor<'v> for StatCollector<'v> {
BareFn,
Never,
Tup,
+ AnonStruct,
+ AnonUnion,
Path,
TraitObject,
ImplTrait,
diff --git a/compiler/rustc_passes/src/lang_items.rs b/compiler/rustc_passes/src/lang_items.rs
index 476394f30..7e8372439 100644
--- a/compiler/rustc_passes/src/lang_items.rs
+++ b/compiler/rustc_passes/src/lang_items.rs
@@ -20,7 +20,8 @@ use rustc_hir::lang_items::{extract, GenericRequirement};
use rustc_hir::{LangItem, LanguageItems, Target};
use rustc_middle::ty::TyCtxt;
use rustc_session::cstore::ExternCrate;
-use rustc_span::{symbol::kw::Empty, Span};
+use rustc_span::symbol::kw::Empty;
+use rustc_span::{sym, Span};
use rustc_middle::query::Providers;
@@ -157,7 +158,14 @@ impl<'tcx> LanguageItemCollector<'tcx> {
self.tcx.hir().get_by_def_id(item_def_id)
{
let (actual_num, generics_span) = match kind.generics() {
- Some(generics) => (generics.params.len(), generics.span),
+ Some(generics) => (
+ generics
+ .params
+ .iter()
+ .filter(|p| !self.tcx.has_attr(p.def_id, sym::rustc_host))
+ .count(),
+ generics.span,
+ ),
None => (0, *item_span),
};
diff --git a/compiler/rustc_passes/src/layout_test.rs b/compiler/rustc_passes/src/layout_test.rs
index a7a8af864..e195f9ab6 100644
--- a/compiler/rustc_passes/src/layout_test.rs
+++ b/compiler/rustc_passes/src/layout_test.rs
@@ -2,33 +2,76 @@ use rustc_ast::Attribute;
use rustc_hir::def::DefKind;
use rustc_hir::def_id::LocalDefId;
use rustc_middle::ty::layout::{HasParamEnv, HasTyCtxt, LayoutError, LayoutOfHelpers, TyAndLayout};
-use rustc_middle::ty::{ParamEnv, Ty, TyCtxt};
+use rustc_middle::ty::{self, ParamEnv, Ty, TyCtxt};
use rustc_span::source_map::Spanned;
use rustc_span::symbol::sym;
use rustc_span::Span;
use rustc_target::abi::{HasDataLayout, TargetDataLayout};
+use rustc_trait_selection::traits::error_reporting::TypeErrCtxtExt;
+use rustc_trait_selection::{infer::TyCtxtInferExt, traits};
-use crate::errors::{Abi, Align, HomogeneousAggregate, LayoutOf, Size, UnrecognizedField};
+use crate::errors::{
+ LayoutAbi, LayoutAlign, LayoutHomogeneousAggregate, LayoutInvalidAttribute, LayoutOf,
+ LayoutSize, UnrecognizedField,
+};
pub fn test_layout(tcx: TyCtxt<'_>) {
- if tcx.features().rustc_attrs {
+ if !tcx.features().rustc_attrs {
// if the `rustc_attrs` feature is not enabled, don't bother testing layout
- for id in tcx.hir().items() {
- if matches!(
- tcx.def_kind(id.owner_id),
- DefKind::TyAlias { .. } | DefKind::Enum | DefKind::Struct | DefKind::Union
- ) {
- for attr in tcx.get_attrs(id.owner_id, sym::rustc_layout) {
- dump_layout_of(tcx, id.owner_id.def_id, attr);
+ return;
+ }
+ for id in tcx.hir_crate_items(()).definitions() {
+ for attr in tcx.get_attrs(id, sym::rustc_layout) {
+ match tcx.def_kind(id) {
+ DefKind::TyAlias | DefKind::Enum | DefKind::Struct | DefKind::Union => {
+ dump_layout_of(tcx, id, attr);
+ }
+ _ => {
+ tcx.sess.emit_err(LayoutInvalidAttribute { span: tcx.def_span(id) });
}
}
}
}
}
+pub fn ensure_wf<'tcx>(
+ tcx: TyCtxt<'tcx>,
+ param_env: ParamEnv<'tcx>,
+ ty: Ty<'tcx>,
+ def_id: LocalDefId,
+ span: Span,
+) -> bool {
+ let pred = ty::ClauseKind::WellFormed(ty.into());
+ let obligation = traits::Obligation::new(
+ tcx,
+ traits::ObligationCause::new(
+ span,
+ def_id,
+ traits::ObligationCauseCode::WellFormed(Some(traits::WellFormedLoc::Ty(def_id))),
+ ),
+ param_env,
+ pred,
+ );
+ let infcx = tcx.infer_ctxt().build();
+ let ocx = traits::ObligationCtxt::new(&infcx);
+ ocx.register_obligation(obligation);
+ let errors = ocx.select_all_or_error();
+ if !errors.is_empty() {
+ infcx.err_ctxt().report_fulfillment_errors(&errors);
+ false
+ } else {
+ // looks WF!
+ true
+ }
+}
+
fn dump_layout_of(tcx: TyCtxt<'_>, item_def_id: LocalDefId, attr: &Attribute) {
let param_env = tcx.param_env(item_def_id);
let ty = tcx.type_of(item_def_id).instantiate_identity();
+ let span = tcx.def_span(item_def_id.to_def_id());
+ if !ensure_wf(tcx, param_env, ty, item_def_id, span) {
+ return;
+ }
match tcx.layout_of(param_env.and(ty)) {
Ok(ty_layout) => {
// Check out the `#[rustc_layout(..)]` attribute to tell what to dump.
@@ -37,29 +80,24 @@ fn dump_layout_of(tcx: TyCtxt<'_>, item_def_id: LocalDefId, attr: &Attribute) {
for meta_item in meta_items {
match meta_item.name_or_empty() {
sym::abi => {
- tcx.sess.emit_err(Abi {
- span: tcx.def_span(item_def_id.to_def_id()),
- abi: format!("{:?}", ty_layout.abi),
- });
+ tcx.sess.emit_err(LayoutAbi { span, abi: format!("{:?}", ty_layout.abi) });
}
sym::align => {
- tcx.sess.emit_err(Align {
- span: tcx.def_span(item_def_id.to_def_id()),
+ tcx.sess.emit_err(LayoutAlign {
+ span,
align: format!("{:?}", ty_layout.align),
});
}
sym::size => {
- tcx.sess.emit_err(Size {
- span: tcx.def_span(item_def_id.to_def_id()),
- size: format!("{:?}", ty_layout.size),
- });
+ tcx.sess
+ .emit_err(LayoutSize { span, size: format!("{:?}", ty_layout.size) });
}
sym::homogeneous_aggregate => {
- tcx.sess.emit_err(HomogeneousAggregate {
- span: tcx.def_span(item_def_id.to_def_id()),
+ tcx.sess.emit_err(LayoutHomogeneousAggregate {
+ span,
homogeneous_aggregate: format!(
"{:?}",
ty_layout.homogeneous_aggregate(&UnwrapLayoutCx { tcx, param_env })
@@ -69,18 +107,15 @@ fn dump_layout_of(tcx: TyCtxt<'_>, item_def_id: LocalDefId, attr: &Attribute) {
sym::debug => {
let normalized_ty = format!(
- "{:?}",
+ "{}",
tcx.normalize_erasing_regions(
param_env.with_reveal_all_normalized(tcx),
ty,
)
);
+ // FIXME: using the `Debug` impl here isn't ideal.
let ty_layout = format!("{:#?}", *ty_layout);
- tcx.sess.emit_err(LayoutOf {
- span: tcx.def_span(item_def_id.to_def_id()),
- normalized_ty,
- ty_layout,
- });
+ tcx.sess.emit_err(LayoutOf { span, normalized_ty, ty_layout });
}
name => {
@@ -91,11 +126,7 @@ fn dump_layout_of(tcx: TyCtxt<'_>, item_def_id: LocalDefId, attr: &Attribute) {
}
Err(layout_error) => {
- tcx.sess.emit_fatal(Spanned {
- node: layout_error.into_diagnostic(),
-
- span: tcx.def_span(item_def_id.to_def_id()),
- });
+ tcx.sess.emit_fatal(Spanned { node: layout_error.into_diagnostic(), span });
}
}
}
diff --git a/compiler/rustc_passes/src/lib.rs b/compiler/rustc_passes/src/lib.rs
index 0da4b2946..51f3c9ad7 100644
--- a/compiler/rustc_passes/src/lib.rs
+++ b/compiler/rustc_passes/src/lib.rs
@@ -24,6 +24,7 @@ use rustc_errors::{DiagnosticMessage, SubdiagnosticMessage};
use rustc_fluent_macro::fluent_messages;
use rustc_middle::query::Providers;
+pub mod abi_test;
mod check_attr;
mod check_const;
pub mod dead;
diff --git a/compiler/rustc_passes/src/reachable.rs b/compiler/rustc_passes/src/reachable.rs
index e62833b35..1239d6d91 100644
--- a/compiler/rustc_passes/src/reachable.rs
+++ b/compiler/rustc_passes/src/reachable.rs
@@ -90,6 +90,10 @@ impl<'tcx> Visitor<'tcx> for ReachableContext<'tcx> {
.typeck_results()
.type_dependent_def(expr.hir_id)
.map(|(kind, def_id)| Res::Def(kind, def_id)),
+ hir::ExprKind::Closure(&hir::Closure { def_id, .. }) => {
+ self.reachable_symbols.insert(def_id);
+ None
+ }
_ => None,
};