Change:
<ins> //@ check-pass //! Tests that associated type projections normalize properly in the presence of HRTBs. //! Original issue: <https://github.com/rust-lang/rust/issues/30472> pub trait MyFrom<T> {} impl<T> MyFrom<T> for T {} pub trait MyInto<T> {} impl<T, U> MyInto<U> for T where U: MyFrom<T> {} pub trait A<'self_> { type T; } pub trait B: for<'self_> A<'self_> { // Originally caused the `type U = usize` example below to fail with a type mismatch error type U: for<'self_> MyFrom<<Self as A<'self_>>::T>; } pub struct M; impl<'self_> A<'self_> for M { type T = usize; } impl B for M { type U = usize; } fn main() {} </ins>

Discussion:
The following doesn't compile, as it tries to assign a concrete instead of : Removing the type parameter makes it work - is only used for the associated type anyway: AFAICT, the selection results in in the first case, and in the second case, and we refuse to allow to be parameterized by in the former case, even though it's only used to satisfy the sugary form of the trait.
Is this the same issue as with the impls for not matching ?
I'm trying to decide if this is an actual bug :) It does seem like the "HR capture" logic is being unnecessarily conservative. Let me poke at the debug logs and see if that reveals to me why it is rejecting the impl when you include but not if you don't (also, it works if you do ).
I believe it breaks for type parameters which cannot be extracted from the , i.e. . You should be able to relate multiple argument types, but not the return type (because it's an associated type and not part of the ).
Hmm, the problem is a bit of a subtle one and, in this particular example, tied to the associated type projection. (No I don't, see update below.) No doubt this is already filed somewhere under another guise. I'm not sure of the best fix, but let me lay out how the problem arises in terms of what the compiler actually does. We start out with a trait reference to solve: We match this against the impl Which, internally, is lowered to: In so doing, we first "open" the binder, so that the trait we are searching for becomes: where is a region variable. We then check whether we can match this against the impl in question. We can, with and . is left unconstrained. The where clauses on the impl are always processed after we perform the initial match. So we wind up saying that the impl applies and that we now have various subobligations. The region variable appears in some of those, and in that case we "regeneralize" by adding back a binder so that becomes a bound region again: Note that is what was substituted for the variable (but never constrained). And this is where the problem arises. I think that the basic strategy here is somewhat wrong.

It would be OK in the absence of variables like , which do not appear in the trait reference but which are constrained by projections, but it's wrong now. The problem is that was created "inside" the binder along with with and but, unlike those other variables, it was never constrained. Thus we kind of silently promote it to live outside the scope of the , since it is completely unconstrained. This is not necessarily wrong I guess but it is overly conservative. One possible fix here would be to recursively (and before returning) handle the projection constraints, so that winds up being "determined" to be , which could then be generalized to wherever it appeared. That may be the best short term fix at least, though I am not so keen on it overall because I don't like doing work recursively like that. If we had had lazy normalization, this would be much easier, because then we could just unify with , which would then be generalized to a bound region as needed. That's probably my preferred fix, presuming it can be made to work. This is basically the same as processing the projection constraint recursively, except that we could defer the actual normalization until later (and we may never have to do it). (The other solutions I can imagine are quite a bit more complicated. It seems like you would need to capture, in the tree, what variables are bound where. What makes this hard is that is shared across two obligations.) UPDATE: Remove sentence I don't think. I think that for this problem to arise you really need an associated type, since you need a type variable that is not found in the trait reference, which is otherwise verboten.
cc -- this seems related to the changes you made to order projection predicates earlier in the list. Does make sense to you?
I am not sure we should not evaluate associated type projections recursively - RFC447 basically forces this to work. Unfortunately, it will work imperfectly without lazy normalization, because we can't represent a constraint like .
On Thu, Jan 14, 2016 at 12:54:36PM -0800, arielb1 wrote: Sorry, the double negative in this sentence is throwing me a bit. I'm not sure I understand what you are saying. Are you saying my proposed solution would or would not work?

Also, when you say evaluate, I presume you are not referring to the family of fns in but just using a generic verb.
Can you elaborate just a bit on this? When does this kind of constraint arise?
Recursively applying constraining-projections during confirmation should work, except for the type-inference case.
Sorry for not replying. I'm afraid I still don't quite follow you, so let me try and work it out. First off, I guess you meant to have , like so, and probably : I'm not quite sure what the last line means, but if we were to follow the model of the original problem, we'd start with something to prove like . "Opening" the and matching this against the impl yields: and hence . This suggests that we would translate the where clauses on the impl to: which we would could then cover back up as: This all seems...OK. Ah, wait, I guess your point is that we would need to normalize the . I feel like we have issues normalizing under for binders still, right?
I was bitten by this bug... simplifying a lot, my code looked like this (): but this isn't lifetime-polymporphic: produces: but if you make the iterator item type a type argument, then it all works: so I need to rewrite a lot of code to take an extra type argument in order to be lifetime-polymorphic!
Both the original example and asajeffrey's example compile now.

This could've been written with written as and similarly for /. It was written this way only to make explicit the necessity of one blanket impl for satisfying the other. I'm guessing that extensional equality is not judged, even though it is possible to make such a judgment and such a judgment must be made to compile code that compiles today. on line 12 ought to be equated to (which must be detected at some other point in time else line 13 wouldn't be able to compile). EDIT: Playing around a bit, it looks more and more like it's all about the HKL bounds...
HRTBs (I've been using the wrong nomenclature the whole time!) make projections sad. Very likely a dupe of .
cc
Known issue.
(or Still a bit unclear on y'all's role separation) What's the expected overall approach to fixing this issue? Even if you don't expect a newcomer to handle it, I'd like to know anyway. :-D
actually, I'm not entirely sure. There are a serious of refactorings that I have in mind for the type system / trait resolver, and I've been figuring that after those are done, I would come back to revisit some of these issues, if they still occur, but it may be worth digging into this example (or ) in detail. Honestly it's not all fresh in my mind. The refactorings I am thinking of are, first, lazy normalization (as described ), which may indeed help here, though I've not thought it through very deeply. Second, I'd like to generally rework how the trait checker is working to make it easier to extend the environment as you go -- the current setup, where the set of assumptions etc is semi-fixed when the inference context is created -- makes it hard to "descend through" a binder like and then do trait resolutions and normalizations within that context.
So, potentially w.r.t. lazy normalization, I've been playing with another bit of code (trying to shrink it a bit): From reading the debug logs, it seems that when checking the well-formed-ness of , upon normalizing to , and registering and ing on the implied , the compiler has no idea that and never normalizes to it either. Is this a situation in which the compiler might have assumed that everything was already normalized the best it could be and thus gave up?

An aside: does lazy normalization have something to do with ?
Is this It looks similar, but uncertain.
What's the state of this now? I fairly frequently run into problems with associated types involved with HRTBs not projecting/unifying.
Triage: last two comments asking for clarification, no replies. Given comments earlier in the thread, I imagine this issue is "post-chalk".
This is one of the things that the traits working group is kind of actively working towards. It's blocked to some extent on the universes work, see e.g. which tries to unblock that effort, plus lazy norm. I think we'll be making active progress though over the next few months.
Triage: According to , this should get tagged .
I think this issue is related to an error I encountered when trying to use the trait example . The trait is defined as follow: I implemented it for a vector of booleans: I believe this should compile, but it errors. <details<summarySee full error</summary</detailsIt does not recognize that and are the same.
You example compiles now.
Triage: The original issue seems to have been fixed, the example from the issue description compiles just fine now.

fails with
I'm using .
cc
Still an issue ().
Triage: no change as of Rust 1.41:
Triage: This compiles just fine now.

When I tried this, I was hoping it would output the executable to stdout. Saving it as a file called would be reasonable behavior too. <!-- TRIAGEBOTSTART --<!-- TRIAGEBOTASSIGNSTART --<!-- TRIAGEBOTASSIGNDATASTARTTRIAGEBOTASSIGNDATAEND --<!-- TRIAGEBOTASSIGNEND --<!-- TRIAGEBOTEND --
Triage: no change.
I almost want to say that this isn't a bug. Do gcc and clang handle this case? I feel like it would be odd to write the compiler's output (binary data) to stdout.
gcc and clang both output to a file called :
Triage: no change
It would be nice if we could still output to stdout in the case where is writing printable output. If you do , it should output to stdout, same with clang, and same for clang's option.
The issue is fixed: But it looks like the forgot to write a regression test for the non- case, i.e. plain . We should add such a test before we close this issue. label E-needs-test
claim
Hi team would like to contribute to the project as a beginner to rust. I see that the task is to add a unit test? Is this available?
claim
I am going to give it a shot. Seems the change should be to the Makefile in ?

Added by pnkfelix: here is a summary of cases discussed in comment dialogue on issue.. Outcome Matrix zero-sized elems ---------------- ------------------ array length = 0xffffffffffffffff [takes too long to know outcome?][smallZ] array length = 0xffffffff [successful compile after several minutes][largeZ] [smallNZ]: [largeNZ]: [smallZ]: [largeZ]: Original bug report below Test case one: Test case two: rustc version: I didn't see any other open issues mentioning .
I just hit this. It happens even with arrays whose element type is zero-sized (and therefore the entire array should be zero-sized):
This also gives the same ICE: If you size it just right you actually get an out of memory instead (= abort)
Triage: tracked by glacier
tests in the OP seem to not build, but no longer ICE. still ICEs though
This code no longer ICEs, it does however kick rustc into high gear and take up huge amounts of RAM and time. https://travis- is currently attempting to build this and it looks like it's hanging. At the very least, it shouldn't take multiple minutes to compile such a thing.
I spoke to for a bit about this issue. They have some ideas on ways to address this within const-eval. The main question was how to select an actual threshold to act as the limit on memory usage (or maybe individual array length); we agreed that a configurable threshold analogous to the recursion limit would probably make the most sense.
But having said that, I the four cases of interest that were identified in the comments here, and evaluated their behavior on my x86_64 Linux box. I saw: a controlled exit from , a successful compile, an LLVM OOM (is the latter considered an ICE in our book? Its a controlled exit, just not controlled by our own Rust code...) and I suspect the last case isn't going to finish compiling any time soon. (Update: I'm still waiting after letting it run for 22 hours... And given the numbers involved here, I don't think I or anyone else is going to see that run finish.) Based on these observations, I'm going to triage this as P-low. If someone wants to put in the effort to get the const-eval to support a configurable limit on memory usage, great.

( even said that it used to have a memory usage limit, and they ripped it out.) But its not something we should prioritize over other problems we face.
Seems to no longer ICE with modify labels: E-needs-test
The ZST variants now work really fast, it's only the 2^32 variant that takes forever to compile on 64 bit