@@ -24,7 +24,7 @@ use rustc_middle::bug;
2424use rustc_middle:: ty:: { TyCtxt , TyCtxtFeed } ;
2525use rustc_session:: config:: { self , CrateType , ExternLocation } ;
2626use rustc_session:: cstore:: { CrateDepKind , CrateSource , ExternCrate , ExternCrateSource } ;
27- use rustc_session:: lint:: { self , BuiltinLintDiag } ;
27+ use rustc_session:: lint:: { self , BuiltinLintDiag , LintBuffer } ;
2828use rustc_session:: output:: validate_crate_name;
2929use rustc_session:: search_paths:: PathKind ;
3030use rustc_span:: edition:: Edition ;
@@ -35,7 +35,9 @@ use tracing::{debug, info, trace};
3535
3636use crate :: errors;
3737use 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 ,
0 commit comments