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