@@ -1024,23 +1024,12 @@ impl<'a, 'tcx> Checker<'a, 'tcx> {
10241024 new_errors. dedup ( ) ;
10251025
10261026 if self . errors != new_errors {
1027- error ! ( "old validator: {:?}" , self . errors) ;
1028- error ! ( "new validator: {:?}" , new_errors) ;
1029-
1030- // ICE on nightly if the validators do not emit exactly the same errors.
1031- // Users can supress this panic with an unstable compiler flag (hopefully after
1032- // filing an issue).
1033- let opts = & self . tcx . sess . opts ;
1034- let trigger_ice = opts. unstable_features . is_nightly_build ( )
1035- && !opts. debugging_opts . suppress_const_validation_back_compat_ice ;
1036-
1037- if trigger_ice {
1038- span_bug ! (
1039- body. span,
1040- "{}" ,
1041- VALIDATOR_MISMATCH_ERR ,
1042- ) ;
1043- }
1027+ validator_mismatch (
1028+ self . tcx ,
1029+ body,
1030+ std:: mem:: replace ( & mut self . errors , vec ! [ ] ) ,
1031+ new_errors,
1032+ ) ;
10441033 }
10451034 }
10461035
@@ -1870,6 +1859,58 @@ fn args_required_const(tcx: TyCtxt<'_>, def_id: DefId) -> Option<FxHashSet<usize
18701859 Some ( ret)
18711860}
18721861
1862+ fn validator_mismatch (
1863+ tcx : TyCtxt < ' tcx > ,
1864+ body : & Body < ' tcx > ,
1865+ mut old_errors : Vec < ( Span , String ) > ,
1866+ mut new_errors : Vec < ( Span , String ) > ,
1867+ ) {
1868+ error ! ( "old validator: {:?}" , old_errors) ;
1869+ error ! ( "new validator: {:?}" , new_errors) ;
1870+
1871+ // ICE on nightly if the validators do not emit exactly the same errors.
1872+ // Users can supress this panic with an unstable compiler flag (hopefully after
1873+ // filing an issue).
1874+ let opts = & tcx. sess . opts ;
1875+ let strict_validation_enabled = opts. unstable_features . is_nightly_build ( )
1876+ && !opts. debugging_opts . suppress_const_validation_back_compat_ice ;
1877+
1878+ if !strict_validation_enabled {
1879+ return ;
1880+ }
1881+
1882+ // If this difference would cause a regression from the old to the new or vice versa, trigger
1883+ // the ICE.
1884+ if old_errors. is_empty ( ) || new_errors. is_empty ( ) {
1885+ span_bug ! ( body. span, "{}" , VALIDATOR_MISMATCH_ERR ) ;
1886+ }
1887+
1888+ // HACK: Borrows that would allow mutation are forbidden in const contexts, but they cause the
1889+ // new validator to be more conservative about when a dropped local has been moved out of.
1890+ //
1891+ // Supress the mismatch ICE in cases where the validators disagree only on the number of
1892+ // `LiveDrop` errors and both observe the same sequence of `MutBorrow`s.
1893+
1894+ let is_live_drop = |( _, s) : & mut ( _ , String ) | s. starts_with ( "LiveDrop" ) ;
1895+ let is_mut_borrow = |( _, s) : & & ( _ , String ) | s. starts_with ( "MutBorrow" ) ;
1896+
1897+ let old_live_drops: Vec < _ > = old_errors. drain_filter ( is_live_drop) . collect ( ) ;
1898+ let new_live_drops: Vec < _ > = new_errors. drain_filter ( is_live_drop) . collect ( ) ;
1899+
1900+ let only_live_drops_differ = old_live_drops != new_live_drops && old_errors == new_errors;
1901+
1902+ let old_mut_borrows = old_errors. iter ( ) . filter ( is_mut_borrow) ;
1903+ let new_mut_borrows = new_errors. iter ( ) . filter ( is_mut_borrow) ;
1904+
1905+ let at_least_one_mut_borrow = old_mut_borrows. clone ( ) . next ( ) . is_some ( ) ;
1906+
1907+ if only_live_drops_differ && at_least_one_mut_borrow && old_mut_borrows. eq ( new_mut_borrows) {
1908+ return ;
1909+ }
1910+
1911+ span_bug ! ( body. span, "{}" , VALIDATOR_MISMATCH_ERR ) ;
1912+ }
1913+
18731914const VALIDATOR_MISMATCH_ERR : & str =
18741915 r"Disagreement between legacy and dataflow-based const validators.
18751916 After filing an issue, use `-Zsuppress-const-validation-back-compat-ice` to compile your code." ;
0 commit comments