Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 14 additions & 2 deletions compiler/rustc_attr_ir/src/data_structures.rs
Original file line number Diff line number Diff line change
Expand Up @@ -172,7 +172,19 @@ impl OptimizeAttr {
}
}

#[derive(PartialEq, Debug, Encodable, Decodable, Copy, Clone, StableHash, PrintAttribute)]
#[derive(
PartialEq,
Eq,
Debug,
PartialOrd,
Ord,
Encodable,
Decodable,
Copy,
Clone,
StableHash,
PrintAttribute
)]
pub enum ReprAttr {
ReprInt(IntType),
ReprRust,
Expand All @@ -188,7 +200,7 @@ pub enum TransparencyError {
MultipleTransparencyAttrs(Span, Span),
}

#[derive(Eq, PartialEq, Debug, Copy, Clone)]
#[derive(Eq, PartialEq, Debug, Copy, Clone, PartialOrd, Ord)]
#[derive(Encodable, Decodable, StableHash, PrintAttribute)]
pub enum IntType {
SignedInt(ast::IntTy),
Expand Down
10 changes: 4 additions & 6 deletions compiler/rustc_data_structures/src/stable_hash.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ use rustc_index::{Idx, IndexSlice, IndexVec};
use smallvec::SmallVec;
use thin_vec::ThinVec;

use crate::fingerprint::Fingerprint;

#[cfg(test)]
mod tests;

Expand All @@ -24,8 +26,8 @@ pub trait StableHashCtxt {
/// The main event: stable hashing of a span.
fn stable_hash_span(&mut self, span: RawSpan, hasher: &mut StableHasher);

/// Compute a `DefPathHash`.
fn def_path_hash(&self, def_id: RawDefId) -> RawDefPathHash;
/// Compute a `Fingerprint`, which can be trivially turned into a `DefPathHash`.
fn def_path_hash(&self, def_id: RawDefId) -> Fingerprint;

/// Get the stable hash controls.
fn stable_hash_controls(&self) -> StableHashControls;
Expand All @@ -43,10 +45,6 @@ pub struct RawSpan(pub u32, pub u16, pub u16);
// `DefId`.
pub struct RawDefId(pub u32, pub u32);

// A type used to work around `DefPathHash` not being visible in this crate. It is the same size as
// `DefPathHash`.
pub struct RawDefPathHash(pub [u8; 16]);

/// Something that implements `StableHash` can be hashed in a way that is
/// stable across multiple compilation sessions.
///
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_data_structures/src/stable_hash/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ impl StableHashCtxt for () {
fn stable_hash_span(&mut self, _: RawSpan, _: &mut StableHasher) {
panic!();
}
fn def_path_hash(&self, _: RawDefId) -> RawDefPathHash {
fn def_path_hash(&self, _: RawDefId) -> Fingerprint {
panic!();
}
fn stable_hash_controls(&self) -> StableHashControls {
Expand Down
46 changes: 32 additions & 14 deletions compiler/rustc_interface/src/interface.rs
Original file line number Diff line number Diff line change
Expand Up @@ -44,8 +44,9 @@ pub struct Compiler {
}

/// Converts strings provided as `--cfg [cfgspec]` into a `Cfg`.
pub(crate) fn parse_cfg(dcx: DiagCtxtHandle<'_>, cfgs: Vec<String>) -> Cfg {
cfgs.into_iter()
pub(crate) fn parse_cfg(sess: &Session, cfgs: Vec<String>) -> Cfg {
let cfg = cfgs
.into_iter()
.map(|s| {
let psess = ParseSess::emitter_with_note(format!(
"this occurred on the command line: `--cfg={s}`"
Expand All @@ -54,7 +55,7 @@ pub(crate) fn parse_cfg(dcx: DiagCtxtHandle<'_>, cfgs: Vec<String>) -> Cfg {

macro_rules! error {
($reason: expr) => {
dcx.fatal(format!("invalid `--cfg` argument: `{s}` ({})", $reason));
sess.dcx().fatal(format!("invalid `--cfg` argument: `{s}` ({})", $reason));
};
}

Expand Down Expand Up @@ -106,11 +107,13 @@ pub(crate) fn parse_cfg(dcx: DiagCtxtHandle<'_>, cfgs: Vec<String>) -> Cfg {
error!(r#"expected `key` or `key="value"`"#);
}
})
.collect::<Cfg>()
.collect::<Cfg>();

config::build_configuration(sess, cfg)
}

/// Converts strings provided as `--check-cfg [specs]` into a `CheckCfg`.
pub(crate) fn parse_check_cfg(dcx: DiagCtxtHandle<'_>, specs: Vec<String>) -> CheckCfg {
pub(crate) fn parse_check_cfg(sess: &Session, specs: Vec<String>) -> CheckCfg {
// If any --check-cfg is passed then exhaustive_values and exhaustive_names
// are enabled by default.
let exhaustive_names = !specs.is_empty();
Expand All @@ -128,13 +131,15 @@ pub(crate) fn parse_check_cfg(dcx: DiagCtxtHandle<'_>, specs: Vec<String>) -> Ch

macro_rules! error {
($reason:expr) => {{
let mut diag = dcx.struct_fatal(format!("invalid `--check-cfg` argument: `{s}`"));
let mut diag =
sess.dcx().struct_fatal(format!("invalid `--check-cfg` argument: `{s}`"));
diag.note($reason);
diag.note(VISIT);
diag.emit()
}};
(in $arg:expr, $reason:expr) => {{
let mut diag = dcx.struct_fatal(format!("invalid `--check-cfg` argument: `{s}`"));
let mut diag =
sess.dcx().struct_fatal(format!("invalid `--check-cfg` argument: `{s}`"));

let pparg = rustc_ast_pretty::pprust::meta_list_item_to_string($arg);
if let Some(lit) = $arg.lit() {
Expand Down Expand Up @@ -304,6 +309,8 @@ pub(crate) fn parse_check_cfg(dcx: DiagCtxtHandle<'_>, specs: Vec<String>) -> Ch
}
}

check_cfg.fill_well_known(&sess.target);

check_cfg
}

Expand Down Expand Up @@ -443,14 +450,25 @@ pub fn run_compiler<R: Send>(config: Config, f: impl FnOnce(&Compiler) -> R + Se
sess.fallback_intrinsics = FxHashSet::from_iter(codegen_backend.fallback_intrinsics());
sess.thin_lto_supported = codegen_backend.thin_lto_supported();

let cfg = parse_cfg(sess.dcx(), config.crate_cfg);
let mut cfg = config::build_configuration(&sess, cfg);
util::add_configuration(&mut cfg, &mut sess, &*codegen_backend);
sess.config = cfg;
let target_config = codegen_backend.target_config(&sess);

// Store all of the target features in the session.
// Needs to be done before `parse_cfg` because it checks this list.
sess.internal_target_features
.extend(target_config.internal_target_features.to_sorted_stable_ord());

sess.config = parse_cfg(&sess, config.crate_cfg);
let is_nightly_build = sess.is_nightly_build();
let is_crt_static = sess.crt_static(None);
util::add_configuration(
&mut sess.config,
&target_config,
&sess.target,
is_nightly_build,
is_crt_static,
);

let mut check_cfg = parse_check_cfg(sess.dcx(), config.crate_check_cfg);
check_cfg.fill_well_known(&sess.target);
sess.check_config = check_cfg;
sess.check_config = parse_check_cfg(&sess, config.crate_check_cfg);

if let Some(psess_created) = config.psess_created {
psess_created(&mut sess.psess);
Expand Down
5 changes: 2 additions & 3 deletions compiler/rustc_interface/src/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ use rustc_session::config::{
LinkerPluginLto, LocationDetail, LtoCli, MirIncludeSpans, NextSolverConfig, Offload, Options,
OutFileName, OutputType, OutputTypes, PAuthKey, PacRet, Passes, PatchableFunctionEntry,
Polonius, ProcMacroExecutionStrategy, Strip, SwitchWithOptPath, SymbolManglingVersion,
WasiExecModel, build_configuration, build_session_options, rustc_optgroups,
WasiExecModel, build_session_options, rustc_optgroups,
};
use rustc_session::search_paths::SearchPath;
use rustc_session::utils::{CanonicalizedPath, NativeLib};
Expand Down Expand Up @@ -75,8 +75,7 @@ where
None,
&USING_INTERNAL_FEATURES,
);
let cfg = parse_cfg(sess.dcx(), matches.opt_strs("cfg"));
let cfg = build_configuration(&sess, cfg);
let cfg = parse_cfg(&sess, matches.opt_strs("cfg"));
f(sess, cfg)
});
}
Expand Down
33 changes: 14 additions & 19 deletions compiler/rustc_interface/src/util.rs
Original file line number Diff line number Diff line change
Expand Up @@ -42,52 +42,47 @@ type MakeBackendFn = fn() -> Box<dyn CodegenBackend>;
/// specific features (SSE, NEON etc.).
///
/// This is performed by checking whether a set of permitted features
/// is available on the target machine, by querying the codegen backend.
/// is available on the target machine, by querying the `TargetConfig` from the codegen backend.
pub(crate) fn add_configuration(
cfg: &mut Cfg,
sess: &mut Session,
codegen_backend: &dyn CodegenBackend,
target_config: &TargetConfig,
target: &Target,
is_nightly_build: bool,
is_crt_static: bool,
) {
let tf = sym::target_feature;
let tf_cfg = codegen_backend.target_config(sess);

// Add some of the target features to `cfg`.
cfg.extend(
sess.target
target
.rust_target_features()
.iter()
.filter_map(|(feature, gate, _)| {
if gate.in_cfg()
&& (sess.is_nightly_build()
|| gate.requires_nightly(/* in_cfg */ true).is_none())
&& (is_nightly_build || gate.requires_nightly(/* in_cfg */ true).is_none())
{
Some(Symbol::intern(feature))
} else {
None
}
})
.filter(|feature| tf_cfg.internal_target_features.contains(&feature))
.filter(|feature| target_config.internal_target_features.contains(&feature))
.map(|feature| (sym::target_feature, Some(feature))),
);

// Store all of them in the session.
sess.internal_target_features.extend(tf_cfg.internal_target_features.into_sorted_stable_ord());

if tf_cfg.has_reliable_f16 {
if target_config.has_reliable_f16 {
cfg.insert((sym::target_has_reliable_f16, None));
}
if tf_cfg.has_reliable_f16_math {
if target_config.has_reliable_f16_math {
cfg.insert((sym::target_has_reliable_f16_math, None));
}
if tf_cfg.has_reliable_f128 {
if target_config.has_reliable_f128 {
cfg.insert((sym::target_has_reliable_f128, None));
}
if tf_cfg.has_reliable_f128_math {
if target_config.has_reliable_f128_math {
cfg.insert((sym::target_has_reliable_f128_math, None));
}

if sess.crt_static(None) {
cfg.insert((tf, Some(sym::crt_dash_static)));
if is_crt_static {
cfg.insert((sym::target_feature, Some(sym::crt_dash_static)));
}
}

Expand Down
3 changes: 2 additions & 1 deletion compiler/rustc_lint/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -367,7 +367,8 @@ fn register_builtins(store: &mut LintStore) {
UNUSED_PARENS,
UNUSED_BRACES,
REDUNDANT_SEMICOLONS,
MAP_UNIT_FN
MAP_UNIT_FN,
REPEATED_REPRS
);

add_lint_group!("let_underscore", LET_UNDERSCORE_DROP, LET_UNDERSCORE_LOCK);
Expand Down
25 changes: 25 additions & 0 deletions compiler/rustc_lint_defs/src/builtin.rs
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,7 @@ pub mod hardwired {
REFINING_IMPL_TRAIT_INTERNAL,
REFINING_IMPL_TRAIT_REACHABLE,
RENAMED_AND_REMOVED_LINTS,
REPEATED_REPRS,
REPR_C_ENUMS_LARGER_THAN_INT,
RESOLVING_TO_ITEMS_SHADOWING_SUPERTRAIT_ITEMS,
RTSAN_NONBLOCKING_ASYNC,
Expand Down Expand Up @@ -276,6 +277,30 @@ declare_lint! {
};
}

declare_lint! {
/// The `repeated_reprs` lint detects when the same representation is
/// specified more than once in a `#[repr(..)]` attribute.
///
/// ### Example
///
/// ```rust
/// #[repr(C)]
/// #[repr(C)]
/// enum Foo { A }
/// ```
///
/// {{produces}}
///
/// ### Explanation
///
/// While some representations may be specified more than once, the compiler
/// will reject repeated uses of some others. For consistency, prefer to
/// only specify the representation once.
pub REPEATED_REPRS,
Warn,
"detects repeated representations in `#[repr(..)]` attributes",
}

declare_lint! {
/// The `meta_variable_misuse` lint detects possible meta-variable misuse
/// in macro definitions.
Expand Down
7 changes: 4 additions & 3 deletions compiler/rustc_middle/src/ich.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
use std::hash::Hash;

use rustc_crate_store::Untracked;
use rustc_data_structures::fingerprint::Fingerprint;
use rustc_data_structures::stable_hash::{
RawDefId, RawDefPathHash, RawSpan, StableHash, StableHashControls, StableHashCtxt, StableHasher,
RawDefId, RawSpan, StableHash, StableHashControls, StableHashCtxt, StableHasher,
};
use rustc_hir::def_id::{DefId, LocalDefId};
use rustc_session::Session;
Expand Down Expand Up @@ -159,14 +160,14 @@ impl<'a> StableHashCtxt for StableHashState<'a> {
}

#[inline]
fn def_path_hash(&self, raw_def_id: RawDefId) -> RawDefPathHash {
fn def_path_hash(&self, raw_def_id: RawDefId) -> Fingerprint {
let def_id = DefId::from_raw_def_id(raw_def_id);
if let Some(def_id) = def_id.as_local() {
self.untracked.definitions.read().def_path_hash(def_id)
} else {
self.untracked.cstore.read().def_path_hash(def_id)
}
.to_raw_def_path_hash()
.0
}

/// Assert that the provided `StableHashCtxt` is configured with the default
Expand Down
38 changes: 34 additions & 4 deletions compiler/rustc_passes/src/check_attr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,8 @@ use rustc_hir::{
};
use rustc_lint_defs::builtin::{
CONFLICTING_REPR_HINTS, INVALID_DOC_ATTRIBUTES, MALFORMED_DIAGNOSTIC_ATTRIBUTES,
MALFORMED_DIAGNOSTIC_FORMAT_LITERALS, MISPLACED_DIAGNOSTIC_ATTRIBUTES, UNUSED_ATTRIBUTES,
MALFORMED_DIAGNOSTIC_FORMAT_LITERALS, MISPLACED_DIAGNOSTIC_ATTRIBUTES, REPEATED_REPRS,
UNUSED_ATTRIBUTES,
};
use rustc_macros::Diagnostic;
use rustc_middle::hir::nested_filter;
Expand Down Expand Up @@ -1220,20 +1221,49 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
ReprAttr::ReprC => {
is_c = true;
}
ReprAttr::ReprAlign(..) => {}
ReprAttr::ReprPacked(_) => {}
ReprAttr::ReprAlign(..) => (),
ReprAttr::ReprPacked(..) => (),
ReprAttr::ReprSimd => {
is_simd = true;
}
ReprAttr::ReprTransparent => {
is_transparent = true;
}
ReprAttr::ReprInt(_) => {
ReprAttr::ReprInt(..) => {
int_reprs += 1;
}
};
}

if !reprs.is_empty() {
let sorted_reprs = {
let mut to_sort = reprs.to_owned();
to_sort.sort_unstable();
to_sort
};

// To collect all duplicates, get subslices where all of the elements of the subslice
// are equal, then filter out all those whose length is not 1. We could return warnings
// for each of them, but that's annoyingly excessive. So we instead collect all spans in
// one big Vec.
let spans: Vec<Span> = sorted_reprs
.chunk_by(|(a, _), (b, _)| a == b)
.map(ToOwned::to_owned)
.filter(|slice| slice.len() != 1)
.flatten()
.map(|(_, span)| span)
.collect();

if !spans.is_empty() {
self.tcx.emit_node_span_lint(
REPEATED_REPRS,
hir_id,
spans,
diagnostics::RepeatedRepr,
);
}
}

// Just point at all repr hints if there are any incompatibilities.
// This is not ideal, but tracking precisely which ones are at fault is a huge hassle.
let hint_spans = reprs.iter().map(|(_, span)| *span);
Expand Down
Loading
Loading