Provide safe conversion from hir::Ty to TyS

It seems there is no way to convert rustc_hir::Ty to rustc_middle::ty::TyS safely.

Currently, I think there are two convenient ways to do the conversion.

  1. hir_ty_to_ty
  2. TypeckResults::node_type

But actually, both of them may cause ICE.

Problems of hir_ty_to_ty

hir_ty_to_ty can't use inside a body because it calls rustc_typeck::collect::ItemCtxt::ast_ty_to_ty internally. if this method is called inside a body it would cause ICE, or worse it would return wrong data silently. These facts are not documented.

Problems of node_type

TypeckResults::node_type can use almost safely inside a body if the passed hir_id.owner is the same as TypeclResults:hir_owner.
If these ids are different from each other, TypeckResults::node_type cause ICE, see here.
But this isn't a problem in almost all situations.

The problem occurres when we try to convert type inside a nested function signature, in that case, we can't convert these types by using node_type. To explain this, see the next example.

fn outer(outer_arg: i32) -> f32 {
    fn inner(inner_arg: i64) -> f64 {

In this example, It's impossible to convert i64/f64 because TypeckResults of inner doesn't contain the types, while outer's TypeckResults contains them. But it's also impossible to convert them by using outer's TypeckResults because owner ids are different between TypeckResults and i64/f64.

And confusingly, outer's TypeckResults can be used to convert inner i64/f64 in the next example.

fn outer(outer_arg: i32) -> f32 {
    let inner = |x: i64| -> f64 {

This is because a closure shares TypeckResults with outer, so both outer and inner's TypeckResults can be used to convert them.


I'd like to use a safe conversion in clippy especially, so I'd like to suppose the next steps to implement the conversion.

  1. Make TypeckResults contain types inside a signature.
  2. Implement a safe conversion API to rustc_lint::LateContext or somewhere else.

I'm glad to get feedback, thanks.

1 Like