206206//! regardless of whether it is actually needed or not.
207207
208208use std:: path:: PathBuf ;
209+ use std:: sync:: atomic:: { AtomicUsize , Ordering } ;
209210
210211use rustc_attr_parsing:: InlineAttr ;
211212use rustc_data_structures:: fx:: FxIndexMap ;
@@ -233,10 +234,12 @@ use rustc_middle::{bug, span_bug};
233234use rustc_session:: Limit ;
234235use rustc_session:: config:: EntryFnType ;
235236use rustc_span:: source_map:: { Spanned , dummy_spanned, respan} ;
236- use rustc_span:: { DUMMY_SP , Span } ;
237+ use rustc_span:: { DUMMY_SP , ErrorGuaranteed , Span } ;
237238use tracing:: { debug, instrument, trace} ;
238239
239- use crate :: errors:: { self , EncounteredErrorWhileInstantiating , NoOptimizedMir , RecursionLimit } ;
240+ use crate :: errors:: {
241+ self , EncounteredErrorWhileInstantiating , MAX_NUMBER_OF_ERRORS , NoOptimizedMir , RecursionLimit ,
242+ } ;
240243
241244#[ derive( PartialEq ) ]
242245pub ( crate ) enum MonoItemCollectionStrategy {
@@ -253,6 +256,8 @@ struct SharedState<'tcx> {
253256 mentioned : MTLock < UnordSet < MonoItem < ' tcx > > > ,
254257 /// Which items are being used where, for better errors.
255258 usage_map : MTLock < UsageMap < ' tcx > > ,
259+ /// Number of errors that have occurred during collection.
260+ error_count : AtomicUsize ,
256261}
257262
258263pub ( crate ) struct UsageMap < ' tcx > {
@@ -362,6 +367,16 @@ fn collect_items_rec<'tcx>(
362367 recursion_limit : Limit ,
363368 mode : CollectionMode ,
364369) {
370+ if state. error_count . load ( Ordering :: Relaxed ) > MAX_NUMBER_OF_ERRORS {
371+ tcx. dcx ( ) . span_fatal (
372+ starting_item. span ,
373+ format ! (
374+ "the limit of {} errors has been reached during monomorphization" ,
375+ MAX_NUMBER_OF_ERRORS
376+ ) ,
377+ ) ;
378+ }
379+
365380 if mode == CollectionMode :: UsedItems {
366381 if !state. visited . lock_mut ( ) . insert ( starting_item. node ) {
367382 // We've been here already, no need to search again.
@@ -466,9 +481,15 @@ fn collect_items_rec<'tcx>(
466481 ) ) ;
467482
468483 rustc_data_structures:: stack:: ensure_sufficient_stack ( || {
469- let ( used, mentioned) = tcx. items_of_instance ( ( instance, mode) ) ;
470- used_items. extend ( used. into_iter ( ) . copied ( ) ) ;
471- mentioned_items. extend ( mentioned. into_iter ( ) . copied ( ) ) ;
484+ match tcx. items_of_instance ( ( instance, mode) ) {
485+ Ok ( ( used, mentioned) ) => {
486+ used_items. extend ( used. into_iter ( ) . copied ( ) ) ;
487+ mentioned_items. extend ( mentioned. into_iter ( ) . copied ( ) ) ;
488+ }
489+ Err ( _) => {
490+ state. error_count . fetch_add ( 1 , Ordering :: Relaxed ) ;
491+ }
492+ } ;
472493 } ) ;
473494 }
474495 MonoItem :: GlobalAsm ( item_id) => {
@@ -660,7 +681,7 @@ impl<'a, 'tcx> MirUsedCollector<'a, 'tcx> {
660681 ) ,
661682 Err ( err @ ErrorHandled :: Reported ( ..) ) => {
662683 err. emit_note ( self . tcx ) ;
663- return None ;
684+ None
664685 }
665686 }
666687 }
@@ -1211,7 +1232,7 @@ fn collect_items_of_instance<'tcx>(
12111232 tcx : TyCtxt < ' tcx > ,
12121233 instance : Instance < ' tcx > ,
12131234 mode : CollectionMode ,
1214- ) -> ( MonoItems < ' tcx > , MonoItems < ' tcx > ) {
1235+ ) -> Result < ( MonoItems < ' tcx > , MonoItems < ' tcx > ) , ErrorGuaranteed > {
12151236 // This item is getting monomorphized, do mono-time checks.
12161237 tcx. ensure ( ) . check_mono_item ( instance) ;
12171238
@@ -1245,9 +1266,12 @@ fn collect_items_of_instance<'tcx>(
12451266
12461267 // Always visit all `required_consts`, so that we evaluate them and abort compilation if any of
12471268 // them errors.
1269+ let mut error_occurred = false ;
12481270 for const_op in body. required_consts ( ) {
12491271 if let Some ( val) = collector. eval_constant ( const_op) {
12501272 collect_const_value ( tcx, val, & mut mentioned_items) ;
1273+ } else {
1274+ error_occurred = true ;
12511275 }
12521276 }
12531277
@@ -1260,19 +1284,25 @@ fn collect_items_of_instance<'tcx>(
12601284 }
12611285 }
12621286
1263- ( used_items, mentioned_items)
1287+ if error_occurred {
1288+ let def_span = tcx. def_span ( instance. def_id ( ) ) ;
1289+ let err = tcx. dcx ( ) . span_delayed_bug ( def_span, "constant evaluation error" ) ;
1290+ return Err ( err) ;
1291+ }
1292+
1293+ Ok ( ( used_items, mentioned_items) )
12641294}
12651295
12661296fn items_of_instance < ' tcx > (
12671297 tcx : TyCtxt < ' tcx > ,
12681298 ( instance, mode) : ( Instance < ' tcx > , CollectionMode ) ,
1269- ) -> ( & ' tcx [ Spanned < MonoItem < ' tcx > > ] , & ' tcx [ Spanned < MonoItem < ' tcx > > ] ) {
1270- let ( used_items, mentioned_items) = collect_items_of_instance ( tcx, instance, mode) ;
1299+ ) -> Result < ( & ' tcx [ Spanned < MonoItem < ' tcx > > ] , & ' tcx [ Spanned < MonoItem < ' tcx > > ] ) , ErrorGuaranteed > {
1300+ let ( used_items, mentioned_items) = collect_items_of_instance ( tcx, instance, mode) ? ;
12711301
12721302 let used_items = tcx. arena . alloc_from_iter ( used_items) ;
12731303 let mentioned_items = tcx. arena . alloc_from_iter ( mentioned_items) ;
12741304
1275- ( used_items, mentioned_items)
1305+ Ok ( ( used_items, mentioned_items) )
12761306}
12771307
12781308/// `item` must be already monomorphized.
@@ -1651,6 +1681,7 @@ pub(crate) fn collect_crate_mono_items<'tcx>(
16511681 visited : MTLock :: new ( UnordSet :: default ( ) ) ,
16521682 mentioned : MTLock :: new ( UnordSet :: default ( ) ) ,
16531683 usage_map : MTLock :: new ( UsageMap :: new ( ) ) ,
1684+ error_count : AtomicUsize :: new ( 0 ) ,
16541685 } ;
16551686 let recursion_limit = tcx. recursion_limit ( ) ;
16561687
0 commit comments