> +        DBUG_RETURN(TRUE);
> +      }
>        num_fields++;
> +    }
>    }
>    if (unlikely(num_fields > MAX_REF_PARTS))
>    {
> diff --git a/sql/table.cc b/sql/table.cc
> index ce7a34a8fe2..0c2ff1eea5a 100644
> --- a/sql/table.cc
> +++ b/sql/table.cc
> @@ -1776,7 +1776,7 @@ int TABLE_SHARE::init_from_binary_frm_image(THD *thd, bool write,
>        goto err;
>      DBUG_PRINT("info", ("Columns with system versioning: [%d, %d]", row_start, row_end));
>      versioned= VERS_TIMESTAMP;
> -    vers_can_native= plugin_hton(se_plugin)->flags & HTON_NATIVE_SYS_VERSIONING;
> +    vers_can_native= handler_file->vers_can_native(thd);

Interesting. How does that work? Your ha_partition::vers_can_native() is

  bool can= !thd->lex->part_info
            || thd->lex->part_info->part_type != VERSIONING_PARTITION;
  for (uint i= 0; i < m_tot_parts && can; i++)
    can= can && m_file[i]->vers_can_native(thd);
  return can;

But it doesn't look like thd->lex->part_info->part_type is initialized
at this point in time. Try to add to your test case

  flush tables;
  select * from t1;

Yes, part_info is going to be filled only if creating, or altering table. 
It works as follows:
If we're creating/altering, then check thd->lex->part_info;
else, check m_file array, which is initialized at that point.

Added this as the comment for clarity.
No, have rewritten it in another style. Should be sane enough now.
Is it?
--
Yours truly,
Nikita Malyavin