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