@@ -27,6 +27,7 @@ use super::{VtableBuiltin, VtableImpl, VtableParam, VtableUnboxedClosure};
27
27
use super :: { VtableImplData , VtableParamData , VtableBuiltinData } ;
28
28
use super :: { util} ;
29
29
30
+ use middle:: fast_reject;
30
31
use middle:: mem_categorization:: Typer ;
31
32
use middle:: subst:: { Subst , Substs , VecPerParamSpace } ;
32
33
use middle:: ty;
@@ -1767,12 +1768,20 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
1767
1768
obligation : & Obligation )
1768
1769
-> Result < Substs , ( ) >
1769
1770
{
1771
+ let impl_trait_ref = ty:: impl_trait_ref ( self . tcx ( ) ,
1772
+ impl_def_id) . unwrap ( ) ;
1773
+
1774
+ // Before we create the substitutions and everything, first
1775
+ // consider a "quick reject". This avoids creating more types
1776
+ // and so forth that we need to.
1777
+ if self . fast_reject_trait_refs ( obligation, & * impl_trait_ref) {
1778
+ return Err ( ( ) ) ;
1779
+ }
1780
+
1770
1781
let impl_substs = util:: fresh_substs_for_impl ( self . infcx ,
1771
1782
obligation. cause . span ,
1772
1783
impl_def_id) ;
1773
1784
1774
- let impl_trait_ref = ty:: impl_trait_ref ( self . tcx ( ) ,
1775
- impl_def_id) . unwrap ( ) ;
1776
1785
let impl_trait_ref = impl_trait_ref. subst ( self . tcx ( ) ,
1777
1786
& impl_substs) ;
1778
1787
@@ -1782,6 +1791,29 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
1782
1791
}
1783
1792
}
1784
1793
1794
+ fn fast_reject_trait_refs ( & mut self ,
1795
+ obligation : & Obligation ,
1796
+ impl_trait_ref : & ty:: TraitRef )
1797
+ -> bool
1798
+ {
1799
+ // We can avoid creating type variables and doing the full
1800
+ // substitution if we find that any of the input types, when
1801
+ // simplified, do not match.
1802
+
1803
+ obligation. trait_ref . input_types ( ) . iter ( )
1804
+ . zip ( impl_trait_ref. input_types ( ) . iter ( ) )
1805
+ . any ( |( & obligation_ty, & impl_ty) | {
1806
+ let simplified_obligation_ty =
1807
+ fast_reject:: simplify_type ( self . tcx ( ) , obligation_ty, true ) ;
1808
+ let simplified_impl_ty =
1809
+ fast_reject:: simplify_type ( self . tcx ( ) , impl_ty, false ) ;
1810
+
1811
+ simplified_obligation_ty. is_some ( ) &&
1812
+ simplified_impl_ty. is_some ( ) &&
1813
+ simplified_obligation_ty != simplified_impl_ty
1814
+ } )
1815
+ }
1816
+
1785
1817
fn match_trait_refs ( & mut self ,
1786
1818
obligation : & Obligation ,
1787
1819
trait_ref : Rc < ty:: TraitRef > )
0 commit comments