@@ -1024,23 +1024,12 @@ impl<'a, 'tcx> Checker<'a, 'tcx> {
1024
1024
new_errors. dedup ( ) ;
1025
1025
1026
1026
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
+ ) ;
1044
1033
}
1045
1034
}
1046
1035
@@ -1870,6 +1859,58 @@ fn args_required_const(tcx: TyCtxt<'_>, def_id: DefId) -> Option<FxHashSet<usize
1870
1859
Some ( ret)
1871
1860
}
1872
1861
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
+
1873
1914
const VALIDATOR_MISMATCH_ERR : & str =
1874
1915
r"Disagreement between legacy and dataflow-based const validators.
1875
1916
After filing an issue, use `-Zsuppress-const-validation-back-compat-ice` to compile your code." ;
0 commit comments