13
13
pub use self :: MethodMatchResult :: * ;
14
14
pub use self :: MethodMatchedData :: * ;
15
15
use self :: SelectionCandidate :: * ;
16
- use self :: BuiltinBoundConditions :: * ;
17
16
use self :: EvaluationResult :: * ;
18
17
19
18
use super :: coherence;
@@ -232,10 +231,18 @@ struct EvaluatedCandidate<'tcx> {
232
231
evaluation : EvaluationResult ,
233
232
}
234
233
235
- enum BuiltinBoundConditions < ' tcx > {
236
- If ( ty:: Binder < Vec < Ty < ' tcx > > > ) ,
237
- ParameterBuiltin ,
238
- AmbiguousBuiltin
234
+ /// When does the builtin impl for `T: Trait` apply?
235
+ enum BuiltinImplConditions < ' tcx > {
236
+ /// The impl is conditional on T1,T2,.. : Trait
237
+ Where ( ty:: Binder < Vec < Ty < ' tcx > > > ) ,
238
+ /// There is no built-in impl. There may be some other
239
+ /// candidate (a where-clause or user-defined impl).
240
+ None ,
241
+ /// There is *no* impl for this, builtin or not. Ignore
242
+ /// all where-clauses.
243
+ Never ( SelectionError < ' tcx > ) ,
244
+ /// It is unknown whether there is an impl.
245
+ Ambiguous
239
246
}
240
247
241
248
#[ derive( Copy , Clone , Debug , PartialOrd , Ord , PartialEq , Eq ) ]
@@ -1608,39 +1615,45 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
1608
1615
// those will hopefully change to library-defined traits in the
1609
1616
// future.
1610
1617
1618
+ // HACK: if this returns an error, selection exits without considering
1619
+ // other impls.
1611
1620
fn assemble_builtin_bound_candidates < ' o > ( & mut self ,
1612
1621
bound : ty:: BuiltinBound ,
1613
1622
obligation : & TraitObligation < ' tcx > ,
1614
1623
candidates : & mut SelectionCandidateSet < ' tcx > )
1615
1624
-> Result < ( ) , SelectionError < ' tcx > >
1616
1625
{
1617
1626
match self . builtin_bound ( bound, obligation) {
1618
- Ok ( If ( .. ) ) => {
1627
+ BuiltinImplConditions :: Where ( .. ) => {
1619
1628
debug ! ( "builtin_bound: bound={:?}" ,
1620
1629
bound) ;
1621
1630
candidates. vec . push ( BuiltinCandidate ( bound) ) ;
1622
1631
Ok ( ( ) )
1623
1632
}
1624
- Ok ( ParameterBuiltin ) => { Ok ( ( ) ) }
1625
- Ok ( AmbiguousBuiltin ) => {
1633
+ BuiltinImplConditions :: None => { Ok ( ( ) ) }
1634
+ BuiltinImplConditions :: Ambiguous => {
1626
1635
debug ! ( "assemble_builtin_bound_candidates: ambiguous builtin" ) ;
1627
1636
Ok ( candidates. ambiguous = true )
1628
1637
}
1629
- Err ( e) => { Err ( e) }
1638
+ BuiltinImplConditions :: Never ( e) => { Err ( e) }
1630
1639
}
1631
1640
}
1632
1641
1633
1642
fn builtin_bound ( & mut self ,
1634
1643
bound : ty:: BuiltinBound ,
1635
1644
obligation : & TraitObligation < ' tcx > )
1636
- -> Result < BuiltinBoundConditions < ' tcx > , SelectionError < ' tcx > >
1645
+ -> BuiltinImplConditions < ' tcx >
1637
1646
{
1638
1647
// Note: these tests operate on types that may contain bound
1639
1648
// regions. To be proper, we ought to skolemize here, but we
1640
1649
// forego the skolemization and defer it until the
1641
1650
// confirmation step.
1642
1651
1643
1652
let self_ty = self . infcx . shallow_resolve ( obligation. predicate . 0 . self_ty ( ) ) ;
1653
+
1654
+ let always = BuiltinImplConditions :: Where ( ty:: Binder ( Vec :: new ( ) ) ) ;
1655
+ let never = BuiltinImplConditions :: Never ( Unimplemented ) ;
1656
+
1644
1657
return match self_ty. sty {
1645
1658
ty:: TyInfer ( ty:: IntVar ( _) ) |
1646
1659
ty:: TyInfer ( ty:: FloatVar ( _) ) |
@@ -1652,14 +1665,13 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
1652
1665
ty:: TyFnPtr ( _) |
1653
1666
ty:: TyChar => {
1654
1667
// safe for everything
1655
- ok_if ( Vec :: new ( ) )
1668
+ always
1656
1669
}
1657
1670
1658
1671
ty:: TyBox ( _) => { // Box<T>
1659
1672
match bound {
1660
- ty:: BoundCopy => Err ( Unimplemented ) ,
1661
-
1662
- ty:: BoundSized => ok_if ( Vec :: new ( ) ) ,
1673
+ ty:: BoundCopy => never,
1674
+ ty:: BoundSized => always,
1663
1675
1664
1676
ty:: BoundSync | ty:: BoundSend => {
1665
1677
bug ! ( "Send/Sync shouldn't occur in builtin_bounds()" ) ;
@@ -1669,7 +1681,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
1669
1681
1670
1682
ty:: TyRawPtr ( ..) => { // *const T, *mut T
1671
1683
match bound {
1672
- ty:: BoundCopy | ty:: BoundSized => ok_if ( Vec :: new ( ) ) ,
1684
+ ty:: BoundCopy | ty:: BoundSized => always ,
1673
1685
1674
1686
ty:: BoundSync | ty:: BoundSend => {
1675
1687
bug ! ( "Send/Sync shouldn't occur in builtin_bounds()" ) ;
@@ -1679,10 +1691,11 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
1679
1691
1680
1692
ty:: TyTrait ( ref data) => {
1681
1693
match bound {
1682
- ty:: BoundSized => Err ( Unimplemented ) ,
1694
+ ty:: BoundSized => never ,
1683
1695
ty:: BoundCopy => {
1696
+ // FIXME(#32963): bit-rot fungus infestation
1684
1697
if data. bounds . builtin_bounds . contains ( & bound) {
1685
- ok_if ( Vec :: new ( ) )
1698
+ always
1686
1699
} else {
1687
1700
// Recursively check all supertraits to find out if any further
1688
1701
// bounds are required and thus we must fulfill.
@@ -1692,11 +1705,11 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
1692
1705
let copy_def_id = obligation. predicate . def_id ( ) ;
1693
1706
for tr in util:: supertraits ( self . tcx ( ) , principal) {
1694
1707
if tr. def_id ( ) == copy_def_id {
1695
- return ok_if ( Vec :: new ( ) )
1708
+ return always
1696
1709
}
1697
1710
}
1698
1711
1699
- Err ( Unimplemented )
1712
+ never
1700
1713
}
1701
1714
}
1702
1715
ty:: BoundSync | ty:: BoundSend => {
@@ -1711,14 +1724,14 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
1711
1724
ty:: BoundCopy => {
1712
1725
match mutbl {
1713
1726
// &mut T is affine and hence never `Copy`
1714
- hir:: MutMutable => Err ( Unimplemented ) ,
1727
+ hir:: MutMutable => never ,
1715
1728
1716
1729
// &T is always copyable
1717
- hir:: MutImmutable => ok_if ( Vec :: new ( ) ) ,
1730
+ hir:: MutImmutable => always
1718
1731
}
1719
1732
}
1720
1733
1721
- ty:: BoundSized => ok_if ( Vec :: new ( ) ) ,
1734
+ ty:: BoundSized => always ,
1722
1735
1723
1736
ty:: BoundSync | ty:: BoundSend => {
1724
1737
bug ! ( "Send/Sync shouldn't occur in builtin_bounds()" ) ;
@@ -1730,7 +1743,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
1730
1743
// [T; n]
1731
1744
match bound {
1732
1745
ty:: BoundCopy => ok_if ( vec ! [ element_ty] ) ,
1733
- ty:: BoundSized => ok_if ( Vec :: new ( ) ) ,
1746
+ ty:: BoundSized => always ,
1734
1747
ty:: BoundSync | ty:: BoundSend => {
1735
1748
bug ! ( "Send/Sync shouldn't occur in builtin_bounds()" ) ;
1736
1749
}
@@ -1743,65 +1756,61 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
1743
1756
bug ! ( "Send/Sync shouldn't occur in builtin_bounds()" ) ;
1744
1757
}
1745
1758
1746
- ty:: BoundCopy | ty:: BoundSized => Err ( Unimplemented ) ,
1759
+ ty:: BoundCopy | ty:: BoundSized => never
1747
1760
}
1748
1761
}
1749
1762
1750
1763
// (T1, ..., Tn) -- meets any bound that all of T1...Tn meet
1751
1764
ty:: TyTuple ( ref tys) => ok_if ( tys. clone ( ) ) ,
1752
1765
1753
- ty:: TyClosure ( _, ref substs) => {
1754
- // FIXME -- This case is tricky. In the case of by-ref
1755
- // closures particularly, we need the results of
1756
- // inference to decide how to reflect the type of each
1757
- // upvar (the upvar may have type `T`, but the runtime
1758
- // type could be `&mut`, `&`, or just `T`). For now,
1759
- // though, we'll do this unsoundly and assume that all
1760
- // captures are by value. Really what we ought to do
1761
- // is reserve judgement and then intertwine this
1762
- // analysis with closure inference.
1763
-
1764
- // Unboxed closures shouldn't be
1765
- // implicitly copyable
1766
- if bound == ty:: BoundCopy {
1767
- return Ok ( ParameterBuiltin ) ;
1768
- }
1766
+ ty:: TyClosure ( ..) => {
1767
+ match bound {
1768
+ ty:: BoundSync | ty:: BoundSend => {
1769
+ bug ! ( "Send/Sync shouldn't occur in builtin_bounds()" ) ;
1770
+ }
1769
1771
1770
- // Upvars are always local variables or references to
1771
- // local variables, and local variables cannot be
1772
- // unsized, so the closure struct as a whole must be
1773
- // Sized.
1774
- if bound == ty:: BoundSized {
1775
- return ok_if ( Vec :: new ( ) ) ;
1772
+ ty:: BoundCopy => never,
1773
+ ty:: BoundSized => always
1776
1774
}
1777
-
1778
- ok_if ( substs. upvar_tys . clone ( ) )
1779
1775
}
1780
1776
1781
1777
ty:: TyStruct ( def, substs) | ty:: TyEnum ( def, substs) => {
1782
- let types: Vec < Ty > = def. all_fields ( ) . map ( |f| {
1783
- f. ty ( self . tcx ( ) , substs)
1784
- } ) . collect ( ) ;
1785
- nominal ( bound, types)
1778
+ match bound {
1779
+ // Fallback to whatever user-defined impls exist in this case.
1780
+ ty:: BoundCopy => BuiltinImplConditions :: None ,
1781
+
1782
+ // Sized if all the component types are sized.
1783
+ ty:: BoundSized => {
1784
+ let sized_crit = def. sized_constraint ( self . tcx ( ) ) ;
1785
+ if sized_crit == self . tcx ( ) . types . bool {
1786
+ always
1787
+ } else {
1788
+ ok_if ( vec ! [ sized_crit. subst( self . tcx( ) , substs) ] )
1789
+ }
1790
+ }
1791
+
1792
+ // Shouldn't be coming through here.
1793
+ ty:: BoundSend | ty:: BoundSync => bug ! ( ) ,
1794
+ }
1786
1795
}
1787
1796
1788
1797
ty:: TyProjection ( _) | ty:: TyParam ( _) => {
1789
1798
// Note: A type parameter is only considered to meet a
1790
1799
// particular bound if there is a where clause telling
1791
1800
// us that it does, and that case is handled by
1792
1801
// `assemble_candidates_from_caller_bounds()`.
1793
- Ok ( ParameterBuiltin )
1802
+ BuiltinImplConditions :: None
1794
1803
}
1795
1804
1796
1805
ty:: TyInfer ( ty:: TyVar ( _) ) => {
1797
1806
// Unbound type variable. Might or might not have
1798
1807
// applicable impls and so forth, depending on what
1799
1808
// those type variables wind up being bound to.
1800
1809
debug ! ( "assemble_builtin_bound_candidates: ambiguous builtin" ) ;
1801
- Ok ( AmbiguousBuiltin )
1810
+ BuiltinImplConditions :: Ambiguous
1802
1811
}
1803
1812
1804
- ty:: TyError => ok_if ( Vec :: new ( ) ) ,
1813
+ ty:: TyError => always ,
1805
1814
1806
1815
ty:: TyInfer ( ty:: FreshTy ( _) )
1807
1816
| ty:: TyInfer ( ty:: FreshIntTy ( _) )
@@ -1811,26 +1820,8 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
1811
1820
}
1812
1821
} ;
1813
1822
1814
- fn ok_if < ' tcx > ( v : Vec < Ty < ' tcx > > )
1815
- -> Result < BuiltinBoundConditions < ' tcx > , SelectionError < ' tcx > > {
1816
- Ok ( If ( ty:: Binder ( v) ) )
1817
- }
1818
-
1819
- fn nominal < ' cx , ' tcx > ( bound : ty:: BuiltinBound ,
1820
- types : Vec < Ty < ' tcx > > )
1821
- -> Result < BuiltinBoundConditions < ' tcx > , SelectionError < ' tcx > >
1822
- {
1823
- // First check for markers and other nonsense.
1824
- match bound {
1825
- // Fallback to whatever user-defined impls exist in this case.
1826
- ty:: BoundCopy => Ok ( ParameterBuiltin ) ,
1827
-
1828
- // Sized if all the component types are sized.
1829
- ty:: BoundSized => ok_if ( types) ,
1830
-
1831
- // Shouldn't be coming through here.
1832
- ty:: BoundSend | ty:: BoundSync => bug ! ( ) ,
1833
- }
1823
+ fn ok_if < ' tcx > ( v : Vec < Ty < ' tcx > > ) -> BuiltinImplConditions < ' tcx > {
1824
+ BuiltinImplConditions :: Where ( ty:: Binder ( v) )
1834
1825
}
1835
1826
}
1836
1827
@@ -1999,7 +1990,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
1999
1990
match candidate {
2000
1991
BuiltinCandidate ( builtin_bound) => {
2001
1992
Ok ( VtableBuiltin (
2002
- self . confirm_builtin_candidate ( obligation, builtin_bound) ? ) )
1993
+ self . confirm_builtin_candidate ( obligation, builtin_bound) ) )
2003
1994
}
2004
1995
2005
1996
ParamCandidate ( param) => {
@@ -2100,18 +2091,18 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
2100
2091
fn confirm_builtin_candidate ( & mut self ,
2101
2092
obligation : & TraitObligation < ' tcx > ,
2102
2093
bound : ty:: BuiltinBound )
2103
- -> Result < VtableBuiltinData < PredicateObligation < ' tcx > > ,
2104
- SelectionError < ' tcx > >
2094
+ -> VtableBuiltinData < PredicateObligation < ' tcx > >
2105
2095
{
2106
2096
debug ! ( "confirm_builtin_candidate({:?})" ,
2107
2097
obligation) ;
2108
2098
2109
- match self . builtin_bound ( bound, obligation) ? {
2110
- If ( nested) => Ok ( self . vtable_builtin_data ( obligation, bound, nested) ) ,
2111
- AmbiguousBuiltin | ParameterBuiltin => {
2099
+ match self . builtin_bound ( bound, obligation) {
2100
+ BuiltinImplConditions :: Where ( nested) =>
2101
+ self . vtable_builtin_data ( obligation, bound, nested) ,
2102
+ _ => {
2112
2103
span_bug ! (
2113
2104
obligation. cause. span,
2114
- "builtin bound for {:?} was ambig " ,
2105
+ "confiriming builtin impl for {:?} where none exists " ,
2115
2106
obligation) ;
2116
2107
}
2117
2108
}
0 commit comments