Skip to content
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.

Commit db91299

Browse files
committedNov 18, 2024
Target modifiers (special marked options) are recorded in metainfo and compared to be equal in different crates
1 parent bca5fde commit db91299

File tree

14 files changed

+285
-6
lines changed

14 files changed

+285
-6
lines changed
 

‎compiler/rustc_interface/src/passes.rs

+1
Original file line numberDiff line numberDiff line change
@@ -281,6 +281,7 @@ fn configure_and_expand(
281281

282282
resolver.resolve_crate(&krate);
283283

284+
CStore::from_tcx(tcx).report_incompatible_target_modifiers(tcx, &krate, resolver.lint_buffer());
284285
krate
285286
}
286287

‎compiler/rustc_lint/messages.ftl

+2
Original file line numberDiff line numberDiff line change
@@ -415,6 +415,8 @@ lint_improper_ctypes_union_layout_help = consider adding a `#[repr(C)]` or `#[re
415415
lint_improper_ctypes_union_layout_reason = this union has unspecified layout
416416
lint_improper_ctypes_union_non_exhaustive = this union is non-exhaustive
417417
418+
lint_incompatible_target_modifiers = crate `{$local_crate}` has incompatible target modifier with extern crate `{$extern_crate}`: `{$tmod}`
419+
418420
lint_incomplete_include =
419421
include macro expected single expression in source
420422

‎compiler/rustc_lint/src/context/diagnostics.rs

+4
Original file line numberDiff line numberDiff line change
@@ -422,6 +422,10 @@ pub(super) fn decorate_lint(sess: &Session, diagnostic: BuiltinLintDiag, diag: &
422422
lints::UnusedCrateDependency { extern_crate, local_crate }.decorate_lint(diag)
423423
}
424424
BuiltinLintDiag::WasmCAbi => lints::WasmCAbi.decorate_lint(diag),
425+
BuiltinLintDiag::IncompatibleTargetModifiers { extern_crate, local_crate, tmod } => {
426+
lints::IncompatibleTargetModifiers { extern_crate, local_crate, tmod }
427+
.decorate_lint(diag)
428+
}
425429
BuiltinLintDiag::IllFormedAttributeInput { suggestions } => {
426430
lints::IllFormedAttributeInput {
427431
num_suggestions: suggestions.len(),

‎compiler/rustc_lint/src/lints.rs

+8
Original file line numberDiff line numberDiff line change
@@ -2470,6 +2470,14 @@ pub(crate) struct UnusedCrateDependency {
24702470
pub local_crate: Symbol,
24712471
}
24722472

2473+
#[derive(LintDiagnostic)]
2474+
#[diag(lint_incompatible_target_modifiers)]
2475+
pub(crate) struct IncompatibleTargetModifiers {
2476+
pub extern_crate: Symbol,
2477+
pub local_crate: Symbol,
2478+
pub tmod: String,
2479+
}
2480+
24732481
#[derive(LintDiagnostic)]
24742482
#[diag(lint_wasm_c_abi)]
24752483
pub(crate) struct WasmCAbi;

‎compiler/rustc_lint_defs/src/builtin.rs

+37
Original file line numberDiff line numberDiff line change
@@ -578,6 +578,43 @@ declare_lint! {
578578
crate_level_only
579579
}
580580

581+
declare_lint! {
582+
/// The `incompatible_target_modifiers` lint detects crates with incompatible target modifiers
583+
/// (abi-changing or vulnerability-affecting flags).
584+
///
585+
/// ### Example
586+
///
587+
/// ```rust,ignore (needs extern crate)
588+
/// #![deny(incompatible_target_modifiers)]
589+
/// ```
590+
///
591+
/// When main and dependency crates are compiled with `-Zregparm=1` and `-Zregparm=2` correspondingly.
592+
///
593+
/// This will produce:
594+
///
595+
/// ```text
596+
/// error: crate `incompatible_regparm` has incompatible target modifier with extern crate `wrong_regparm`: `regparm = ( Some(1) | Some(2) )`
597+
/// --> $DIR/incompatible_regparm.rs:5:1
598+
/// |
599+
/// 1 | #![no_core]
600+
/// | ^
601+
/// |
602+
/// = note: `#[deny(incompatible_target_modifiers)]` on by default
603+
/// ```
604+
///
605+
/// ### Explanation
606+
///
607+
/// `Target modifiers` are compilation flags that affects abi or vulnerability resistance.
608+
/// Linking together crates with incompatible target modifiers would produce incorrect code
609+
/// or degradation of vulnerability resistance.
610+
/// So this lint should find such inconsistency.
611+
///
612+
pub INCOMPATIBLE_TARGET_MODIFIERS,
613+
Deny,
614+
"Incompatible target modifiers",
615+
crate_level_only
616+
}
617+
581618
declare_lint! {
582619
/// The `unused_qualifications` lint detects unnecessarily qualified
583620
/// names.

‎compiler/rustc_lint_defs/src/lib.rs

+5
Original file line numberDiff line numberDiff line change
@@ -719,6 +719,11 @@ pub enum BuiltinLintDiag {
719719
AvoidUsingIntelSyntax,
720720
AvoidUsingAttSyntax,
721721
IncompleteInclude,
722+
IncompatibleTargetModifiers {
723+
extern_crate: Symbol,
724+
local_crate: Symbol,
725+
tmod: String,
726+
},
722727
UnnameableTestItems,
723728
DuplicateMacroAttribute,
724729
CfgAttrNoAttributes,

‎compiler/rustc_metadata/src/creader.rs

+98-2
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ use rustc_middle::bug;
2424
use rustc_middle::ty::{TyCtxt, TyCtxtFeed};
2525
use rustc_session::config::{self, CrateType, ExternLocation};
2626
use rustc_session::cstore::{CrateDepKind, CrateSource, ExternCrate, ExternCrateSource};
27-
use rustc_session::lint::{self, BuiltinLintDiag};
27+
use rustc_session::lint::{self, BuiltinLintDiag, LintBuffer};
2828
use rustc_session::output::validate_crate_name;
2929
use rustc_session::search_paths::PathKind;
3030
use rustc_span::edition::Edition;
@@ -35,7 +35,9 @@ use tracing::{debug, info, trace};
3535

3636
use crate::errors;
3737
use crate::locator::{CrateError, CrateLocator, CratePaths};
38-
use crate::rmeta::{CrateDep, CrateMetadata, CrateNumMap, CrateRoot, MetadataBlob};
38+
use crate::rmeta::{
39+
CrateDep, CrateMetadata, CrateNumMap, CrateRoot, MetadataBlob, TargetModifiers,
40+
};
3941

4042
/// The backend's way to give the crate store access to the metadata in a library.
4143
/// Note that it returns the raw metadata bytes stored in the library file, whether
@@ -290,6 +292,79 @@ impl CStore {
290292
}
291293
}
292294

295+
pub fn report_incompatible_target_modifiers(
296+
&self,
297+
tcx: TyCtxt<'_>,
298+
krate: &Crate,
299+
lints: &mut LintBuffer,
300+
) {
301+
if tcx.crate_types().contains(&CrateType::ProcMacro) {
302+
return;
303+
}
304+
let sess = tcx.sess;
305+
let span = krate.spans.inner_span.shrink_to_lo();
306+
307+
let splitter = |v: &String| {
308+
let splitted: Vec<_> = v.split("=").collect();
309+
(splitted[0].to_string(), splitted[1].to_string())
310+
};
311+
let name = tcx.crate_name(LOCAL_CRATE);
312+
let mods = sess.opts.gather_target_modifiers();
313+
for (_cnum, data) in self.iter_crate_data() {
314+
if data.is_proc_macro_crate() {
315+
continue;
316+
}
317+
let mut report_diff = |tmod: String| {
318+
lints.buffer_lint(
319+
lint::builtin::INCOMPATIBLE_TARGET_MODIFIERS,
320+
ast::CRATE_NODE_ID,
321+
span,
322+
BuiltinLintDiag::IncompatibleTargetModifiers {
323+
extern_crate: data.name(),
324+
local_crate: name,
325+
tmod,
326+
},
327+
);
328+
};
329+
let mut it1 = mods.iter().map(splitter);
330+
let mut it2 = data.target_modifiers().map(splitter);
331+
let mut left_name_val: Option<(String, String)> = None;
332+
let mut right_name_val: Option<(String, String)> = None;
333+
loop {
334+
left_name_val = left_name_val.or_else(|| it1.next());
335+
right_name_val = right_name_val.or_else(|| it2.next());
336+
match (&left_name_val, &right_name_val) {
337+
(Some(l), Some(r)) => match l.0.cmp(&r.0) {
338+
cmp::Ordering::Equal => {
339+
if l.1 != r.1 {
340+
report_diff(format!("{} = ( {} | {} )", l.0, l.1, r.1));
341+
}
342+
left_name_val = None;
343+
right_name_val = None;
344+
}
345+
cmp::Ordering::Greater => {
346+
report_diff(format!("{} = ( * | {} )", r.0, r.1));
347+
right_name_val = None;
348+
}
349+
cmp::Ordering::Less => {
350+
report_diff(format!("{} = ( {} | * )", l.0, l.1));
351+
left_name_val = None;
352+
}
353+
},
354+
(Some(l), None) => {
355+
report_diff(format!("{} = ( {} | * )", l.0, l.1));
356+
left_name_val = None;
357+
}
358+
(None, Some(r)) => {
359+
report_diff(format!("{} = ( * | {} )", r.0, r.1));
360+
right_name_val = None;
361+
}
362+
(None, None) => break,
363+
}
364+
}
365+
}
366+
}
367+
293368
pub fn new(metadata_loader: Box<MetadataLoaderDyn>) -> CStore {
294369
CStore {
295370
metadata_loader,
@@ -432,6 +507,7 @@ impl<'a, 'tcx> CrateLoader<'a, 'tcx> {
432507
};
433508

434509
let cnum_map = self.resolve_crate_deps(root, &crate_root, &metadata, cnum, dep_kind)?;
510+
let target_modifiers = self.resolve_target_modifiers(&crate_root, &metadata, cnum)?;
435511

436512
let raw_proc_macros = if crate_root.is_proc_macro_crate() {
437513
let temp_root;
@@ -456,6 +532,7 @@ impl<'a, 'tcx> CrateLoader<'a, 'tcx> {
456532
raw_proc_macros,
457533
cnum,
458534
cnum_map,
535+
target_modifiers,
459536
dep_kind,
460537
source,
461538
private_dep,
@@ -689,6 +766,25 @@ impl<'a, 'tcx> CrateLoader<'a, 'tcx> {
689766
Ok(crate_num_map)
690767
}
691768

769+
fn resolve_target_modifiers(
770+
&mut self,
771+
crate_root: &CrateRoot,
772+
metadata: &MetadataBlob,
773+
krate: CrateNum,
774+
) -> Result<TargetModifiers, CrateError> {
775+
debug!("resolving target modifiers of external crate");
776+
if crate_root.is_proc_macro_crate() {
777+
return Ok(TargetModifiers::new());
778+
}
779+
let mods = crate_root.decode_target_modifiers(metadata);
780+
let mut target_modifiers = TargetModifiers::with_capacity(mods.len());
781+
for modifier in mods {
782+
target_modifiers.push(modifier);
783+
}
784+
debug!("resolve_target_modifiers: target mods for {:?} is {:?}", krate, target_modifiers);
785+
Ok(target_modifiers)
786+
}
787+
692788
fn dlsym_proc_macros(
693789
&self,
694790
path: &Path,

‎compiler/rustc_metadata/src/rmeta/decoder.rs

+18
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,9 @@ impl MetadataBlob {
7373
/// own crate numbers.
7474
pub(crate) type CrateNumMap = IndexVec<CrateNum, CrateNum>;
7575

76+
/// Target modifiers - abi / vulnerability-resist affecting flags
77+
pub(crate) type TargetModifiers = Vec<String>;
78+
7679
pub(crate) struct CrateMetadata {
7780
/// The primary crate data - binary metadata blob.
7881
blob: MetadataBlob,
@@ -110,6 +113,8 @@ pub(crate) struct CrateMetadata {
110113
cnum_map: CrateNumMap,
111114
/// Same ID set as `cnum_map` plus maybe some injected crates like panic runtime.
112115
dependencies: Vec<CrateNum>,
116+
/// Target modifiers - abi and vulnerability-resist affecting flags the crate was compiled with
117+
target_modifiers: TargetModifiers,
113118
/// How to link (or not link) this crate to the currently compiled crate.
114119
dep_kind: CrateDepKind,
115120
/// Filesystem location of this crate.
@@ -960,6 +965,13 @@ impl CrateRoot {
960965
) -> impl ExactSizeIterator<Item = CrateDep> + Captures<'a> {
961966
self.crate_deps.decode(metadata)
962967
}
968+
969+
pub(crate) fn decode_target_modifiers<'a>(
970+
&self,
971+
metadata: &'a MetadataBlob,
972+
) -> impl ExactSizeIterator<Item = String> + Captures<'a> {
973+
self.target_modifiers.decode(metadata)
974+
}
963975
}
964976

965977
impl<'a> CrateMetadataRef<'a> {
@@ -1815,6 +1827,7 @@ impl CrateMetadata {
18151827
raw_proc_macros: Option<&'static [ProcMacro]>,
18161828
cnum: CrateNum,
18171829
cnum_map: CrateNumMap,
1830+
target_modifiers: TargetModifiers,
18181831
dep_kind: CrateDepKind,
18191832
source: CrateSource,
18201833
private_dep: bool,
@@ -1846,6 +1859,7 @@ impl CrateMetadata {
18461859
cnum,
18471860
cnum_map,
18481861
dependencies,
1862+
target_modifiers,
18491863
dep_kind,
18501864
source: Lrc::new(source),
18511865
private_dep,
@@ -1875,6 +1889,10 @@ impl CrateMetadata {
18751889
self.dependencies.push(cnum);
18761890
}
18771891

1892+
pub(crate) fn target_modifiers(&self) -> impl Iterator<Item = &String> + '_ {
1893+
self.target_modifiers.iter()
1894+
}
1895+
18781896
pub(crate) fn update_extern_crate(&mut self, new_extern_crate: ExternCrate) -> bool {
18791897
let update =
18801898
Some(new_extern_crate.rank()) > self.extern_crate.as_ref().map(ExternCrate::rank);

‎compiler/rustc_metadata/src/rmeta/encoder.rs

+8
Original file line numberDiff line numberDiff line change
@@ -692,6 +692,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
692692
// Encode source_map. This needs to be done last, because encoding `Span`s tells us which
693693
// `SourceFiles` we actually need to encode.
694694
let source_map = stat!("source-map", || self.encode_source_map());
695+
let target_modifiers = stat!("target-modifiers", || self.encode_target_modifiers());
695696

696697
let root = stat!("final", || {
697698
let attrs = tcx.hir().krate_attrs();
@@ -732,6 +733,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
732733
native_libraries,
733734
foreign_modules,
734735
source_map,
736+
target_modifiers,
735737
traits,
736738
impls,
737739
incoherent_impls,
@@ -1978,6 +1980,12 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
19781980
self.lazy_array(deps.iter().map(|(_, dep)| dep))
19791981
}
19801982

1983+
fn encode_target_modifiers(&mut self) -> LazyArray<String> {
1984+
empty_proc_macro!(self);
1985+
let tcx = self.tcx;
1986+
self.lazy_array(tcx.sess.opts.gather_target_modifiers())
1987+
}
1988+
19811989
fn encode_lib_features(&mut self) -> LazyArray<(Symbol, FeatureStability)> {
19821990
empty_proc_macro!(self);
19831991
let tcx = self.tcx;

‎compiler/rustc_metadata/src/rmeta/mod.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
use std::marker::PhantomData;
22
use std::num::NonZero;
33

4-
pub(crate) use decoder::{CrateMetadata, CrateNumMap, MetadataBlob};
4+
pub(crate) use decoder::{CrateMetadata, CrateNumMap, MetadataBlob, TargetModifiers};
55
use decoder::{DecodeContext, Metadata};
66
use def_path_hash_map::DefPathHashMapRef;
77
use encoder::EncodeContext;
@@ -283,6 +283,7 @@ pub(crate) struct CrateRoot {
283283
def_path_hash_map: LazyValue<DefPathHashMapRef<'static>>,
284284

285285
source_map: LazyTable<u32, Option<LazyValue<rustc_span::SourceFile>>>,
286+
target_modifiers: LazyArray<String>,
286287

287288
compiler_builtins: bool,
288289
needs_allocator: bool,
There was a problem loading the remainder of the diff.

0 commit comments

Comments
 (0)
Failed to load comments.