Skip to content

Commit 2083e2a

Browse files
committedNov 26, 2019
Stabilize nested self receivers
Previously, only Self, &Self, &mut Self, Arc<Self>, Rc<Self>, and Box<Self> were available as stable method receivers. This commit stabilizes nested uses of all the above types. However, nested receivers remain non-object-safe.
1 parent 797fd92 commit 2083e2a

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

58 files changed

+214
-319
lines changed
 

‎src/librustc_typeck/check/wfcheck.rs

Lines changed: 48 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ use crate::check::{Inherited, FnCtxt};
22
use crate::constrained_generic_params::{identify_constrained_generic_params, Parameter};
33

44
use crate::hir::def_id::DefId;
5-
use rustc::traits::{self, ObligationCauseCode};
5+
use rustc::traits::{self, ObligationCause, ObligationCauseCode};
66
use rustc::ty::{self, Ty, TyCtxt, GenericParamDefKind, TypeFoldable, ToPredicate};
77
use rustc::ty::subst::{Subst, InternalSubsts};
88
use rustc::util::nodemap::{FxHashSet, FxHashMap};
@@ -895,6 +895,11 @@ fn receiver_is_valid<'fcx, 'tcx>(
895895
// The first type is `receiver_ty`, which we know its not equal to `self_ty`; skip it.
896896
autoderef.next();
897897

898+
let receiver_trait_def_id = fcx.tcx.require_lang_item(
899+
lang_items::ReceiverTraitLangItem,
900+
None,
901+
);
902+
898903
// Keep dereferencing `receiver_ty` until we get to `self_ty`.
899904
loop {
900905
if let Some((potential_self_ty, _)) = autoderef.next() {
@@ -911,6 +916,19 @@ fn receiver_is_valid<'fcx, 'tcx>(
911916
}
912917

913918
break
919+
} else {
920+
// Without `feature(arbitrary_self_types)`, we require that each step in the
921+
// deref chain implement `receiver`
922+
if !arbitrary_self_types_enabled
923+
&& !receiver_is_implemented(
924+
fcx,
925+
receiver_trait_def_id,
926+
cause.clone(),
927+
potential_self_ty,
928+
)
929+
{
930+
return false
931+
}
914932
}
915933
} else {
916934
debug!("receiver_is_valid: type `{:?}` does not deref to `{:?}`",
@@ -919,43 +937,42 @@ fn receiver_is_valid<'fcx, 'tcx>(
919937
// unecessary errors (#58712).
920938
return receiver_ty.references_error();
921939
}
922-
923-
// Without the `arbitrary_self_types` feature, `receiver_ty` must directly deref to
924-
// `self_ty`. Enforce this by only doing one iteration of the loop.
925-
if !arbitrary_self_types_enabled {
926-
return false
927-
}
928940
}
929941

930942
// Without `feature(arbitrary_self_types)`, we require that `receiver_ty` implements `Receiver`.
931-
if !arbitrary_self_types_enabled {
932-
let trait_def_id = match fcx.tcx.lang_items().receiver_trait() {
933-
Some(did) => did,
934-
None => {
935-
debug!("receiver_is_valid: missing Receiver trait");
936-
return false
937-
}
938-
};
943+
if !arbitrary_self_types_enabled
944+
&& !receiver_is_implemented(fcx, receiver_trait_def_id, cause.clone(), receiver_ty)
945+
{
946+
return false
947+
}
939948

940-
let trait_ref = ty::TraitRef{
941-
def_id: trait_def_id,
942-
substs: fcx.tcx.mk_substs_trait(receiver_ty, &[]),
943-
};
949+
true
950+
}
951+
952+
fn receiver_is_implemented(
953+
fcx: &FnCtxt<'_, 'tcx>,
954+
receiver_trait_def_id: DefId,
955+
cause: ObligationCause<'tcx>,
956+
receiver_ty: Ty<'tcx>,
957+
) -> bool {
958+
let trait_ref = ty::TraitRef{
959+
def_id: receiver_trait_def_id,
960+
substs: fcx.tcx.mk_substs_trait(receiver_ty, &[]),
961+
};
944962

945-
let obligation = traits::Obligation::new(
946-
cause,
947-
fcx.param_env,
948-
trait_ref.to_predicate()
949-
);
963+
let obligation = traits::Obligation::new(
964+
cause,
965+
fcx.param_env,
966+
trait_ref.to_predicate()
967+
);
950968

951-
if !fcx.predicate_must_hold_modulo_regions(&obligation) {
952-
debug!("receiver_is_valid: type `{:?}` does not implement `Receiver` trait",
953-
receiver_ty);
954-
return false
955-
}
969+
if fcx.predicate_must_hold_modulo_regions(&obligation) {
970+
true
971+
} else {
972+
debug!("receiver_is_implemented: type `{:?}` does not implement `Receiver` trait",
973+
receiver_ty);
974+
false
956975
}
957-
958-
true
959976
}
960977

961978
fn check_variances_for_type_defn<'tcx>(

‎src/test/ui/self/arbitrary-self-types-not-object-safe.curr.stderr

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
error[E0038]: the trait `Foo` cannot be made into an object
2-
--> $DIR/arbitrary-self-types-not-object-safe.rs:34:32
2+
--> $DIR/arbitrary-self-types-not-object-safe.rs:33:32
33
|
44
LL | fn foo(self: &Rc<Self>) -> usize;
55
| --- method `foo`'s `self` parameter cannot be dispatched on
@@ -8,7 +8,7 @@ LL | let x = Rc::new(5usize) as Rc<dyn Foo>;
88
| ^^^^^^^^^^^ the trait `Foo` cannot be made into an object
99

1010
error[E0038]: the trait `Foo` cannot be made into an object
11-
--> $DIR/arbitrary-self-types-not-object-safe.rs:34:13
11+
--> $DIR/arbitrary-self-types-not-object-safe.rs:33:13
1212
|
1313
LL | fn foo(self: &Rc<Self>) -> usize;
1414
| --- method `foo`'s `self` parameter cannot be dispatched on

0 commit comments

Comments
 (0)