Skip to content

Commit f16fc5b

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 4b2ad13 commit f16fc5b

File tree

13 files changed

+87
-216
lines changed

13 files changed

+87
-216
lines changed

Diff for: 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.

Diff for: 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.

Diff for: 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);

Diff for: compiler/rustc_hir_analysis/src/check/wfcheck.rs

+21-118
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,
@@ -1629,13 +1628,6 @@ fn check_fn_or_method<'tcx>(
16291628
}
16301629
}
16311630

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

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

16801665
// yet to do: determine whether self_ty is Sized. If not (most commonly
@@ -1687,46 +1672,19 @@ fn check_method_receiver<'tcx>(
16871672
// exist for this.
16881673
let raw_pointer = is_raw_pointer(receiver_ty);
16891674

1690-
let receiver_validity =
1691-
receiver_is_valid(wfcx, span, receiver_ty, self_ty, arbitrary_self_types_level, generics);
1675+
let arbitrary_self_types_pointers_enabled = tcx.features().arbitrary_self_types_pointers();
1676+
let receiver_validity = receiver_is_valid(
1677+
wfcx,
1678+
span,
1679+
receiver_ty,
1680+
self_ty,
1681+
arbitrary_self_types_pointers_enabled,
1682+
generics,
1683+
);
16921684
if let Err(receiver_validity_err) = receiver_validity {
1693-
return Err(match arbitrary_self_types_level {
1694-
// Wherever possible, emit a message advising folks that the features
1695-
// `arbitrary_self_types` or `arbitrary_self_types_pointers` might
1696-
// have helped.
1697-
None if receiver_is_valid(
1698-
wfcx,
1699-
span,
1700-
receiver_ty,
1701-
self_ty,
1702-
Some(ArbitrarySelfTypesLevel::Basic),
1703-
generics,
1704-
)
1705-
.is_ok() =>
1706-
{
1707-
// Report error; would have worked with `arbitrary_self_types`.
1708-
feature_err(
1709-
&tcx.sess,
1710-
sym::arbitrary_self_types,
1711-
span,
1712-
format!(
1713-
"`{receiver_ty}` cannot be used as the type of `self` without \
1714-
the `arbitrary_self_types` feature",
1715-
),
1716-
)
1717-
.with_help(fluent::hir_analysis_invalid_receiver_ty_help)
1718-
.emit()
1719-
}
1720-
None | Some(ArbitrarySelfTypesLevel::Basic)
1721-
if receiver_is_valid(
1722-
wfcx,
1723-
span,
1724-
receiver_ty,
1725-
self_ty,
1726-
Some(ArbitrarySelfTypesLevel::WithPointers),
1727-
generics,
1728-
)
1729-
.is_ok() =>
1685+
return Err(
1686+
if !arbitrary_self_types_pointers_enabled
1687+
&& receiver_is_valid(wfcx, span, receiver_ty, self_ty, true, generics).is_ok()
17301688
{
17311689
// Report error; would have worked with `arbitrary_self_types_pointers`.
17321690
feature_err(
@@ -1735,15 +1693,13 @@ fn check_method_receiver<'tcx>(
17351693
span,
17361694
format!(
17371695
"`{receiver_ty}` cannot be used as the type of `self` without \
1738-
the `arbitrary_self_types_pointers` feature",
1696+
the `arbitrary_self_types_pointers` feature",
17391697
),
17401698
)
17411699
.with_help(fluent::hir_analysis_invalid_receiver_ty_help)
17421700
.emit()
1743-
}
1744-
_ =>
1745-
// Report error; would not have worked with `arbitrary_self_types[_pointers]`.
1746-
{
1701+
} else {
1702+
// Report error; would not have worked with `arbitrary_self_types[_pointers]`.
17471703
match receiver_validity_err {
17481704
ReceiverValidityError::DoesNotDeref => tcx
17491705
.dcx()
@@ -1752,8 +1708,8 @@ fn check_method_receiver<'tcx>(
17521708
tcx.dcx().emit_err(errors::InvalidGenericReceiverTy { span, receiver_ty })
17531709
}
17541710
}
1755-
}
1756-
});
1711+
},
1712+
);
17571713
}
17581714
Ok(())
17591715
}
@@ -1801,11 +1757,10 @@ fn receiver_is_valid<'tcx>(
18011757
span: Span,
18021758
receiver_ty: Ty<'tcx>,
18031759
self_ty: Ty<'tcx>,
1804-
arbitrary_self_types_enabled: Option<ArbitrarySelfTypesLevel>,
1760+
arbitrary_self_types_pointers_enabled: bool,
18051761
method_generics: &ty::Generics,
18061762
) -> Result<(), ReceiverValidityError> {
18071763
let infcx = wfcx.infcx;
1808-
let tcx = wfcx.tcx();
18091764
let cause =
18101765
ObligationCause::new(span, wfcx.body_def_id, traits::ObligationCauseCode::MethodReceiver);
18111766

@@ -1820,17 +1775,11 @@ fn receiver_is_valid<'tcx>(
18201775

18211776
confirm_type_is_not_a_method_generic_param(receiver_ty, method_generics)?;
18221777

1823-
let mut autoderef = Autoderef::new(infcx, wfcx.param_env, wfcx.body_def_id, span, receiver_ty);
1824-
1825-
// The `arbitrary_self_types` feature allows custom smart pointer
1826-
// types to be method receivers, as identified by following the Receiver<Target=T>
1827-
// chain.
1828-
if arbitrary_self_types_enabled.is_some() {
1829-
autoderef = autoderef.use_receiver_trait();
1830-
}
1778+
let mut autoderef = Autoderef::new(infcx, wfcx.param_env, wfcx.body_def_id, span, receiver_ty)
1779+
.use_receiver_trait();
18311780

18321781
// The `arbitrary_self_types_pointers` feature allows raw pointer receivers like `self: *const Self`.
1833-
if arbitrary_self_types_enabled == Some(ArbitrarySelfTypesLevel::WithPointers) {
1782+
if arbitrary_self_types_pointers_enabled {
18341783
autoderef = autoderef.include_raw_pointers();
18351784
}
18361785

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

18821807
debug!("receiver_is_valid: type `{:?}` does not deref to `{:?}`", receiver_ty, self_ty);
18831808
Err(ReceiverValidityError::DoesNotDeref)
18841809
}
18851810

1886-
fn legacy_receiver_is_implemented<'tcx>(
1887-
wfcx: &WfCheckingCtxt<'_, 'tcx>,
1888-
legacy_receiver_trait_def_id: DefId,
1889-
cause: ObligationCause<'tcx>,
1890-
receiver_ty: Ty<'tcx>,
1891-
) -> bool {
1892-
let tcx = wfcx.tcx();
1893-
let trait_ref = ty::TraitRef::new(tcx, legacy_receiver_trait_def_id, [receiver_ty]);
1894-
1895-
let obligation = Obligation::new(tcx, cause, wfcx.param_env, trait_ref);
1896-
1897-
if wfcx.infcx.predicate_must_hold_modulo_regions(&obligation) {
1898-
true
1899-
} else {
1900-
debug!(
1901-
"receiver_is_implemented: type `{:?}` does not implement `LegacyReceiver` trait",
1902-
receiver_ty
1903-
);
1904-
false
1905-
}
1906-
}
1907-
19081811
fn check_variances_for_type_defn<'tcx>(
19091812
tcx: TyCtxt<'tcx>,
19101813
item: &'tcx hir::Item<'tcx>,

Diff for: 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
}

Diff for: compiler/rustc_hir_typeck/src/method/probe.rs

+28-63
Original file line numberDiff line numberDiff line change
@@ -476,7 +476,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
476476
let guar = match *ty.kind() {
477477
ty::Infer(ty::TyVar(_)) => {
478478
let raw_ptr_call = bad_ty.reached_raw_pointer
479-
&& !self.tcx.features().arbitrary_self_types();
479+
&& !self.tcx.features().arbitrary_self_types_pointers();
480480
let mut err = self.err_ctxt().emit_inference_failure_err(
481481
self.body_id,
482482
span,
@@ -562,73 +562,38 @@ fn method_autoderef_steps<'tcx>(
562562
let (ref infcx, goal, inference_vars) = tcx.infer_ctxt().build_with_canonical(DUMMY_SP, &goal);
563563
let ParamEnvAnd { param_env, value: self_ty } = goal;
564564

565-
// If arbitrary self types is not enabled, we follow the chain of
566-
// `Deref<Target=T>`. If arbitrary self types is enabled, we instead
567-
// follow the chain of `Receiver<Target=T>`, but we also record whether
568-
// such types are reachable by following the (potentially shorter)
569-
// chain of `Deref<Target=T>`. We will use the first list when finding
570-
// potentially relevant function implementations (e.g. relevant impl blocks)
571-
// but the second list when determining types that the receiver may be
572-
// converted to, in order to find out which of those methods might actually
573-
// be callable.
574565
let mut autoderef_via_deref =
575566
Autoderef::new(infcx, param_env, hir::def_id::CRATE_DEF_ID, DUMMY_SP, self_ty)
576567
.include_raw_pointers()
577568
.silence_errors();
578569

570+
let mut autoderef_via_receiver =
571+
Autoderef::new(infcx, param_env, hir::def_id::CRATE_DEF_ID, DUMMY_SP, self_ty)
572+
.include_raw_pointers()
573+
.use_receiver_trait()
574+
.silence_errors();
575+
579576
let mut reached_raw_pointer = false;
580-
let arbitrary_self_types_enabled =
581-
tcx.features().arbitrary_self_types() || tcx.features().arbitrary_self_types_pointers();
582-
let (mut steps, reached_recursion_limit): (Vec<_>, bool) = if arbitrary_self_types_enabled {
583-
let reachable_via_deref =
584-
autoderef_via_deref.by_ref().map(|_| true).chain(std::iter::repeat(false));
585-
586-
let mut autoderef_via_receiver =
587-
Autoderef::new(infcx, param_env, hir::def_id::CRATE_DEF_ID, DUMMY_SP, self_ty)
588-
.include_raw_pointers()
589-
.use_receiver_trait()
590-
.silence_errors();
591-
let steps = autoderef_via_receiver
592-
.by_ref()
593-
.zip(reachable_via_deref)
594-
.map(|((ty, d), reachable_via_deref)| {
595-
let step = CandidateStep {
596-
self_ty: infcx
597-
.make_query_response_ignoring_pending_obligations(inference_vars, ty),
598-
autoderefs: d,
599-
from_unsafe_deref: reached_raw_pointer,
600-
unsize: false,
601-
reachable_via_deref,
602-
};
603-
if let ty::RawPtr(_, _) = ty.kind() {
604-
// all the subsequent steps will be from_unsafe_deref
605-
reached_raw_pointer = true;
606-
}
607-
step
608-
})
609-
.collect();
610-
(steps, autoderef_via_receiver.reached_recursion_limit())
611-
} else {
612-
let steps = autoderef_via_deref
613-
.by_ref()
614-
.map(|(ty, d)| {
615-
let step = CandidateStep {
616-
self_ty: infcx
617-
.make_query_response_ignoring_pending_obligations(inference_vars, ty),
618-
autoderefs: d,
619-
from_unsafe_deref: reached_raw_pointer,
620-
unsize: false,
621-
reachable_via_deref: true,
622-
};
623-
if let ty::RawPtr(_, _) = ty.kind() {
624-
// all the subsequent steps will be from_unsafe_deref
625-
reached_raw_pointer = true;
626-
}
627-
step
628-
})
629-
.collect();
630-
(steps, autoderef_via_deref.reached_recursion_limit())
631-
};
577+
let reachable_via_deref =
578+
autoderef_via_deref.by_ref().map(|_| true).chain(std::iter::repeat(false));
579+
let mut steps: Vec<_> = autoderef_via_receiver
580+
.by_ref()
581+
.zip(reachable_via_deref)
582+
.map(|((ty, d), reachable_via_deref)| {
583+
let step = CandidateStep {
584+
self_ty: infcx.make_query_response_ignoring_pending_obligations(inference_vars, ty),
585+
autoderefs: d,
586+
from_unsafe_deref: reached_raw_pointer,
587+
unsize: false,
588+
reachable_via_deref,
589+
};
590+
if let ty::RawPtr(_, _) = ty.kind() {
591+
// all the subsequent steps will be from_unsafe_deref
592+
reached_raw_pointer = true;
593+
}
594+
step
595+
})
596+
.collect();
632597
let final_ty = autoderef_via_deref.final_ty(true);
633598
let opt_bad_ty = match final_ty.kind() {
634599
ty::Infer(ty::TyVar(_)) | ty::Error(_) => Some(MethodAutoderefBadTy {
@@ -661,7 +626,7 @@ fn method_autoderef_steps<'tcx>(
661626
MethodAutoderefStepsResult {
662627
steps: tcx.arena.alloc_from_iter(steps),
663628
opt_bad_ty: opt_bad_ty.map(|ty| &*tcx.arena.alloc(ty)),
664-
reached_recursion_limit,
629+
reached_recursion_limit: autoderef_via_receiver.reached_recursion_limit(),
665630
}
666631
}
667632

0 commit comments

Comments
 (0)