Good question!
Partly the answer is that I too do not want type inference doing open-ended queries, and for that reason I am paying special attention to them to be sure that we don’t waste too much time when they do happen.
But I guess the question is “how can they happen in the first place”, or maybe “can’t we just not make such queries”. I think to some extent the answer is yes, we can try to hold off on doing queries until the “input types” are fully resolved.
But it’s not always that simple. There are several cases where we rely on the trait solver to help us push type inference through. Some examples:
Associated type normalization. For example, consider this simple case:
impl<A, B> Foo for A
where A: Iterator<Item = B>
{ ... }
when lowered to chalk, you get something like:
(?A: Foo) :-
?A: Iterator,
<?A as Iterator>::Item = ?B
Note that ?B is unconstrained here (of course, it will be derived from ?A).
Partially restricted impls. Similarly, we sometimes have “partially restricted” examples, like Vec<T>: Index<usize> and Vec<T>: Index<Slice<usize>>, where we’d like to be able to infer that the 3 in vec[3] is a usize (as opposed to some other kind of integer). It is initially an unconstrained type variable, so we start out with something like Vec<T>: Index<?U>, and we have to restrain ?U.
Integer literals have a bit of additional complexity here: in the compiler, they are a like a special ad-hoc kind of type variable that only unifies with integer types. That helps us here to narrow down the impls. In this SLG solver, you could model that instead with a pair of goals, like Vec<T>: Index<?U> and IsIntegral(?U), where IsIntegral is true for the integral types.