@@ -1652,6 +1652,13 @@ fn check_fn_or_method<'tcx>(
16521652 }
16531653}
16541654
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+
16551662#[ instrument( level = "debug" , skip( wfcx) ) ]
16561663fn check_method_receiver < ' tcx > (
16571664 wfcx : & WfCheckingCtxt < ' _ , ' tcx > ,
@@ -1684,40 +1691,77 @@ fn check_method_receiver<'tcx>(
16841691 return Ok ( ( ) ) ;
16851692 }
16861693
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 )
16921698 } 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+ {
16951715 // Report error; would have worked with `arbitrary_self_types`.
16961716 feature_err (
16971717 & tcx. sess ,
16981718 sym:: arbitrary_self_types,
16991719 span,
17001720 format ! (
17011721 "`{receiver_ty}` cannot be used as the type of `self` without \
1702- the `arbitrary_self_types` feature",
1722+ the `arbitrary_self_types` feature",
17031723 ) ,
17041724 )
17051725 . with_help ( fluent:: hir_analysis_invalid_receiver_ty_help)
17061726 . 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+ {
17091753 tcx. dcx ( ) . emit_err ( errors:: InvalidReceiverTy { span, receiver_ty } )
1710- } ) ;
1711- }
1754+ }
1755+ } ) ;
17121756 }
17131757 Ok ( ( ) )
17141758}
17151759
17161760/// Returns whether `receiver_ty` would be considered a valid receiver type for `self_ty`. If
17171761/// `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>`.
17211765///
17221766/// N.B., there are cases this function returns `true` but causes an error to be emitted,
17231767/// 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>(
17271771 span : Span ,
17281772 receiver_ty : Ty < ' tcx > ,
17291773 self_ty : Ty < ' tcx > ,
1730- arbitrary_self_types_enabled : bool ,
1774+ arbitrary_self_types_enabled : Option < ArbitrarySelfTypesLevel > ,
17311775) -> bool {
17321776 let infcx = wfcx. infcx ;
17331777 let tcx = wfcx. tcx ( ) ;
@@ -1745,8 +1789,8 @@ fn receiver_is_valid<'tcx>(
17451789
17461790 let mut autoderef = Autoderef :: new ( infcx, wfcx. param_env , wfcx. body_def_id , span, receiver_ty) ;
17471791
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 ) {
17501794 autoderef = autoderef. include_raw_pointers ( ) ;
17511795 }
17521796
@@ -1772,7 +1816,7 @@ fn receiver_is_valid<'tcx>(
17721816
17731817 // Without `feature(arbitrary_self_types)`, we require that each step in the
17741818 // deref chain implement `receiver`.
1775- if ! arbitrary_self_types_enabled {
1819+ if arbitrary_self_types_enabled. is_none ( ) {
17761820 if !receiver_is_implemented (
17771821 wfcx,
17781822 receiver_trait_def_id,
0 commit comments