Stream: wg-async-foundations

Topic: "recorded types from MIR" PR #65782


nikomatsakis (Dec 11 2019 at 19:30, on Zulip):

Hey @Aaron Hill -- I've been looking over PR #65782, do you want to chat about it soon-ish as we discussed?

Aaron Hill (Dec 11 2019 at 19:30, on Zulip):

Sure!

nikomatsakis (Dec 11 2019 at 19:30, on Zulip):

Actually I've mostly been pondering the main comment, I've not really looked at the code yet =)

Aaron Hill (Dec 11 2019 at 19:31, on Zulip):

There are essentially two parts:
1) Delaying the processing of generator-related obligations until mir typeck/borrowck
2) Changing how 'constituent tyoes' are defined for GeneratorWitness

nikomatsakis (Dec 11 2019 at 19:31, on Zulip):

Can you say a bit more about 2?

nikomatsakis (Dec 11 2019 at 19:31, on Zulip):

I'm mostly thinking about 1

Aaron Hill (Dec 11 2019 at 19:31, on Zulip):

I think the first part might actually be the more complicated part, since it involves changes to both typeck, TraitEngine/SelectionContext, and mir typeck/borrowck

Aaron Hill (Dec 11 2019 at 19:31, on Zulip):

sure

nikomatsakis (Dec 11 2019 at 19:32, on Zulip):

How I understood from the PR description is something like

nikomatsakis (Dec 11 2019 at 19:32, on Zulip):
nikomatsakis (Dec 11 2019 at 19:32, on Zulip):

we record that for posterity and just assume it's true

nikomatsakis (Dec 11 2019 at 19:32, on Zulip):

(perhaps in some "special mode")

nikomatsakis (Dec 11 2019 at 19:32, on Zulip):

then later in MIR code, we go and prove for real

Aaron Hill (Dec 11 2019 at 19:32, on Zulip):

That's correct

nikomatsakis (Dec 11 2019 at 19:32, on Zulip):

this is effectively similar to the idea of "reveal"

nikomatsakis (Dec 11 2019 at 19:32, on Zulip):

it interacts I think with specialization

Aaron Hill (Dec 11 2019 at 19:33, on Zulip):

How so? I would have assumed that specialization doesn't directly interact with generators

nikomatsakis (Dec 11 2019 at 19:33, on Zulip):

like, if you have a specialization that is true iff something is Send

Aaron Hill (Dec 11 2019 at 19:33, on Zulip):

Since you can't write impls for them

Aaron Hill (Dec 11 2019 at 19:34, on Zulip):

ah

nikomatsakis (Dec 11 2019 at 19:34, on Zulip):
trait MyTrait {
    type Bar;
}

impl<T> MyTrait for T { default type Bar = (); }
impl<T: Send> MyTrait for T { type Bar = u32; }
Aaron Hill (Dec 11 2019 at 19:34, on Zulip):

I implemeneted the 'delayed generator witnesses' as a 'special mode' of TraitEngine

Aaron Hill (Dec 11 2019 at 19:34, on Zulip):

we only use this mode during type inference

nikomatsakis (Dec 11 2019 at 19:34, on Zulip):

I believe that, as presently defined, you can observe that <T as MyTrait>::Bar is u32

Aaron Hill (Dec 11 2019 at 19:34, on Zulip):

every other existing usage of TraitEngine/SelectionnContext gets the current behavior

nikomatsakis (Dec 11 2019 at 19:34, on Zulip):

(I'm thinking also about what this would mean for chalk)

Aaron Hill (Dec 11 2019 at 19:35, on Zulip):

oh, you're talking about specialization of assocaited types

Aaron Hill (Dec 11 2019 at 19:35, on Zulip):

I thought you were referring to the impl itself

Aaron Hill (Dec 11 2019 at 19:35, on Zulip):

hmm

nikomatsakis (Dec 11 2019 at 19:36, on Zulip):

I guess if I had concerns they would be:

nikomatsakis (Dec 11 2019 at 19:37, on Zulip):

yes, typeck can observe specializations, as you can see here

Aaron Hill (Dec 11 2019 at 19:37, on Zulip):

I'm not very familiar with specialization of associated types - where do we end up 'checking' (but not requiring) if a bound holds, so that we can see if the specialized impl should be used?

nikomatsakis (Dec 11 2019 at 19:37, on Zulip):

(interestingly, the current code cannot rely on the projection being () -- that is, we always assume new specializations could be added during typeck)

nikomatsakis (Dec 11 2019 at 19:37, on Zulip):

I'm not very familiar with specialization of associated types - where do we end up 'checking' (but not requiring) if a bound holds, so that we can see if the specialized impl should be used?

it happens in the select.rs code right now

nikomatsakis (Dec 11 2019 at 19:38, on Zulip):

there is some logic that says "if you have two competing impls A and B, and A specializes B, and you know that A applies, then discard B"

nikomatsakis (Dec 11 2019 at 19:38, on Zulip):

we could certainly make it so that "generator impls Send" is more of a "maybe true" bit of info

nikomatsakis (Dec 11 2019 at 19:39, on Zulip):

that's a new concept we'd have to add though

Aaron Hill (Dec 11 2019 at 19:39, on Zulip):

I hadn't considered that interaction at all

Aaron Hill (Dec 11 2019 at 19:39, on Zulip):

that really complicates things

nikomatsakis (Dec 11 2019 at 19:39, on Zulip):

Yes.

Aaron Hill (Dec 11 2019 at 19:39, on Zulip):

I had previously assumed that it didn't really matter 'when' we determined if 'G: AutoTrait' holds or not. However, that seems to be wrong

nikomatsakis (Dec 11 2019 at 19:39, on Zulip):

The same thing is something of a problem for -> impl Trait and send

nikomatsakis (Dec 11 2019 at 19:40, on Zulip):

Right now we impose a DAG relationship for that reason

nikomatsakis (Dec 11 2019 at 19:40, on Zulip):

It's of course possible to imagine that we should alter specialization to avoid this interaction, though it'd be a significant limitation

nikomatsakis (Dec 11 2019 at 19:42, on Zulip):

/me thinks

nikomatsakis (Dec 11 2019 at 19:42, on Zulip):

So, if we didn't take this approach

nikomatsakis (Dec 11 2019 at 19:42, on Zulip):

Well, put another way, the conflict I am identifying is basically unavoidable

Aaron Hill (Dec 11 2019 at 19:44, on Zulip):

yeah, it seems so - we need to do type-checking to generate the MIR, but the MIR can directly influence type-checking via specialization

Aaron Hill (Dec 11 2019 at 19:45, on Zulip):

I think this would apply to any approach that tries to use the MIR (in any way) to determine generator auto trait impls

nikomatsakis (Dec 11 2019 at 19:45, on Zulip):

Agreed

nikomatsakis (Dec 11 2019 at 19:45, on Zulip):

This is kind of where I got stuck when thinking about it before

nikomatsakis (Dec 11 2019 at 19:45, on Zulip):

It seems like there are two options

nikomatsakis (Dec 11 2019 at 19:45, on Zulip):

Or maybe three :)

nikomatsakis (Dec 11 2019 at 19:46, on Zulip):

I mean (1) is that we take this basic approach, but we work out the interactions w/ specialization etc somehow

nikomatsakis (Dec 11 2019 at 19:46, on Zulip):

This might be by assuming Send is true (and checking later), which I'm not wild about, or by regarding it as "unknown" (and hence refusing to decide whether the specialization applies)

nikomatsakis (Dec 11 2019 at 19:47, on Zulip):

with perhaps some kind of "opt-in" to make it required to be true

nikomatsakis (Dec 11 2019 at 19:48, on Zulip):

well, hmm, so even looking past MIR, there really is a "core cycle" which is:

nikomatsakis (Dec 11 2019 at 19:48, on Zulip):

we can't figure out all the types

nikomatsakis (Dec 11 2019 at 19:48, on Zulip):

(at least in some cases)

nikomatsakis (Dec 11 2019 at 19:48, on Zulip):

i.e., the type of something might depend on specialization

nikomatsakis (Dec 11 2019 at 19:48, on Zulip):

so I think there are really just two choices

nikomatsakis (Dec 11 2019 at 19:49, on Zulip):

we can resolve that, as I just described, or we can use an approximation (as we do today) -- but even the one we use today seems to require knowing the types..?

Aaron Hill (Dec 11 2019 at 19:51, on Zulip):

To make matters worse, the generator can be hidden behind several other types, via type-alias-impl-trait

nikomatsakis (Dec 11 2019 at 19:51, on Zulip):
#![feature(specialization)]

trait MyTrait {
    type Bar;
}

impl<T> MyTrait for T { default type Bar = (); }
impl<T: Send> MyTrait for T { type Bar = u32; }

fn gimme<T: MyTrait>(x: T) -> <T as MyTrait>::Bar {
    panic!()
}

fn main() {
    let x = async move {

    };
    let y = gimme(x);
}
Aaron Hill (Dec 11 2019 at 19:51, on Zulip):

So, trying to specialize based on InnocousStruct: Send might actually involve determining whether some generator is Send

nikomatsakis (Dec 11 2019 at 19:52, on Zulip):

that's an example where the type of y is determined from gimme(x)

nikomatsakis (Dec 11 2019 at 19:52, on Zulip):

I think you can use some deferred type variables to get that as part of x

nikomatsakis (Dec 11 2019 at 19:53, on Zulip):

e.g., this one, but it won't compile today (which seems good)

nikomatsakis (Dec 11 2019 at 19:53, on Zulip):

(and as I expected)

nikomatsakis (Dec 11 2019 at 19:54, on Zulip):

I think what is happening there is that we don't yet know the interior types of the generator, so that the T: MyTrait<Bar = ?U> obligation remains effectively unsatisfied, and hence the type of z: Option<?U> is never fully known

nikomatsakis (Dec 11 2019 at 19:55, on Zulip):

"more or less"

Aaron Hill (Dec 11 2019 at 19:55, on Zulip):

hmm

Aaron Hill (Dec 11 2019 at 19:56, on Zulip):

thinking about this from the MIR side - we really do need to know the actual types when deciding which types are live across yield points. - the analysis takes Drop into account

Aaron Hill (Dec 11 2019 at 19:57, on Zulip):

this cycle seems really fundamental, unfortunately

nikomatsakis (Dec 11 2019 at 19:58, on Zulip):

Yeah. So there is the option of just refusing to make decisions.

nikomatsakis (Dec 11 2019 at 19:58, on Zulip):

After all, this is something of an edge case that is unlikely to truly arise.

nikomatsakis (Dec 11 2019 at 19:58, on Zulip):

I'm thinking a bit about it from the chalk angle

nikomatsakis (Dec 11 2019 at 19:58, on Zulip):

Right now chalk has a notion of "cannot prove" --

nikomatsakis (Dec 11 2019 at 19:59, on Zulip):

so e.g. trying to prove T: Send could yield that, and it would prevent specializations from being used

nikomatsakis (Dec 11 2019 at 19:59, on Zulip):

however, that's likely not quite what we want here, in that

nikomatsakis (Dec 11 2019 at 19:59, on Zulip):

if you had some code that relied on it being send

nikomatsakis (Dec 11 2019 at 19:59, on Zulip):

it would get an error

nikomatsakis (Dec 11 2019 at 20:00, on Zulip):

(well, maybe that is what we want..?)

nikomatsakis (Dec 11 2019 at 20:00, on Zulip):

put another way, leaving chalk aside, if you imagine that the result of saying "can I prove this?" is either yes/no/maybe

nikomatsakis (Dec 11 2019 at 20:01, on Zulip):

/me stops to think :)

Aaron Hill (Dec 11 2019 at 20:01, on Zulip):

So, we would error whenever we attempted to check a specialization that would require evaluating G: AutoTrait?

nikomatsakis (Dec 11 2019 at 20:01, on Zulip):

well, it wouldn't be an error

nikomatsakis (Dec 11 2019 at 20:01, on Zulip):

it wouldn't be able to decide if the spec applies or not

nikomatsakis (Dec 11 2019 at 20:01, on Zulip):

but that might not lead to an error

nikomatsakis (Dec 11 2019 at 20:01, on Zulip):

as it might not matter

nikomatsakis (Dec 11 2019 at 20:02, on Zulip):

e.g., if you were trying to prove something like <T as MyTrait>::Bar: Sized, you don't actually care if T: Send--i.e., you don't care if you took the specialization or not

nikomatsakis (Dec 11 2019 at 20:02, on Zulip):

there is a small 'fly in the ointment' though

Aaron Hill (Dec 11 2019 at 20:02, on Zulip):

In your <u32 as MyTrait>::Bar example, would we then use the unspecialised impl for G?

Aaron Hill (Dec 11 2019 at 20:02, on Zulip):

if the example were changed to involve generators, that is

nikomatsakis (Dec 11 2019 at 20:03, on Zulip):

ah, maybe since specialization is unstable, it's largely ok, but it's true that this compiles today

fn main() {
    let x = async move {

    };
    let y = gimme(x);
}

and it is only able to do so because we are able to first figure out that the generator type is Send so that we can resolve the type of y

nikomatsakis (Dec 11 2019 at 20:03, on Zulip):

In your <u32 as MyTrait>::Bar example, would we then use the unspecialised impl for G?

we would not use either impl

nikomatsakis (Dec 11 2019 at 20:04, on Zulip):

that is, in type-checking

nikomatsakis (Dec 11 2019 at 20:04, on Zulip):

er, I'm guessing you meant <G as MyTrait>::Bar, where G is a generator type

nikomatsakis (Dec 11 2019 at 20:04, on Zulip):

(or something that depends on a generator)

Aaron Hill (Dec 11 2019 at 20:04, on Zulip):

yeah, sorry for being unclear there

nikomatsakis (Dec 11 2019 at 20:05, on Zulip):

the idea would be that we just can't normalize that

nikomatsakis (Dec 11 2019 at 20:05, on Zulip):

we can't convert it to () or u32

Aaron Hill (Dec 11 2019 at 20:06, on Zulip):

What would happen for uses of the impl that don't involve associated types - e.g. calling a potentially specialised method?

Aaron Hill (Dec 11 2019 at 20:06, on Zulip):

I guess we don't actually need to know that during typeck, right?

nikomatsakis (Dec 11 2019 at 20:06, on Zulip):

nothing; we know that there exists some method, you could still call it, it's not until codgen time that we'd have to figure out exactly which one gets invoked

Aaron Hill (Dec 11 2019 at 20:08, on Zulip):

in the associated type example, would we just give up and error when a generator was involved in the normalization?

nikomatsakis (Dec 11 2019 at 20:09, on Zulip):

it depends I guess, I'm not sure exactly which example you mean

Aaron Hill (Dec 11 2019 at 20:09, on Zulip):

<G as MyTrait>::Bar

nikomatsakis (Dec 11 2019 at 20:10, on Zulip):

a lazy normalization strategy kind of affects this too

Aaron Hill (Dec 11 2019 at 20:10, on Zulip):

or some type involving a generator instead of G

nikomatsakis (Dec 11 2019 at 20:10, on Zulip):

i.e., the type of y right now is considered "unresolved" but conceivably it could just be assigned to <G as MyTrait>::Bar in a lazy norm strategy, and that's a perfectly valid type (that will be normalized if it must be, i.e., if some bit of code requires that to be u32)

nikomatsakis (Dec 11 2019 at 20:10, on Zulip):

right, but that's not a complete example

Aaron Hill (Dec 11 2019 at 20:11, on Zulip):

the gimme(x) example with let x = async move

nikomatsakis (Dec 11 2019 at 20:11, on Zulip):

so e.g. if you had

let x = async move { };
let y = gimme(x);
drop(y);

we don't really have to know the type of y, it's enough to know that it has some Sized type

nikomatsakis (Dec 11 2019 at 20:11, on Zulip):

but if you have

nikomatsakis (Dec 11 2019 at 20:11, on Zulip):
let x = async move { };
let y: u32 = gimme(x);

that's different

nikomatsakis (Dec 11 2019 at 20:12, on Zulip):

so depending on how we set things up, it could be that the first one builds, but the second one doesn't

nikomatsakis (Dec 11 2019 at 20:12, on Zulip):

e.g., because the type of y effectively gets inferred to the placeholder G::Bar, since we can't decide which specialization to use

Aaron Hill (Dec 11 2019 at 20:13, on Zulip):

I see. When this error occurred, would the user have any way to fix it (other than not using the trait in question)?

Aaron Hill (Dec 11 2019 at 20:14, on Zulip):

Things could be very deeply nested, so I'm not sure what kind of information the user could specify to resolve it

nikomatsakis (Dec 11 2019 at 20:15, on Zulip):

the bigger problem I think is code like this, which builds today:

fn gimme_send<T: Send>(x: T) {
    panic!()
}

fn main() {
    let x = async move {

    };
    gimme_send(x);
}

because this code only type-checks if the generator is Send

nikomatsakis (Dec 11 2019 at 20:15, on Zulip):

(sorry, it's not a problem, it's just a thing to remember)

nikomatsakis (Dec 11 2019 at 20:15, on Zulip):

I see. When this error occurred, would the user have any way to fix it (other than not using the trait in question)?

I think we'd have to add a mechanism

nikomatsakis (Dec 11 2019 at 20:16, on Zulip):

I'm not sure what that means, I guess it would be a declaration that the async move is Send

nikomatsakis (Dec 11 2019 at 20:16, on Zulip):

and maybe we can use some kind of "approx analysis" to avoid the need for that sometimes, too -- i.e., if we have an over-approx, we could (maybe?)check if that suffices

nikomatsakis (Dec 11 2019 at 20:17, on Zulip):

( in any case, I was just pondering how specialization should be modeled in chalk, I'm trying to map this to the chalk solver, and wondering if I had overlooked something there )

nikomatsakis (Dec 11 2019 at 20:18, on Zulip):

(ah, no, I guess it's ok)

nikomatsakis (Dec 11 2019 at 20:18, on Zulip):

sorry to keep mapping back to chalk, I can try to elaborate, I just find that a useful framework for thinking about this stuff

nikomatsakis (Dec 11 2019 at 20:20, on Zulip):

I think the way I'm thining about it right now is like this

Aaron Hill (Dec 11 2019 at 20:21, on Zulip):

Here's a different approach I'm thinking of (not sure if it will work):

nikomatsakis (Dec 11 2019 at 20:21, on Zulip):

we augment the system so that when you try to prove something (e.g., T: Foo), you can get back an answer like "yes if G" where G are some things that must be proven later. We already do something like this for region constraints and we are trying to build up some similar logic for coinduction anyway.

nikomatsakis (Dec 11 2019 at 20:22, on Zulip):

Such an answer is considered "ambiguous" in some sense, you can't know if it's true or false yet

nikomatsakis (Dec 11 2019 at 20:22, on Zulip):

This is basically the "mode" you added

nikomatsakis (Dec 11 2019 at 20:22, on Zulip):

i.e., the mode is "defer" G: Send goals

nikomatsakis (Dec 11 2019 at 20:23, on Zulip):

Here's a different approach I'm thinking of (not sure if it will work):

anyway, go for it :)

Aaron Hill (Dec 11 2019 at 20:26, on Zulip):

hmm, what I was thinking of might actually not work out

Aaron Hill (Dec 11 2019 at 20:26, on Zulip):

I was thinking that we didn't actually need to know the types of upvars when type-checking the parent - only the types of things local to the generator.

Aaron Hill (Dec 11 2019 at 20:26, on Zulip):

However, you can have something like:

Aaron Hill (Dec 11 2019 at 20:27, on Zulip):

async move { let myvar = some_fn(local_var, upvar) }

Aaron Hill (Dec 11 2019 at 20:27, on Zulip):

And the type of myvar might depend on upvar if some_fn is generic

Aaron Hill (Dec 11 2019 at 20:27, on Zulip):

So the typeck results from the parent can actually be relevant when determining which types live across suspend points

nikomatsakis (Dec 11 2019 at 20:29, on Zulip):

yeah it's all tangled up :)

Aaron Hill (Dec 11 2019 at 20:31, on Zulip):

though, on second thought - is it possible to combine that case with specialization of an associated type?

Aaron Hill (Dec 11 2019 at 20:32, on Zulip):

That would mean that 1) the parent is trying to compute a type (e.g. let a: u32 = <G as MyTrait>::MyType) while specializing on the generator, and 2) the generator is trying to use that type from the parent

Aaron Hill (Dec 11 2019 at 20:32, on Zulip):

I think that should cause a cycle error even if we kept the current generator auto-trait behavior (i.e using the GeneratorWitness types from HIR)

Aaron Hill (Dec 11 2019 at 20:33, on Zulip):

The parent needs to evaluate G: AutoTrait, but the constituent types (under any scheme) depend on an upvar that relies on the specialization of G: AutoTrait

Aaron Hill (Dec 11 2019 at 20:35, on Zulip):

So, I think there are two cases:
1) We have the kind of weird cycle that I just described. We have to emit a cycle error regardless of how we determine the consitutent types of G
2) We don't have this kind of cycle. This means that one of these cases is true:
2.1) We are specializing on the generator type, but the generator doesn't rely on the result of that specializtion (via an upvar)
2.2) We are not specializing on the generator type, and the generator uses an upvar
2.3) We are not specializing, and the generator does not use an upvar

Aaron Hill (Dec 11 2019 at 20:36, on Zulip):

If we're not specializing, then the existing 'delayed generator predicate' scheme works

Aaron Hill (Dec 11 2019 at 20:37, on Zulip):

If we are specializing, then I think we can go with something like this:

We comute some kind of 'incomplete mir' for the generator - it has the generator interior types filled in, but not upvars

Aaron Hill (Dec 11 2019 at 20:37, on Zulip):

err, rather

Aaron Hill (Dec 11 2019 at 20:38, on Zulip):

It does have upvars, which we can determine the types of because we're not specializing

Aaron Hill (Dec 11 2019 at 20:38, on Zulip):

We then run the analysis on that MIR, and use the results for the witness types

Aaron Hill (Dec 11 2019 at 20:38, on Zulip):

This is pretty complicated, but I think it should be completely transparent to users

Aaron Hill (Dec 11 2019 at 20:38, on Zulip):

and will not introduce errors in any casses where they did not already exist (e.g. the weird specialization + upvar cycle)

Aaron Hill (Dec 11 2019 at 20:39, on Zulip):

sorry, that ended up being way longer than I thought it would :smiley:

nikomatsakis (Dec 11 2019 at 20:39, on Zulip):

I admit i don't quite follow all that logic. I'll have to re-read it carefully. =)

nikomatsakis (Dec 11 2019 at 20:40, on Zulip):

I've probably got to run to do a few other things, but I think the idea of able to have "deferred" trait proving goals might be quite useful (as I noted, also for impl Trait). I feel like I can sort of understand how to model it in chalk, and then the question is mostly how we can ensure that those things eventually get proven.

Aaron Hill (Dec 11 2019 at 20:40, on Zulip):

The main idea is that if we're doing any kind of associated type specialization based on the generator, the generator itself cannot rely on that associated type specialization (via an upvar)

nikomatsakis (Dec 11 2019 at 20:40, on Zulip):

Yeah. I'm kind of taking that as a given in some sense.

nikomatsakis (Dec 11 2019 at 20:41, on Zulip):

I think it would effectively manifest as a kind of error -- i.e., we wouldn't be able to prove that the specialized impl applies

Aaron Hill (Dec 11 2019 at 20:41, on Zulip):

I think that fact lets us perform the needed analysis without hitting cycles

nikomatsakis (Dec 11 2019 at 20:41, on Zulip):

I guess I don't really like the idea of (e.g.) "incomplete MIR", it's sounding very complex

Aaron Hill (Dec 11 2019 at 20:41, on Zulip):

Yeah, I agree that it's not very great

nikomatsakis (Dec 11 2019 at 20:42, on Zulip):

That said, maybe there is some "reframing"

nikomatsakis (Dec 11 2019 at 20:43, on Zulip):

That is, the current setup where we do type-check to compute all the types etc, then build the MIR, doesn't quite seem fine-grained enough necessarily, maybe there is another way to draw the line .. e.g. I don't know producing some other kind of intermediate structure (more like HAIR, maybe) that we can use .. still sounds complex :)

Aaron Hill (Dec 11 2019 at 20:43, on Zulip):

Thinking about this more, I think we don't actually need the notion of 'incomplete MIR':

Aaron Hill (Dec 11 2019 at 20:47, on Zulip):

or perhaps not - this approach really is quite complicated

Aaron Hill (Dec 11 2019 at 20:49, on Zulip):

Oh, wait - I think I may have misunderstood how closrue type-checking works

Aaron Hill (Dec 11 2019 at 20:50, on Zulip):

I was thinking that the parent had a separate TypeckTables, which the child depended on

Aaron Hill (Dec 11 2019 at 20:50, on Zulip):

but actually, they use the same TypeckTables

Aaron Hill (Dec 11 2019 at 20:52, on Zulip):

I don't think that helps to simplify the complexity of the 'incomplete mir' approach, though

nikomatsakis (Dec 11 2019 at 21:04, on Zulip):

yeah, that's how it works, but in a way it's part of the problem

Aaron Hill (Dec 11 2019 at 21:06, on Zulip):

I wonder if we could just ban associated type specializations on generator types, when the specialization occurs in the same function as the generator

Aaron Hill (Dec 11 2019 at 21:06, on Zulip):

for the time being, that is

Aaron Hill (Dec 11 2019 at 21:07, on Zulip):

I think the error would almost never come up (you need to be using an unstable feature, and be specializing on associated types, and have generators/async fns involved)

Aaron Hill (Dec 11 2019 at 21:08, on Zulip):

it would leave room to decide what the actual behavior should be (a more complicated analysis, a more targeted error, something else)

Aaron Hill (Dec 11 2019 at 21:08, on Zulip):

I think all other cases are fine (if the specialization is in a different function, then we can certainly compute G: AutoTrait without hitting a cycle)

Last update: Jan 28 2020 at 00:45UTC