Just to make sure I understand this code - we end up in get_lookup_constraint branch in the case the final_field was a ForeignKey. If so,  we do the _pk_trace stage in get_lookup_constraint().

How about the get_db_prep_lookup(), get_prep_lookup()? If I understand correctly, these seem to be handled by the underlying fields now which is of course the right thing to do. It might be we need to document this as backwards incompatible change for those who have subclassed ForeignKey and overridden these public methods.