Skip to content

Commit eb997d7

Browse files
committed
add U: Trait to the param env during DispatchFromDyn check
also updated the doc on `receiver_is_dispatchable` to reflect current state of the implementation
1 parent b5b25f8 commit eb997d7

File tree

1 file changed

+40
-27
lines changed

1 file changed

+40
-27
lines changed

src/librustc/traits/object_safety.rs

+40-27
Original file line numberDiff line numberDiff line change
@@ -437,16 +437,16 @@ impl<'a, 'tcx> TyCtxt<'a, 'tcx, 'tcx> {
437437
/// in the following way:
438438
/// - let `Receiver` be the type of the `self` argument, i.e `Self`, `&Self`, `Rc<Self>`
439439
/// - require the following bound:
440-
/// forall(T: Trait) {
441-
/// Receiver[Self => T]: DispatchFromDyn<Receiver[Self => dyn Trait]>
442-
/// }
443-
/// where `Foo[X => Y]` means "the same type as `Foo`, but with `X` replaced with `Y`"
440+
///
441+
/// Receiver[Self => T]: DispatchFromDyn<Receiver[Self => dyn Trait]>
442+
///
443+
/// where `Foo[X => Y]` means "the same type as `Foo`, but with `X` replaced with `Y`"
444444
/// (substitution notation).
445445
///
446446
/// some examples of receiver types and their required obligation
447-
/// - `&'a mut self` requires `&'a mut T: DispatchFromDyn<&'a mut dyn Trait>`
448-
/// - `self: Rc<Self>` requires `Rc<T>: DispatchFromDyn<Rc<dyn Trait>>`
449-
/// - `self: Pin<Box<Self>>` requires `Pin<Box<T>>: DispatchFromDyn<Pin<Box<dyn Trait>>>`
447+
/// - `&'a mut self` requires `&'a mut Self: DispatchFromDyn<&'a mut dyn Trait>`
448+
/// - `self: Rc<Self>` requires `Rc<Self>: DispatchFromDyn<Rc<dyn Trait>>`
449+
/// - `self: Pin<Box<Self>>` requires `Pin<Box<Self>>: DispatchFromDyn<Pin<Box<dyn Trait>>>`
450450
///
451451
/// The only case where the receiver is not dispatchable, but is still a valid receiver
452452
/// type (just not object-safe), is when there is more than one level of pointer indirection.
@@ -456,14 +456,12 @@ impl<'a, 'tcx> TyCtxt<'a, 'tcx, 'tcx> {
456456
/// contained by the trait object, because the object that needs to be coerced is behind
457457
/// a pointer.
458458
///
459-
/// In practice, there are issues with the above bound: `where` clauses that apply to `Self`
460-
/// would have to apply to `T`, trait object types have a lot of parameters that need to
461-
/// be filled in (lifetime and type parameters, and the lifetime of the actual object), and
462-
/// I'm pretty sure using `dyn Trait` in the query causes another object-safety query for
463-
/// `Trait`, resulting in cyclic queries. So in the implementation, we use the following,
464-
/// more general bound:
459+
/// In practice, we cannot use `dyn Trait` explicitly in the obligation because it would result
460+
/// in a new check that `Trait` is object safe, creating a cycle. So instead, we fudge a little
461+
/// by introducing a new type parameter `U` such that `Self: Unsize<U>` and `U: Trait + ?Sized`,
462+
/// and use `U` in place of `dyn Trait`. Written as a chalk-style query:
465463
///
466-
/// forall (U: ?Sized) {
464+
/// forall (U: Trait + ?Sized) {
467465
/// if (Self: Unsize<U>) {
468466
/// Receiver: DispatchFromDyn<Receiver[Self => U]>
469467
/// }
@@ -493,6 +491,7 @@ impl<'a, 'tcx> TyCtxt<'a, 'tcx, 'tcx> {
493491
return false;
494492
};
495493

494+
// the type `U` in the query
496495
// use a bogus type parameter to mimick a forall(U) query using u32::MAX for now.
497496
// FIXME(mikeyhew) this is a total hack, and we should replace it when real forall queries
498497
// are implemented
@@ -501,34 +500,48 @@ impl<'a, 'tcx> TyCtxt<'a, 'tcx, 'tcx> {
501500
Name::intern("RustaceansAreAwesome").as_interned_str(),
502501
);
503502

504-
// create a modified param env, with `Self: Unsize<U>` added to the caller bounds
503+
// `Receiver[Self => U]`
504+
let unsized_receiver_ty = self.receiver_for_self_ty(
505+
receiver_ty, unsized_self_ty, method.def_id
506+
);
507+
508+
// create a modified param env, with `Self: Unsize<U>` and `U: Trait` added to caller bounds
509+
// `U: ?Sized` is already implied here
505510
let param_env = {
506511
let mut param_env = self.param_env(method.def_id);
507512

508-
let predicate = ty::TraitRef {
513+
// Self: Unsize<U>
514+
let unsize_predicate = ty::TraitRef {
509515
def_id: unsize_did,
510516
substs: self.mk_substs_trait(self.mk_self_type(), &[unsized_self_ty.into()]),
511517
}.to_predicate();
512518

519+
// U: Trait<Arg1, ..., ArgN>
520+
let trait_predicate = {
521+
let substs = Substs::for_item(self, method.container.assert_trait(), |param, _| {
522+
if param.index == 0 {
523+
unsized_self_ty.into()
524+
} else {
525+
self.mk_param_from_def(param)
526+
}
527+
});
528+
529+
ty::TraitRef {
530+
def_id: unsize_did,
531+
substs,
532+
}.to_predicate()
533+
};
534+
513535
let caller_bounds: Vec<Predicate<'tcx>> = param_env.caller_bounds.iter().cloned()
514-
.chain(iter::once(predicate))
536+
.chain(iter::once(unsize_predicate))
537+
.chain(iter::once(trait_predicate))
515538
.collect();
516539

517540
param_env.caller_bounds = self.intern_predicates(&caller_bounds);
518541

519542
param_env
520543
};
521544

522-
let receiver_substs = Substs::for_item(self, method.def_id, |param, _| {
523-
if param.index == 0 {
524-
unsized_self_ty.into()
525-
} else {
526-
self.mk_param_from_def(param)
527-
}
528-
});
529-
// the type `Receiver[Self => U]` in the query
530-
let unsized_receiver_ty = receiver_ty.subst(self, receiver_substs);
531-
532545
// Receiver: DispatchFromDyn<Receiver[Self => U]>
533546
let obligation = {
534547
let predicate = ty::TraitRef {

0 commit comments

Comments
 (0)