diff options
| -rw-r--r-- | src/librustc_typeck/check/wfcheck.rs | 23 | ||||
| -rw-r--r-- | src/librustc_typeck/diagnostics.rs | 1 | ||||
| -rw-r--r-- | src/libsyntax/feature_gate.rs | 3 |
3 files changed, 27 insertions, 0 deletions
diff --git a/src/librustc_typeck/check/wfcheck.rs b/src/librustc_typeck/check/wfcheck.rs index 483af08cabf..9f3fd33260e 100644 --- a/src/librustc_typeck/check/wfcheck.rs +++ b/src/librustc_typeck/check/wfcheck.rs @@ -469,6 +469,29 @@ impl<'a, 'gcx> CheckTypeWellFormedVisitor<'a, 'gcx> { debug!("check_method_receiver: sig={:?}", sig); let self_arg_ty = sig.inputs()[0]; + + if fcx.tcx.sess.features.borrow().arbitrary_self_types { + let cause = fcx.cause(span, ObligationCauseCode::MethodReceiver); + + let mut autoderef = fcx.autoderef(span, self_arg_ty); + while let Some((potential_self_ty, _)) = autoderef.next() { + debug!("check_method_receiver: potential self type `{:?}` to match `{:?}`", potential_self_ty, self_ty); + + // there's gotta be a more idiomatic way of checking if types are equal than this + if let Some(mut err) = fcx.demand_eqtype_with_origin(&cause, self_ty, potential_self_ty) { + err.cancel(); + continue; + } else { + // we found a type that matches `self_ty` + autoderef.finalize(); + return; + } + } + + span_err!(fcx.tcx.sess, span, E0307, "invalid `self` type: {:?}", self_arg_ty); + return; + } + let rcvr_ty = match ExplicitSelf::determine(self_ty, self_arg_ty) { ExplicitSelf::ByValue => self_ty, ExplicitSelf::ByReference(region, mutbl) => { diff --git a/src/librustc_typeck/diagnostics.rs b/src/librustc_typeck/diagnostics.rs index 075367cbbb7..5581613afd8 100644 --- a/src/librustc_typeck/diagnostics.rs +++ b/src/librustc_typeck/diagnostics.rs @@ -4724,6 +4724,7 @@ register_diagnostics! { // E0247, // E0248, // value used as a type, now reported earlier during resolution as E0412 // E0249, + E0307, // invalid method `self` type // E0319, // trait impls for defaulted traits allowed just for structs/enums // E0372, // coherence not object safe E0377, // the trait `CoerceUnsized` may only be implemented for a coercion diff --git a/src/libsyntax/feature_gate.rs b/src/libsyntax/feature_gate.rs index a69bf53ee14..b6cb3ac1308 100644 --- a/src/libsyntax/feature_gate.rs +++ b/src/libsyntax/feature_gate.rs @@ -409,6 +409,9 @@ declare_features! ( // extern types (active, extern_types, "1.23.0", Some(43467)), + + // Allow trait methods with arbitrary self types + (active, arbitrary_self_types, "1.23.0", Some(44874)), ); declare_features! ( |
