fn virtual_call_violation_for_method<'tcx>(
    tcx: TyCtxt<'tcx>,
    trait_def_id: DefId,
    method: &ty::AssocItem,
) -> Option<MethodViolationCode> {
    // The method's first parameter must be named `self`
    if !method.fn_has_self_parameter {
        // We'll attempt to provide a structured suggestion for `Self: Sized`.
        let sugg =
            tcx.hir().get_if_local(method.def_id).as_ref().and_then(|node| node.generics()).map(
                |generics| match generics.where_clause.predicates {
                    [] => (" where Self: Sized", generics.where_clause.span),
                    [.., pred] => (", Self: Sized", pred.span().shrink_to_hi()),
                },
            );
        return Some(MethodViolationCode::StaticMethod(sugg));
    }

    let sig = tcx.fn_sig(method.def_id);

    for (i, input_ty) in sig.skip_binder().inputs()[1..].iter().enumerate() {
        if contains_illegal_self_type_reference(tcx, trait_def_id, input_ty) {
            return Some(MethodViolationCode::ReferencesSelfInput(i));
        }
    }
    if contains_illegal_self_type_reference(tcx, trait_def_id, sig.output().skip_binder()) {
        return Some(MethodViolationCode::ReferencesSelfOutput);
    }

    // We can't monomorphize things like `fn foo<A>(...)`.
    let own_counts = tcx.generics_of(method.def_id).own_counts();
    if own_counts.types + own_counts.consts != 0 {
        return Some(MethodViolationCode::Generic);
    }

    if tcx
        .predicates_of(method.def_id)
        .predicates
        .iter()
        // A trait object can't claim to live more than the concrete type,
        // so outlives predicates will always hold.
        .cloned()
        .filter(|(p, _)| p.to_opt_type_outlives().is_none())
        .collect::<Vec<_>>()
        // Do a shallow visit so that `contains_illegal_self_type_reference`
        // may apply it's custom visiting.
        .visit_tys_shallow(|t| contains_illegal_self_type_reference(tcx, trait_def_id, t))
    {
        return Some(MethodViolationCode::WhereClauseReferencesSelf);
    }

    let receiver_ty =
        tcx.liberate_late_bound_regions(method.def_id, &sig.map_bound(|sig| sig.inputs()[0]));

    // Until `unsized_locals` is fully implemented, `self: Self` can't be dispatched on.
    // However, this is already considered object-safe. We allow it as a special case here.
    // FIXME(mikeyhew) get rid of this `if` statement once `receiver_is_dispatchable` allows
    // `Receiver: Unsize<Receiver[Self => dyn Trait]>`.
    if receiver_ty != tcx.types.self_param {
        if !receiver_is_dispatchable(tcx, method, receiver_ty) {
            return Some(MethodViolationCode::UndispatchableReceiver);
        } else {
            // Do sanity check to make sure the receiver actually has the layout of a pointer.

            use rustc_target::abi::Abi;

            let param_env = tcx.param_env(method.def_id);

            let abi_of_ty = |ty: Ty<'tcx>| -> &Abi {
                match tcx.layout_of(param_env.and(ty)) {
                    Ok(layout) => &layout.abi,
                    Err(err) => bug!("error: {}\n while computing layout for type {:?}", err, ty),
                }
            };

            // e.g., `Rc<()>`
            let unit_receiver_ty =
                receiver_for_self_ty(tcx, receiver_ty, tcx.mk_unit(), method.def_id);

            match abi_of_ty(unit_receiver_ty) {
                &Abi::Scalar(..) => (),
                abi => {
                    tcx.sess.delay_span_bug(
                        tcx.def_span(method.def_id),
                        &format!(
                            "receiver when `Self = ()` should have a Scalar ABI; found {:?}",
                            abi
                        ),
                    );
                }
            }

            let trait_object_ty =
                object_ty_for_trait(tcx, trait_def_id, tcx.mk_region(ty::ReStatic));

            // e.g., `Rc<dyn Trait>`
            let trait_object_receiver =
                receiver_for_self_ty(tcx, receiver_ty, trait_object_ty, method.def_id);

            match abi_of_ty(trait_object_receiver) {
                &Abi::ScalarPair(..) => (),
                abi => {
                    tcx.sess.delay_span_bug(
                        tcx.def_span(method.def_id),
                        &format!(
                            "receiver when `Self = {}` should have a ScalarPair ABI; \
                                 found {:?}",
                            trait_object_ty, abi
                        ),
                    );
                }
            }
        }
    }

    None
}
/// Returns `Some(_)` if this method cannot be called on a trait
/// object; this does not necessarily imply that the enclosing trait
/// is not object safe, because the method might have a where clause
/// `Self:Sized`.
Returns `Some(_)` if this method cannot be called on a trait
object; this does not necessarily imply that the enclosing trait
is not object safe, because the method might have a where clause
`Self:Sized`.
Returns ` Some ( _ ) ` if this method cannot be called on a trait object ; this does not necessarily imply that the enclosing trait is not object safe because the method might have a where clause ` Self : Sized ` .
fn virtual_call_violation_for_method<'tcx>(
    tcx: TyCtxt<'tcx>,
    trait_def_id: DefId,
    method: &ty::AssocItem,
) -> Option<MethodViolationCode> {
    // The method's first parameter must be named `self`
    if !method.fn_has_self_parameter {
        // We'll attempt to provide a structured suggestion for `Self: Sized`.
        let sugg =
            tcx.hir().get_if_local(method.def_id).as_ref().and_then(|node| node.generics()).map(
                |generics| match generics.where_clause.predicates {
                    [] => (" where Self: Sized", generics.where_clause.span),
                    [.., pred] => (", Self: Sized", pred.span().shrink_to_hi()),
                },
            );
        return Some(MethodViolationCode::StaticMethod(sugg));
    }
    let sig = tcx.fn_sig(method.def_id);
    for (i, input_ty) in sig.skip_binder().inputs()[1..].iter().enumerate() {
        if contains_illegal_self_type_reference(tcx, trait_def_id, input_ty) {
            return Some(MethodViolationCode::ReferencesSelfInput(i));
        }
    }
    if contains_illegal_self_type_reference(tcx, trait_def_id, sig.output().skip_binder()) {
        return Some(MethodViolationCode::ReferencesSelfOutput);
    }
    // We can't monomorphize things like `fn foo<A>(...)`.
    let own_counts = tcx.generics_of(method.def_id).own_counts();
    if own_counts.types + own_counts.consts != 0 {
        return Some(MethodViolationCode::Generic);
    }
    if tcx
        .predicates_of(method.def_id)
        .predicates
        .iter()
        // A trait object can't claim to live more than the concrete type,
        // so outlives predicates will always hold.
        .cloned()
        .filter(|(p, _)| p.to_opt_type_outlives().is_none())
        .collect::<Vec<_>>()
        // Do a shallow visit so that `contains_illegal_self_type_reference`
        // may apply it's custom visiting.
        .visit_tys_shallow(|t| contains_illegal_self_type_reference(tcx, trait_def_id, t))
    {
        return Some(MethodViolationCode::WhereClauseReferencesSelf);
    }
    let receiver_ty =
        tcx.liberate_late_bound_regions(method.def_id, &sig.map_bound(|sig| sig.inputs()[0]));
    // Until `unsized_locals` is fully implemented, `self: Self` can't be dispatched on.
    // However, this is already considered object-safe. We allow it as a special case here.
    // FIXME(mikeyhew) get rid of this `if` statement once `receiver_is_dispatchable` allows
    // `Receiver: Unsize<Receiver[Self => dyn Trait]>`.
    if receiver_ty != tcx.types.self_param {
        if !receiver_is_dispatchable(tcx, method, receiver_ty) {
            return Some(MethodViolationCode::UndispatchableReceiver);
        } else {
            // Do sanity check to make sure the receiver actually has the layout of a pointer.
            use rustc_target::abi::Abi;
            let param_env = tcx.param_env(method.def_id);
            let abi_of_ty = |ty: Ty<'tcx>| -> &Abi {
                match tcx.layout_of(param_env.and(ty)) {
                    Ok(layout) => &layout.abi,
                    Err(err) => bug!("error: {}\n while computing layout for type {:?}", err, ty),
                }
            };
            // e.g., `Rc<()>`
            let unit_receiver_ty =
                receiver_for_self_ty(tcx, receiver_ty, tcx.mk_unit(), method.def_id);
            match abi_of_ty(unit_receiver_ty) {
                &Abi::Scalar(..) => (),
                abi => {
                    tcx.sess.delay_span_bug(
                        tcx.def_span(method.def_id),
                        &format!(
                            "receiver when `Self = ()` should have a Scalar ABI; found {:?}",
                            abi
                        ),
                    );
                }
            }
            let trait_object_ty =
                object_ty_for_trait(tcx, trait_def_id, tcx.mk_region(ty::ReStatic));
            // e.g., `Rc<dyn Trait>`
            let trait_object_receiver =
                receiver_for_self_ty(tcx, receiver_ty, trait_object_ty, method.def_id);
            match abi_of_ty(trait_object_receiver) {
                &Abi::ScalarPair(..) => (),
                abi => {
                    tcx.sess.delay_span_bug(
                        tcx.def_span(method.def_id),
                        &format!(
                            "receiver when `Self = {}` should have a ScalarPair ABI; \
                                 found {:?}",
                            trait_object_ty, abi
                        ),
                    );
                }
            }
        }
    }
    None
}
fn virtual_call_violation_for_method < ' tcx > ( tcx : TyCtxt < ' tcx > , trait_def_id : DefId , method : & ty :: AssocItem , ) -> Option < MethodViolationCode > { // The method's first parameter must be named `self` if ! method . fn_has_self_parameter { // We'll attempt to provide a structured suggestion for `Self: Sized`. let sugg = tcx . hir ( ) . get_if_local ( method . def_id ) . as_ref ( ) . and_then ( | node | node . generics ( ) ) . map ( | generics | match generics . where_clause . predicates { [ ] => ( " " , generics . where_clause . span ) , [ .. , pred ] => ( " " , pred . span ( ) . shrink_to_hi ( ) ) , } , ) ; return Some ( MethodViolationCode :: StaticMethod ( sugg ) ) ; } let sig = tcx . fn_sig ( method . def_id ) ; for ( i , input_ty ) in sig . skip_binder ( ) . inputs ( ) [ 1 .. ] . iter ( ) . enumerate ( ) { if contains_illegal_self_type_reference ( tcx , trait_def_id , input_ty ) { return Some ( MethodViolationCode :: ReferencesSelfInput ( i ) ) ; } } if contains_illegal_self_type_reference ( tcx , trait_def_id , sig . output ( ) . skip_binder ( ) ) { return Some ( MethodViolationCode :: ReferencesSelfOutput ) ; } // We can't monomorphize things like `fn foo<A>(...)`. let own_counts = tcx . generics_of ( method . def_id ) . own_counts ( ) ; if own_counts . types + own_counts . consts != 0 { return Some ( MethodViolationCode :: Generic ) ; } if tcx . predicates_of ( method . def_id ) . predicates . iter ( ) // A trait object can't claim to live more than the concrete type, // so outlives predicates will always hold. . cloned ( ) . filter ( | ( p , _ ) | p . to_opt_type_outlives ( ) . is_none ( ) ) . collect :: < Vec < _ > > ( ) // Do a shallow visit so that `contains_illegal_self_type_reference` // may apply it's custom visiting. . visit_tys_shallow ( | t | contains_illegal_self_type_reference ( tcx , trait_def_id , t ) ) { return Some ( MethodViolationCode :: WhereClauseReferencesSelf ) ; } let receiver_ty = tcx . liberate_late_bound_regions ( method . def_id , & sig . map_bound ( | sig | sig . inputs ( ) [ 0 ] ) ) ; // Until `unsized_locals` is fully implemented, `self: Self` can't be dispatched on. // However, this is already considered object-safe. We allow it as a special case here. // FIXME(mikeyhew) get rid of this `if` statement once `receiver_is_dispatchable` allows // `Receiver: Unsize<Receiver[Self => dyn Trait]>`. if receiver_ty != tcx . types . self_param { if ! receiver_is_dispatchable ( tcx , method , receiver_ty ) { return Some ( MethodViolationCode :: UndispatchableReceiver ) ; } else { // Do sanity check to make sure the receiver actually has the layout of a pointer. use rustc_target :: abi :: Abi ; let param_env = tcx . param_env ( method . def_id ) ; let abi_of_ty = | ty : Ty < ' tcx > | -> & Abi { match tcx . layout_of ( param_env . and ( ty ) ) { Ok ( layout ) => & layout . abi , Err ( err ) => bug ! ( " \n " err ty ) , } } ; // e.g., `Rc<()>` let unit_receiver_ty = receiver_for_self_ty ( tcx , receiver_ty , tcx . mk_unit ( ) , method . def_id ) ; match abi_of_ty ( unit_receiver_ty ) { & Abi :: Scalar ( .. ) => ( ) , abi => { tcx . sess . delay_span_bug ( tcx . def_span ( method . def_id ) , & format ! ( " " abi ) , ) ; } } let trait_object_ty = object_ty_for_trait ( tcx , trait_def_id , tcx . mk_region ( ty :: ReStatic ) ) ; // e.g., `Rc<dyn Trait>` let trait_object_receiver = receiver_for_self_ty ( tcx , receiver_ty , trait_object_ty , method . def_id ) ; match abi_of_ty ( trait_object_receiver ) { & Abi :: ScalarPair ( .. ) => ( ) , abi => { tcx . sess . delay_span_bug ( tcx . def_span ( method . def_id ) , & format ! ( " \
 " trait_object_ty abi ) , ) ; } } } } None }
Returns `Some(_)` if this method cannot be called on a trait
object; this does not necessarily imply that the enclosing trait
is not object safe, because the method might have a where clause
`Self:Sized`.
Returns ` Some ( _ ) ` if this method cannot be called on a trait object ; this does not necessarily imply that the enclosing trait is not object safe because the method might have a where clause ` Self : Sized ` .
tcx
TyCtxt<'tcx>
trait_def_id
DefId
method
&ty::AssocItem
tcx
TyCtxt<'tcx>
trait_def_id
DefId
method
&ty::AssocItem