@@ -1652,6 +1652,13 @@ fn check_fn_or_method<'tcx>(
1652
1652
}
1653
1653
}
1654
1654
1655
+ /// The `arbitrary_self_types_pointers` feature implies `arbitrary_self_types`.
1656
+ #[ derive( Clone , Copy , PartialEq ) ]
1657
+ enum ArbitrarySelfTypesLevel {
1658
+ Basic , // just arbitrary_self_types
1659
+ WithPointers , // both arbitrary_self_types and arbitrary_self_types_pointers
1660
+ }
1661
+
1655
1662
#[ instrument( level = "debug" , skip( wfcx) ) ]
1656
1663
fn check_method_receiver < ' tcx > (
1657
1664
wfcx : & WfCheckingCtxt < ' _ , ' tcx > ,
@@ -1684,40 +1691,77 @@ fn check_method_receiver<'tcx>(
1684
1691
return Ok ( ( ) ) ;
1685
1692
}
1686
1693
1687
- if tcx. features ( ) . arbitrary_self_types {
1688
- if !receiver_is_valid ( wfcx, span, receiver_ty, self_ty, true ) {
1689
- // Report error; `arbitrary_self_types` was enabled.
1690
- return Err ( tcx. dcx ( ) . emit_err ( errors:: InvalidReceiverTy { span, receiver_ty } ) ) ;
1691
- }
1694
+ let arbitrary_self_types_level = if tcx. features ( ) . arbitrary_self_types_pointers {
1695
+ Some ( ArbitrarySelfTypesLevel :: WithPointers )
1696
+ } else if tcx. features ( ) . arbitrary_self_types {
1697
+ Some ( ArbitrarySelfTypesLevel :: Basic )
1692
1698
} else {
1693
- if !receiver_is_valid ( wfcx, span, receiver_ty, self_ty, false ) {
1694
- return Err ( if receiver_is_valid ( wfcx, span, receiver_ty, self_ty, true ) {
1699
+ None
1700
+ } ;
1701
+
1702
+ if !receiver_is_valid ( wfcx, span, receiver_ty, self_ty, arbitrary_self_types_level) {
1703
+ return Err ( match arbitrary_self_types_level {
1704
+ // Wherever possible, emit a message advising folks that the features
1705
+ // `arbitrary_self_types` or `arbitrary_self_types_pointers` might
1706
+ // have helped.
1707
+ None if receiver_is_valid (
1708
+ wfcx,
1709
+ span,
1710
+ receiver_ty,
1711
+ self_ty,
1712
+ Some ( ArbitrarySelfTypesLevel :: Basic ) ,
1713
+ ) =>
1714
+ {
1695
1715
// Report error; would have worked with `arbitrary_self_types`.
1696
1716
feature_err (
1697
1717
& tcx. sess ,
1698
1718
sym:: arbitrary_self_types,
1699
1719
span,
1700
1720
format ! (
1701
1721
"`{receiver_ty}` cannot be used as the type of `self` without \
1702
- the `arbitrary_self_types` feature",
1722
+ the `arbitrary_self_types` feature",
1703
1723
) ,
1704
1724
)
1705
1725
. with_help ( fluent:: hir_analysis_invalid_receiver_ty_help)
1706
1726
. emit ( )
1707
- } else {
1708
- // Report error; would not have worked with `arbitrary_self_types`.
1727
+ }
1728
+ None | Some ( ArbitrarySelfTypesLevel :: Basic )
1729
+ if receiver_is_valid (
1730
+ wfcx,
1731
+ span,
1732
+ receiver_ty,
1733
+ self_ty,
1734
+ Some ( ArbitrarySelfTypesLevel :: WithPointers ) ,
1735
+ ) =>
1736
+ {
1737
+ // Report error; would have worked with `arbitrary_self_types_pointers`.
1738
+ feature_err (
1739
+ & tcx. sess ,
1740
+ sym:: arbitrary_self_types_pointers,
1741
+ span,
1742
+ format ! (
1743
+ "`{receiver_ty}` cannot be used as the type of `self` without \
1744
+ the `arbitrary_self_types_pointers` feature",
1745
+ ) ,
1746
+ )
1747
+ . with_help ( fluent:: hir_analysis_invalid_receiver_ty_help)
1748
+ . emit ( )
1749
+ }
1750
+ _ =>
1751
+ // Report error; would not have worked with `arbitrary_self_types[_pointers]`.
1752
+ {
1709
1753
tcx. dcx ( ) . emit_err ( errors:: InvalidReceiverTy { span, receiver_ty } )
1710
- } ) ;
1711
- }
1754
+ }
1755
+ } ) ;
1712
1756
}
1713
1757
Ok ( ( ) )
1714
1758
}
1715
1759
1716
1760
/// Returns whether `receiver_ty` would be considered a valid receiver type for `self_ty`. If
1717
1761
/// `arbitrary_self_types` is enabled, `receiver_ty` must transitively deref to `self_ty`, possibly
1718
- /// through a `*const/mut T` raw pointer. If the feature is not enabled, the requirements are more
1719
- /// strict: `receiver_ty` must implement `Receiver` and directly implement
1720
- /// `Deref<Target = self_ty>`.
1762
+ /// through a `*const/mut T` raw pointer if `arbitrary_self_types_pointers` is also enabled.
1763
+ /// If neither feature is enabled, the requirements are more strict: `receiver_ty` must implement
1764
+ /// `Receiver` and directly implement ` Deref<Target = self_ty>`.
1721
1765
///
1722
1766
/// N.B., there are cases this function returns `true` but causes an error to be emitted,
1723
1767
/// particularly when `receiver_ty` derefs to a type that is the same as `self_ty` but has the
@@ -1727,7 +1771,7 @@ fn receiver_is_valid<'tcx>(
1727
1771
span : Span ,
1728
1772
receiver_ty : Ty < ' tcx > ,
1729
1773
self_ty : Ty < ' tcx > ,
1730
- arbitrary_self_types_enabled : bool ,
1774
+ arbitrary_self_types_enabled : Option < ArbitrarySelfTypesLevel > ,
1731
1775
) -> bool {
1732
1776
let infcx = wfcx. infcx ;
1733
1777
let tcx = wfcx. tcx ( ) ;
@@ -1745,8 +1789,8 @@ fn receiver_is_valid<'tcx>(
1745
1789
1746
1790
let mut autoderef = Autoderef :: new ( infcx, wfcx. param_env , wfcx. body_def_id , span, receiver_ty) ;
1747
1791
1748
- // The `arbitrary_self_types ` feature allows raw pointer receivers like `self: *const Self`.
1749
- if arbitrary_self_types_enabled {
1792
+ // The `arbitrary_self_types_pointers ` feature allows raw pointer receivers like `self: *const Self`.
1793
+ if arbitrary_self_types_enabled == Some ( ArbitrarySelfTypesLevel :: WithPointers ) {
1750
1794
autoderef = autoderef. include_raw_pointers ( ) ;
1751
1795
}
1752
1796
@@ -1772,7 +1816,7 @@ fn receiver_is_valid<'tcx>(
1772
1816
1773
1817
// Without `feature(arbitrary_self_types)`, we require that each step in the
1774
1818
// deref chain implement `receiver`.
1775
- if ! arbitrary_self_types_enabled {
1819
+ if arbitrary_self_types_enabled. is_none ( ) {
1776
1820
if !receiver_is_implemented (
1777
1821
wfcx,
1778
1822
receiver_trait_def_id,
0 commit comments