@@ -1784,43 +1784,49 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
1784
1784
// variable would only be in `unbound_tyvars` and have a concrete value if
1785
1785
// it had been solved by previously applying a default.
1786
1786
1787
- // We take a snapshot for use in error reporting.
1788
- let snapshot = self . infcx ( ) . start_snapshot ( ) ;
1789
-
1790
- for ty in & unbound_tyvars {
1791
- if self . infcx ( ) . type_var_diverges ( ty) {
1792
- demand:: eqtype ( self , codemap:: DUMMY_SP , * ty, self . tcx ( ) . mk_nil ( ) ) ;
1793
- } else {
1794
- match self . infcx ( ) . type_is_unconstrained_numeric ( ty) {
1795
- UnconstrainedInt => {
1796
- demand:: eqtype ( self , codemap:: DUMMY_SP , * ty, self . tcx ( ) . types . i32 )
1797
- } ,
1798
- UnconstrainedFloat => {
1799
- demand:: eqtype ( self , codemap:: DUMMY_SP , * ty, self . tcx ( ) . types . f64 )
1800
- }
1801
- Neither => {
1802
- if let Some ( default) = default_map. get ( ty) {
1803
- let default = default. clone ( ) ;
1804
- match infer:: mk_eqty ( self . infcx ( ) , false ,
1805
- infer:: Misc ( default. origin_span ) ,
1806
- ty, default. ty ) {
1807
- Ok ( ( ) ) => { }
1808
- Err ( _) => {
1809
- conflicts. push ( ( * ty, default) ) ;
1787
+ // We wrap this in a transaction for error reporting, if we detect a conflict
1788
+ // we will rollback the inference context to its prior state so we can probe
1789
+ // for conflicts and correctly report them.
1790
+ let _ = self . infcx ( ) . commit_if_ok ( |_: & infer:: CombinedSnapshot | {
1791
+ for ty in & unbound_tyvars {
1792
+ if self . infcx ( ) . type_var_diverges ( ty) {
1793
+ demand:: eqtype ( self , codemap:: DUMMY_SP , * ty, self . tcx ( ) . mk_nil ( ) ) ;
1794
+ } else {
1795
+ match self . infcx ( ) . type_is_unconstrained_numeric ( ty) {
1796
+ UnconstrainedInt => {
1797
+ demand:: eqtype ( self , codemap:: DUMMY_SP , * ty, self . tcx ( ) . types . i32 )
1798
+ } ,
1799
+ UnconstrainedFloat => {
1800
+ demand:: eqtype ( self , codemap:: DUMMY_SP , * ty, self . tcx ( ) . types . f64 )
1801
+ }
1802
+ Neither => {
1803
+ if let Some ( default) = default_map. get ( ty) {
1804
+ let default = default. clone ( ) ;
1805
+ match infer:: mk_eqty ( self . infcx ( ) , false ,
1806
+ infer:: Misc ( default. origin_span ) ,
1807
+ ty, default. ty ) {
1808
+ Ok ( ( ) ) => { }
1809
+ Err ( _) => {
1810
+ conflicts. push ( ( * ty, default) ) ;
1811
+ }
1810
1812
}
1811
1813
}
1812
1814
}
1813
1815
}
1814
1816
}
1815
1817
}
1816
- }
1817
1818
1818
- // There are some errors to report
1819
- if conflicts. len ( ) > 0 {
1820
- self . infcx ( ) . rollback_to ( snapshot) ;
1819
+ // If there are conflicts we rollback, otherwise commit
1820
+ if conflicts. len ( ) > 0 {
1821
+ Err ( ( ) )
1822
+ } else {
1823
+ Ok ( ( ) )
1824
+ }
1825
+ } ) ;
1821
1826
1822
- // Loop through each conflicting default compute the conflict
1823
- // and then report the error.
1827
+ if conflicts. len ( ) > 0 {
1828
+ // Loop through each conflicting default, figuring out the default that caused
1829
+ // a unification failure and then report an error for each.
1824
1830
for ( conflict, default) in conflicts {
1825
1831
let conflicting_default =
1826
1832
self . find_conflicting_default (
@@ -1832,13 +1838,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
1832
1838
definition_span : codemap:: DUMMY_SP
1833
1839
} ) ;
1834
1840
1835
- self . infcx ( ) . report_conflicting_default_types (
1836
- conflicting_default. origin_span ,
1837
- conflicting_default,
1838
- default)
1841
+ self . infcx ( ) . report_conflicting_default_types (
1842
+ conflicting_default. origin_span ,
1843
+ conflicting_default,
1844
+ default)
1839
1845
}
1840
- } else {
1841
- self . infcx ( ) . commit_from ( snapshot)
1842
1846
}
1843
1847
}
1844
1848
@@ -1856,41 +1860,47 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
1856
1860
-> Option < type_variable:: Default < ' tcx > > {
1857
1861
use middle:: ty:: UnconstrainedNumeric :: { UnconstrainedInt , UnconstrainedFloat , Neither } ;
1858
1862
1859
- // Ensure that the conflicting default is applied first
1863
+ // Ensure that we apply the conflicting default first
1860
1864
let mut unbound_tyvars = Vec :: with_capacity ( unbound_vars. len ( ) + 1 ) ;
1861
1865
unbound_tyvars. push ( conflict) ;
1862
1866
unbound_tyvars. extend ( unbound_vars. iter ( ) ) ;
1863
1867
1864
1868
let mut result = None ;
1865
1869
// We run the same code as above applying defaults in order, this time when
1866
1870
// we find the conflict we just return it for error reporting above.
1867
- for ty in & unbound_tyvars {
1868
- if self . infcx ( ) . type_var_diverges ( ty) {
1869
- demand:: eqtype ( self , codemap:: DUMMY_SP , * ty, self . tcx ( ) . mk_nil ( ) ) ;
1870
- } else {
1871
- match self . infcx ( ) . type_is_unconstrained_numeric ( ty) {
1872
- UnconstrainedInt => {
1873
- demand:: eqtype ( self , codemap:: DUMMY_SP , * ty, self . tcx ( ) . types . i32 )
1874
- } ,
1875
- UnconstrainedFloat => {
1876
- demand:: eqtype ( self , codemap:: DUMMY_SP , * ty, self . tcx ( ) . types . f64 )
1877
- } ,
1878
- Neither => {
1879
- if let Some ( default) = default_map. get ( ty) {
1880
- let default = default. clone ( ) ;
1881
- match infer:: mk_eqty ( self . infcx ( ) , false ,
1882
- infer:: Misc ( default. origin_span ) ,
1883
- ty, default. ty ) {
1884
- Ok ( ( ) ) => { }
1885
- Err ( _) => {
1886
- result = Some ( default) ;
1871
+
1872
+ // We also run this inside snapshot that never commits so we can do error
1873
+ // reporting for more then one conflict.
1874
+ //let _ = self.infcx().commit_if_ok(|_: &infer::CombinedSnapshot| {
1875
+ for ty in & unbound_tyvars {
1876
+ if self . infcx ( ) . type_var_diverges ( ty) {
1877
+ demand:: eqtype ( self , codemap:: DUMMY_SP , * ty, self . tcx ( ) . mk_nil ( ) ) ;
1878
+ } else {
1879
+ match self . infcx ( ) . type_is_unconstrained_numeric ( ty) {
1880
+ UnconstrainedInt => {
1881
+ demand:: eqtype ( self , codemap:: DUMMY_SP , * ty, self . tcx ( ) . types . i32 )
1882
+ } ,
1883
+ UnconstrainedFloat => {
1884
+ demand:: eqtype ( self , codemap:: DUMMY_SP , * ty, self . tcx ( ) . types . f64 )
1885
+ } ,
1886
+ Neither => {
1887
+ if let Some ( default) = default_map. get ( ty) {
1888
+ let default = default. clone ( ) ;
1889
+ match infer:: mk_eqty ( self . infcx ( ) , false ,
1890
+ infer:: Misc ( default. origin_span ) ,
1891
+ ty, default. ty ) {
1892
+ Ok ( ( ) ) => { }
1893
+ Err ( _) => {
1894
+ result = Some ( default) ;
1895
+ }
1887
1896
}
1888
1897
}
1889
1898
}
1890
1899
}
1891
1900
}
1892
1901
}
1893
- }
1902
+ // let result: Result<(), ()> = Err(()); result
1903
+ //});
1894
1904
1895
1905
return result;
1896
1906
}
0 commit comments