Skip to content

Commit 497397a

Browse files
committed
initial implementation of arbitrary_self_types
If the feature is enabled, allow method `self` types to be any type that auto-derefs to `self`. - Currently, this supports inherent methods as well as trait methods. The plan AFAIK is to only allow this for trait methods, so I guess it won’t stay this way - Dynamic dispatch isn’t implemented yet, so the compiler will ICE if you define a trait method that takes `self: Rc<Self>` and try to call it on an `Rc<Trait>`. I will probably just make those methods non-object-safe initially.
1 parent edc8c76 commit 497397a

File tree

3 files changed

+27
-0
lines changed

3 files changed

+27
-0
lines changed

src/librustc_typeck/check/wfcheck.rs

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -469,6 +469,29 @@ impl<'a, 'gcx> CheckTypeWellFormedVisitor<'a, 'gcx> {
469469
debug!("check_method_receiver: sig={:?}", sig);
470470

471471
let self_arg_ty = sig.inputs()[0];
472+
473+
if fcx.tcx.sess.features.borrow().arbitrary_self_types {
474+
let cause = fcx.cause(span, ObligationCauseCode::MethodReceiver);
475+
476+
let mut autoderef = fcx.autoderef(span, self_arg_ty);
477+
while let Some((potential_self_ty, _)) = autoderef.next() {
478+
debug!("check_method_receiver: potential self type `{:?}` to match `{:?}`", potential_self_ty, self_ty);
479+
480+
// there's gotta be a more idiomatic way of checking if types are equal than this
481+
if let Some(mut err) = fcx.demand_eqtype_with_origin(&cause, self_ty, potential_self_ty) {
482+
err.cancel();
483+
continue;
484+
} else {
485+
// we found a type that matches `self_ty`
486+
autoderef.finalize();
487+
return;
488+
}
489+
}
490+
491+
span_err!(fcx.tcx.sess, span, E0307, "invalid `self` type: {:?}", self_arg_ty);
492+
return;
493+
}
494+
472495
let rcvr_ty = match ExplicitSelf::determine(self_ty, self_arg_ty) {
473496
ExplicitSelf::ByValue => self_ty,
474497
ExplicitSelf::ByReference(region, mutbl) => {

src/librustc_typeck/diagnostics.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4724,6 +4724,7 @@ register_diagnostics! {
47244724
// E0247,
47254725
// E0248, // value used as a type, now reported earlier during resolution as E0412
47264726
// E0249,
4727+
E0307, // invalid method `self` type
47274728
// E0319, // trait impls for defaulted traits allowed just for structs/enums
47284729
// E0372, // coherence not object safe
47294730
E0377, // the trait `CoerceUnsized` may only be implemented for a coercion

src/libsyntax/feature_gate.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -409,6 +409,9 @@ declare_features! (
409409

410410
// extern types
411411
(active, extern_types, "1.23.0", Some(43467)),
412+
413+
// Allow trait methods with arbitrary self types
414+
(active, arbitrary_self_types, "1.23.0", Some(44874)),
412415
);
413416

414417
declare_features! (

0 commit comments

Comments
 (0)