Skip to content

Commit e4eec94

Browse files
committed
Arbitrary self types v2: stabilize! [WIP]
Do not merge any time soon - just to see what blows up in test suites when the old non-arbitrary-self-types paths are removed.
1 parent d743a1c commit e4eec94

File tree

13 files changed

+86
-222
lines changed

13 files changed

+86
-222
lines changed

compiler/rustc_feature/src/accepted.rs

+2
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,8 @@ declare_features! (
6060
(accepted, adx_target_feature, "1.61.0", Some(44839)),
6161
/// Allows explicit discriminants on non-unit enum variants.
6262
(accepted, arbitrary_enum_discriminant, "1.66.0", Some(60553)),
63+
/// Allows inherent and trait methods with arbitrary self types.
64+
(accepted, arbitrary_self_types, "CURRENT_RUSTC_VERSION", Some(44874)),
6365
/// Allows using `const` operands in inline assembly.
6466
(accepted, asm_const, "1.82.0", Some(93332)),
6567
/// Allows using `sym` operands in inline assembly.

compiler/rustc_feature/src/unstable.rs

-2
Original file line numberDiff line numberDiff line change
@@ -370,8 +370,6 @@ declare_features! (
370370
(unstable, adt_const_params, "1.56.0", Some(95174)),
371371
/// Allows defining an `#[alloc_error_handler]`.
372372
(unstable, alloc_error_handler, "1.29.0", Some(51540)),
373-
/// Allows inherent and trait methods with arbitrary self types.
374-
(unstable, arbitrary_self_types, "1.23.0", Some(44874)),
375373
/// Allows inherent and trait methods with arbitrary self types that are raw pointers.
376374
(unstable, arbitrary_self_types_pointers, "1.83.0", Some(44874)),
377375
/// Enables experimental inline assembly support for additional architectures.

compiler/rustc_hir/src/lang_items.rs

-1
Original file line numberDiff line numberDiff line change
@@ -243,7 +243,6 @@ language_item_table! {
243243
DerefTarget, sym::deref_target, deref_target, Target::AssocTy, GenericRequirement::None;
244244
Receiver, sym::receiver, receiver_trait, Target::Trait, GenericRequirement::None;
245245
ReceiverTarget, sym::receiver_target, receiver_target, Target::AssocTy, GenericRequirement::None;
246-
LegacyReceiver, sym::legacy_receiver, legacy_receiver_trait, Target::Trait, GenericRequirement::None;
247246

248247
Fn, kw::Fn, fn_trait, Target::Trait, GenericRequirement::Exact(1);
249248
FnMut, sym::fn_mut, fn_mut_trait, Target::Trait, GenericRequirement::Exact(1);

compiler/rustc_hir_analysis/src/check/wfcheck.rs

+24-124
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,6 @@ use rustc_trait_selection::traits::misc::{
3030
ConstParamTyImplementationError, type_allowed_to_implement_const_param_ty,
3131
};
3232
use rustc_trait_selection::traits::outlives_bounds::InferCtxtExt as _;
33-
use rustc_trait_selection::traits::query::evaluate_obligation::InferCtxtExt as _;
3433
use rustc_trait_selection::traits::{
3534
self, FulfillmentError, Obligation, ObligationCause, ObligationCauseCode, ObligationCtxt,
3635
WellFormedLoc,
@@ -1630,13 +1629,6 @@ fn check_fn_or_method<'tcx>(
16301629
}
16311630
}
16321631

1633-
/// The `arbitrary_self_types_pointers` feature implies `arbitrary_self_types`.
1634-
#[derive(Clone, Copy, PartialEq)]
1635-
enum ArbitrarySelfTypesLevel {
1636-
Basic, // just arbitrary_self_types
1637-
WithPointers, // both arbitrary_self_types and arbitrary_self_types_pointers
1638-
}
1639-
16401632
#[instrument(level = "debug", skip(wfcx))]
16411633
fn check_method_receiver<'tcx>(
16421634
wfcx: &WfCheckingCtxt<'_, 'tcx>,
@@ -1669,55 +1661,21 @@ fn check_method_receiver<'tcx>(
16691661
return Ok(());
16701662
}
16711663

1672-
let arbitrary_self_types_level = if tcx.features().arbitrary_self_types_pointers() {
1673-
Some(ArbitrarySelfTypesLevel::WithPointers)
1674-
} else if tcx.features().arbitrary_self_types() {
1675-
Some(ArbitrarySelfTypesLevel::Basic)
1676-
} else {
1677-
None
1678-
};
16791664
let generics = tcx.generics_of(method.def_id);
16801665

1681-
let receiver_validity =
1682-
receiver_is_valid(wfcx, span, receiver_ty, self_ty, arbitrary_self_types_level, generics);
1666+
let arbitrary_self_types_pointers_enabled = tcx.features().arbitrary_self_types_pointers();
1667+
let receiver_validity = receiver_is_valid(
1668+
wfcx,
1669+
span,
1670+
receiver_ty,
1671+
self_ty,
1672+
arbitrary_self_types_pointers_enabled,
1673+
generics,
1674+
);
16831675
if let Err(receiver_validity_err) = receiver_validity {
1684-
return Err(match arbitrary_self_types_level {
1685-
// Wherever possible, emit a message advising folks that the features
1686-
// `arbitrary_self_types` or `arbitrary_self_types_pointers` might
1687-
// have helped.
1688-
None if receiver_is_valid(
1689-
wfcx,
1690-
span,
1691-
receiver_ty,
1692-
self_ty,
1693-
Some(ArbitrarySelfTypesLevel::Basic),
1694-
generics,
1695-
)
1696-
.is_ok() =>
1697-
{
1698-
// Report error; would have worked with `arbitrary_self_types`.
1699-
feature_err(
1700-
&tcx.sess,
1701-
sym::arbitrary_self_types,
1702-
span,
1703-
format!(
1704-
"`{receiver_ty}` cannot be used as the type of `self` without \
1705-
the `arbitrary_self_types` feature",
1706-
),
1707-
)
1708-
.with_help(fluent::hir_analysis_invalid_receiver_ty_help)
1709-
.emit()
1710-
}
1711-
None | Some(ArbitrarySelfTypesLevel::Basic)
1712-
if receiver_is_valid(
1713-
wfcx,
1714-
span,
1715-
receiver_ty,
1716-
self_ty,
1717-
Some(ArbitrarySelfTypesLevel::WithPointers),
1718-
generics,
1719-
)
1720-
.is_ok() =>
1676+
return Err(
1677+
if !arbitrary_self_types_pointers_enabled
1678+
&& receiver_is_valid(wfcx, span, receiver_ty, self_ty, true, generics).is_ok()
17211679
{
17221680
// Report error; would have worked with `arbitrary_self_types_pointers`.
17231681
feature_err(
@@ -1726,15 +1684,13 @@ fn check_method_receiver<'tcx>(
17261684
span,
17271685
format!(
17281686
"`{receiver_ty}` cannot be used as the type of `self` without \
1729-
the `arbitrary_self_types_pointers` feature",
1687+
the `arbitrary_self_types_pointers` feature",
17301688
),
17311689
)
17321690
.with_help(fluent::hir_analysis_invalid_receiver_ty_help)
17331691
.emit()
1734-
}
1735-
_ =>
1736-
// Report error; would not have worked with `arbitrary_self_types[_pointers]`.
1737-
{
1692+
} else {
1693+
// Report error; would not have worked with `arbitrary_self_types[_pointers]`.
17381694
match receiver_validity_err {
17391695
ReceiverValidityError::DoesNotDeref => {
17401696
let hint = match receiver_ty
@@ -1748,7 +1704,7 @@ fn check_method_receiver<'tcx>(
17481704
wfcx,
17491705
span,
17501706
receiver_ty,
1751-
arbitrary_self_types_level,
1707+
arbitrary_self_types_pointers_enabled,
17521708
);
17531709
None
17541710
}
@@ -1760,8 +1716,8 @@ fn check_method_receiver<'tcx>(
17601716
tcx.dcx().emit_err(errors::InvalidGenericReceiverTy { span, receiver_ty })
17611717
}
17621718
}
1763-
}
1764-
});
1719+
},
1720+
);
17651721
}
17661722
Ok(())
17671723
}
@@ -1805,11 +1761,10 @@ fn receiver_is_valid<'tcx>(
18051761
span: Span,
18061762
receiver_ty: Ty<'tcx>,
18071763
self_ty: Ty<'tcx>,
1808-
arbitrary_self_types_enabled: Option<ArbitrarySelfTypesLevel>,
1764+
arbitrary_self_types_pointers_enabled: bool,
18091765
method_generics: &ty::Generics,
18101766
) -> Result<(), ReceiverValidityError> {
18111767
let infcx = wfcx.infcx;
1812-
let tcx = wfcx.tcx();
18131768
let cause =
18141769
ObligationCause::new(span, wfcx.body_def_id, traits::ObligationCauseCode::MethodReceiver);
18151770

@@ -1824,17 +1779,11 @@ fn receiver_is_valid<'tcx>(
18241779

18251780
confirm_type_is_not_a_method_generic_param(receiver_ty, method_generics)?;
18261781

1827-
let mut autoderef = Autoderef::new(infcx, wfcx.param_env, wfcx.body_def_id, span, receiver_ty);
1828-
1829-
// The `arbitrary_self_types` feature allows custom smart pointer
1830-
// types to be method receivers, as identified by following the Receiver<Target=T>
1831-
// chain.
1832-
if arbitrary_self_types_enabled.is_some() {
1833-
autoderef = autoderef.use_receiver_trait();
1834-
}
1782+
let mut autoderef = Autoderef::new(infcx, wfcx.param_env, wfcx.body_def_id, span, receiver_ty)
1783+
.use_receiver_trait();
18351784

18361785
// The `arbitrary_self_types_pointers` feature allows raw pointer receivers like `self: *const Self`.
1837-
if arbitrary_self_types_enabled == Some(ArbitrarySelfTypesLevel::WithPointers) {
1786+
if arbitrary_self_types_pointers_enabled {
18381787
autoderef = autoderef.include_raw_pointers();
18391788
}
18401789

@@ -1857,58 +1806,12 @@ fn receiver_is_valid<'tcx>(
18571806
wfcx.register_obligations(autoderef.into_obligations());
18581807
return Ok(());
18591808
}
1860-
1861-
// Without `feature(arbitrary_self_types)`, we require that each step in the
1862-
// deref chain implement `LegacyReceiver`.
1863-
if arbitrary_self_types_enabled.is_none() {
1864-
let legacy_receiver_trait_def_id =
1865-
tcx.require_lang_item(LangItem::LegacyReceiver, Some(span));
1866-
if !legacy_receiver_is_implemented(
1867-
wfcx,
1868-
legacy_receiver_trait_def_id,
1869-
cause.clone(),
1870-
potential_self_ty,
1871-
) {
1872-
// We cannot proceed.
1873-
break;
1874-
}
1875-
1876-
// Register the bound, in case it has any region side-effects.
1877-
wfcx.register_bound(
1878-
cause.clone(),
1879-
wfcx.param_env,
1880-
potential_self_ty,
1881-
legacy_receiver_trait_def_id,
1882-
);
1883-
}
18841809
}
18851810

18861811
debug!("receiver_is_valid: type `{:?}` does not deref to `{:?}`", receiver_ty, self_ty);
18871812
Err(ReceiverValidityError::DoesNotDeref)
18881813
}
18891814

1890-
fn legacy_receiver_is_implemented<'tcx>(
1891-
wfcx: &WfCheckingCtxt<'_, 'tcx>,
1892-
legacy_receiver_trait_def_id: DefId,
1893-
cause: ObligationCause<'tcx>,
1894-
receiver_ty: Ty<'tcx>,
1895-
) -> bool {
1896-
let tcx = wfcx.tcx();
1897-
let trait_ref = ty::TraitRef::new(tcx, legacy_receiver_trait_def_id, [receiver_ty]);
1898-
1899-
let obligation = Obligation::new(tcx, cause, wfcx.param_env, trait_ref);
1900-
1901-
if wfcx.infcx.predicate_must_hold_modulo_regions(&obligation) {
1902-
true
1903-
} else {
1904-
debug!(
1905-
"receiver_is_implemented: type `{:?}` does not implement `LegacyReceiver` trait",
1906-
receiver_ty
1907-
);
1908-
false
1909-
}
1910-
}
1911-
19121815
/// Determine whether it _would have_ been possible to use `receiver_ty` as
19131816
/// a self type if it had been `Sized`, so we can show a specialized diagnostic.
19141817
/// This is because it's an easy mistake to `impl<T> Receiver` instead of
@@ -1917,16 +1820,13 @@ fn emit_receiver_not_implemented_errors<'tcx>(
19171820
wfcx: &WfCheckingCtxt<'_, 'tcx>,
19181821
span: Span,
19191822
receiver_ty: Ty<'tcx>,
1920-
arbitrary_self_types_enabled: Option<ArbitrarySelfTypesLevel>,
1823+
arbitrary_self_types_pointers_enabled: bool,
19211824
) {
19221825
let infcx = wfcx.infcx;
19231826
let mut autoderef = Autoderef::new(infcx, wfcx.param_env, wfcx.body_def_id, span, receiver_ty)
19241827
.use_receiver_trait();
19251828

1926-
if arbitrary_self_types_enabled.is_some() {
1927-
autoderef = autoderef.use_receiver_trait();
1928-
}
1929-
if arbitrary_self_types_enabled == Some(ArbitrarySelfTypesLevel::WithPointers) {
1829+
if arbitrary_self_types_pointers_enabled {
19301830
autoderef = autoderef.include_raw_pointers();
19311831
}
19321832

compiler/rustc_hir_typeck/src/method/confirm.rs

+3-18
Original file line numberDiff line numberDiff line change
@@ -531,24 +531,9 @@ impl<'a, 'tcx> ConfirmContext<'a, 'tcx> {
531531
self.register_predicates(obligations);
532532
}
533533
Err(terr) => {
534-
if self.tcx.features().arbitrary_self_types() {
535-
self.err_ctxt()
536-
.report_mismatched_types(
537-
&cause,
538-
self.param_env,
539-
method_self_ty,
540-
self_ty,
541-
terr,
542-
)
543-
.emit();
544-
} else {
545-
// This has/will have errored in wfcheck, which we cannot depend on from here, as typeck on functions
546-
// may run before wfcheck if the function is used in const eval.
547-
self.dcx().span_delayed_bug(
548-
cause.span,
549-
format!("{self_ty} was a subtype of {method_self_ty} but now is not?"),
550-
);
551-
}
534+
self.err_ctxt()
535+
.report_mismatched_types(&cause, self.param_env, method_self_ty, self_ty, terr)
536+
.emit();
552537
}
553538
}
554539
}

0 commit comments

Comments
 (0)