Skip to content

Commit 6733334

Browse files
committed
Arbitrary self types v2: stabilize! [WIP]
1 parent 5958825 commit 6733334

File tree

15 files changed

+88
-248
lines changed

15 files changed

+88
-248
lines changed

compiler/rustc_feature/src/accepted.rs

Lines changed: 2 additions & 0 deletions
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

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -373,8 +373,6 @@ declare_features! (
373373
(unstable, adt_const_params, "1.56.0", Some(95174)),
374374
/// Allows defining an `#[alloc_error_handler]`.
375375
(unstable, alloc_error_handler, "1.29.0", Some(51540)),
376-
/// Allows inherent and trait methods with arbitrary self types.
377-
(unstable, arbitrary_self_types, "1.23.0", Some(44874)),
378376
/// Allows inherent and trait methods with arbitrary self types that are raw pointers.
379377
(unstable, arbitrary_self_types_pointers, "1.83.0", Some(44874)),
380378
/// Enables experimental inline assembly support for additional architectures.

compiler/rustc_hir/src/lang_items.rs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -242,7 +242,6 @@ language_item_table! {
242242
DerefTarget, sym::deref_target, deref_target, Target::AssocTy, GenericRequirement::None;
243243
Receiver, sym::receiver, receiver_trait, Target::Trait, GenericRequirement::None;
244244
ReceiverTarget, sym::receiver_target, receiver_target, Target::AssocTy, GenericRequirement::None;
245-
LegacyReceiver, sym::legacy_receiver, legacy_receiver_trait, Target::Trait, GenericRequirement::None;
246245

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

compiler/rustc_hir_analysis/messages.ftl

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -249,18 +249,12 @@ hir_analysis_invalid_receiver_ty = invalid `self` parameter type: `{$receiver_ty
249249
hir_analysis_invalid_receiver_ty_help =
250250
consider changing to `self`, `&self`, `&mut self`, or a type implementing `Receiver` such as `self: Box<Self>`, `self: Rc<Self>`, or `self: Arc<Self>`
251251
252-
hir_analysis_invalid_receiver_ty_help_no_arbitrary_self_types =
253-
consider changing to `self`, `&self`, `&mut self`, `self: Box<Self>`, `self: Rc<Self>`, `self: Arc<Self>`, or `self: Pin<P>` (where P is one of the previous types except `Self`)
254-
255252
hir_analysis_invalid_receiver_ty_help_nonnull_note =
256253
`NonNull` does not implement `Receiver` because it has methods that may shadow the referent; consider wrapping your `NonNull` in a newtype wrapper for which you implement `Receiver`
257254
258255
hir_analysis_invalid_receiver_ty_help_weak_note =
259256
`Weak` does not implement `Receiver` because it has methods that may shadow the referent; consider wrapping your `Weak` in a newtype wrapper for which you implement `Receiver`
260257
261-
hir_analysis_invalid_receiver_ty_no_arbitrary_self_types = invalid `self` parameter type: `{$receiver_ty}`
262-
.note = type of `self` must be `Self` or a type that dereferences to it
263-
264258
hir_analysis_invalid_union_field =
265259
field must implement `Copy` or be wrapped in `ManuallyDrop<...>` to be used in a union
266260
.note = union fields must not have drop side-effects, which is currently enforced via either `Copy` or `ManuallyDrop<...>`

compiler/rustc_hir_analysis/src/check/wfcheck.rs

Lines changed: 22 additions & 125 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,6 @@ use rustc_trait_selection::regions::{InferCtxtRegionExt, OutlivesEnvironmentBuil
2929
use rustc_trait_selection::traits::misc::{
3030
ConstParamTyImplementationError, type_allowed_to_implement_const_param_ty,
3131
};
32-
use rustc_trait_selection::traits::query::evaluate_obligation::InferCtxtExt as _;
3332
use rustc_trait_selection::traits::{
3433
self, FulfillmentError, Obligation, ObligationCause, ObligationCauseCode, ObligationCtxt,
3534
WellFormedLoc,
@@ -1672,13 +1671,6 @@ fn check_sized_if_body<'tcx>(
16721671
}
16731672
}
16741673

1675-
/// The `arbitrary_self_types_pointers` feature implies `arbitrary_self_types`.
1676-
#[derive(Clone, Copy, PartialEq)]
1677-
enum ArbitrarySelfTypesLevel {
1678-
Basic, // just arbitrary_self_types
1679-
WithPointers, // both arbitrary_self_types and arbitrary_self_types_pointers
1680-
}
1681-
16821674
#[instrument(level = "debug", skip(wfcx))]
16831675
fn check_method_receiver<'tcx>(
16841676
wfcx: &WfCheckingCtxt<'_, 'tcx>,
@@ -1711,55 +1703,21 @@ fn check_method_receiver<'tcx>(
17111703
return Ok(());
17121704
}
17131705

1714-
let arbitrary_self_types_level = if tcx.features().arbitrary_self_types_pointers() {
1715-
Some(ArbitrarySelfTypesLevel::WithPointers)
1716-
} else if tcx.features().arbitrary_self_types() {
1717-
Some(ArbitrarySelfTypesLevel::Basic)
1718-
} else {
1719-
None
1720-
};
17211706
let generics = tcx.generics_of(method.def_id);
17221707

1723-
let receiver_validity =
1724-
receiver_is_valid(wfcx, span, receiver_ty, self_ty, arbitrary_self_types_level, generics);
1708+
let arbitrary_self_types_pointers_enabled = tcx.features().arbitrary_self_types_pointers();
1709+
let receiver_validity = receiver_is_valid(
1710+
wfcx,
1711+
span,
1712+
receiver_ty,
1713+
self_ty,
1714+
arbitrary_self_types_pointers_enabled,
1715+
generics,
1716+
);
17251717
if let Err(receiver_validity_err) = receiver_validity {
1726-
return Err(match arbitrary_self_types_level {
1727-
// Wherever possible, emit a message advising folks that the features
1728-
// `arbitrary_self_types` or `arbitrary_self_types_pointers` might
1729-
// have helped.
1730-
None if receiver_is_valid(
1731-
wfcx,
1732-
span,
1733-
receiver_ty,
1734-
self_ty,
1735-
Some(ArbitrarySelfTypesLevel::Basic),
1736-
generics,
1737-
)
1738-
.is_ok() =>
1739-
{
1740-
// Report error; would have worked with `arbitrary_self_types`.
1741-
feature_err(
1742-
&tcx.sess,
1743-
sym::arbitrary_self_types,
1744-
span,
1745-
format!(
1746-
"`{receiver_ty}` cannot be used as the type of `self` without \
1747-
the `arbitrary_self_types` feature",
1748-
),
1749-
)
1750-
.with_help(fluent::hir_analysis_invalid_receiver_ty_help)
1751-
.emit()
1752-
}
1753-
None | Some(ArbitrarySelfTypesLevel::Basic)
1754-
if receiver_is_valid(
1755-
wfcx,
1756-
span,
1757-
receiver_ty,
1758-
self_ty,
1759-
Some(ArbitrarySelfTypesLevel::WithPointers),
1760-
generics,
1761-
)
1762-
.is_ok() =>
1718+
return Err(
1719+
if !arbitrary_self_types_pointers_enabled
1720+
&& receiver_is_valid(wfcx, span, receiver_ty, self_ty, true, generics).is_ok()
17631721
{
17641722
// Report error; would have worked with `arbitrary_self_types_pointers`.
17651723
feature_err(
@@ -1768,17 +1726,15 @@ fn check_method_receiver<'tcx>(
17681726
span,
17691727
format!(
17701728
"`{receiver_ty}` cannot be used as the type of `self` without \
1771-
the `arbitrary_self_types_pointers` feature",
1729+
the `arbitrary_self_types_pointers` feature",
17721730
),
17731731
)
17741732
.with_help(fluent::hir_analysis_invalid_receiver_ty_help)
17751733
.emit()
1776-
}
1777-
_ =>
1778-
// Report error; would not have worked with `arbitrary_self_types[_pointers]`.
1779-
{
1734+
} else {
1735+
// Report error; would not have worked with `arbitrary_self_types_pointers`.
17801736
match receiver_validity_err {
1781-
ReceiverValidityError::DoesNotDeref if arbitrary_self_types_level.is_some() => {
1737+
ReceiverValidityError::DoesNotDeref => {
17821738
let hint = match receiver_ty
17831739
.builtin_deref(false)
17841740
.unwrap_or(receiver_ty)
@@ -1792,18 +1748,12 @@ fn check_method_receiver<'tcx>(
17921748

17931749
tcx.dcx().emit_err(errors::InvalidReceiverTy { span, receiver_ty, hint })
17941750
}
1795-
ReceiverValidityError::DoesNotDeref => {
1796-
tcx.dcx().emit_err(errors::InvalidReceiverTyNoArbitrarySelfTypes {
1797-
span,
1798-
receiver_ty,
1799-
})
1800-
}
18011751
ReceiverValidityError::MethodGenericParamUsed => {
18021752
tcx.dcx().emit_err(errors::InvalidGenericReceiverTy { span, receiver_ty })
18031753
}
18041754
}
1805-
}
1806-
});
1755+
},
1756+
);
18071757
}
18081758
Ok(())
18091759
}
@@ -1847,11 +1797,10 @@ fn receiver_is_valid<'tcx>(
18471797
span: Span,
18481798
receiver_ty: Ty<'tcx>,
18491799
self_ty: Ty<'tcx>,
1850-
arbitrary_self_types_enabled: Option<ArbitrarySelfTypesLevel>,
1800+
arbitrary_self_types_pointers_enabled: bool,
18511801
method_generics: &ty::Generics,
18521802
) -> Result<(), ReceiverValidityError> {
18531803
let infcx = wfcx.infcx;
1854-
let tcx = wfcx.tcx();
18551804
let cause =
18561805
ObligationCause::new(span, wfcx.body_def_id, traits::ObligationCauseCode::MethodReceiver);
18571806

@@ -1866,17 +1815,11 @@ fn receiver_is_valid<'tcx>(
18661815

18671816
confirm_type_is_not_a_method_generic_param(receiver_ty, method_generics)?;
18681817

1869-
let mut autoderef = Autoderef::new(infcx, wfcx.param_env, wfcx.body_def_id, span, receiver_ty);
1870-
1871-
// The `arbitrary_self_types` feature allows custom smart pointer
1872-
// types to be method receivers, as identified by following the Receiver<Target=T>
1873-
// chain.
1874-
if arbitrary_self_types_enabled.is_some() {
1875-
autoderef = autoderef.use_receiver_trait();
1876-
}
1818+
let mut autoderef = Autoderef::new(infcx, wfcx.param_env, wfcx.body_def_id, span, receiver_ty)
1819+
.use_receiver_trait();
18771820

18781821
// The `arbitrary_self_types_pointers` feature allows raw pointer receivers like `self: *const Self`.
1879-
if arbitrary_self_types_enabled == Some(ArbitrarySelfTypesLevel::WithPointers) {
1822+
if arbitrary_self_types_pointers_enabled {
18801823
autoderef = autoderef.include_raw_pointers();
18811824
}
18821825

@@ -1899,58 +1842,12 @@ fn receiver_is_valid<'tcx>(
18991842
wfcx.register_obligations(autoderef.into_obligations());
19001843
return Ok(());
19011844
}
1902-
1903-
// Without `feature(arbitrary_self_types)`, we require that each step in the
1904-
// deref chain implement `LegacyReceiver`.
1905-
if arbitrary_self_types_enabled.is_none() {
1906-
let legacy_receiver_trait_def_id =
1907-
tcx.require_lang_item(LangItem::LegacyReceiver, Some(span));
1908-
if !legacy_receiver_is_implemented(
1909-
wfcx,
1910-
legacy_receiver_trait_def_id,
1911-
cause.clone(),
1912-
potential_self_ty,
1913-
) {
1914-
// We cannot proceed.
1915-
break;
1916-
}
1917-
1918-
// Register the bound, in case it has any region side-effects.
1919-
wfcx.register_bound(
1920-
cause.clone(),
1921-
wfcx.param_env,
1922-
potential_self_ty,
1923-
legacy_receiver_trait_def_id,
1924-
);
1925-
}
19261845
}
19271846

19281847
debug!("receiver_is_valid: type `{:?}` does not deref to `{:?}`", receiver_ty, self_ty);
19291848
Err(ReceiverValidityError::DoesNotDeref)
19301849
}
19311850

1932-
fn legacy_receiver_is_implemented<'tcx>(
1933-
wfcx: &WfCheckingCtxt<'_, 'tcx>,
1934-
legacy_receiver_trait_def_id: DefId,
1935-
cause: ObligationCause<'tcx>,
1936-
receiver_ty: Ty<'tcx>,
1937-
) -> bool {
1938-
let tcx = wfcx.tcx();
1939-
let trait_ref = ty::TraitRef::new(tcx, legacy_receiver_trait_def_id, [receiver_ty]);
1940-
1941-
let obligation = Obligation::new(tcx, cause, wfcx.param_env, trait_ref);
1942-
1943-
if wfcx.infcx.predicate_must_hold_modulo_regions(&obligation) {
1944-
true
1945-
} else {
1946-
debug!(
1947-
"receiver_is_implemented: type `{:?}` does not implement `LegacyReceiver` trait",
1948-
receiver_ty
1949-
);
1950-
false
1951-
}
1952-
}
1953-
19541851
fn check_variances_for_type_defn<'tcx>(
19551852
tcx: TyCtxt<'tcx>,
19561853
item: &'tcx hir::Item<'tcx>,

compiler/rustc_hir_analysis/src/errors.rs

Lines changed: 0 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1613,16 +1613,6 @@ pub(crate) enum InvalidReceiverTyHint {
16131613
NonNull,
16141614
}
16151615

1616-
#[derive(Diagnostic)]
1617-
#[diag(hir_analysis_invalid_receiver_ty_no_arbitrary_self_types, code = E0307)]
1618-
#[note]
1619-
#[help(hir_analysis_invalid_receiver_ty_help_no_arbitrary_self_types)]
1620-
pub(crate) struct InvalidReceiverTyNoArbitrarySelfTypes<'tcx> {
1621-
#[primary_span]
1622-
pub span: Span,
1623-
pub receiver_ty: Ty<'tcx>,
1624-
}
1625-
16261616
#[derive(Diagnostic)]
16271617
#[diag(hir_analysis_invalid_receiver_ty, code = E0307)]
16281618
#[note]

compiler/rustc_hir_typeck/src/method/confirm.rs

Lines changed: 3 additions & 18 deletions
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)