Stream: t-compiler/wg-rls-2.0

Topic: for loops & ? operator


Florian Diebold (Jun 22 2019 at 13:34, on Zulip):

I added issues with hopefully adequate mentoring instructions for for loops and the ? operator. I guess this would be a good place for questions (and/or disagreements about handling them directly instead of desugaring) ;)

matklad (Jun 22 2019 at 13:41, on Zulip):

I'd like to go via desugaring, but not as the initial implementation. Desugaring is tricky for IDEs, so it makes sense to experiment with it more.

Florian Diebold (Jun 22 2019 at 13:55, on Zulip):

Yeah. In any case, I think everything we need to build for the 'handling it directly' approach we would also need for the desugaring approach.

matklad (Jun 22 2019 at 14:05, on Zulip):

That's true, and, for desugaring, I think it maybe makes sense to to a bit of up-front design of the hir::Body, scopes and source maps. I feel like the current incarnation is not the best one: in particular, it seems like we should name-resolve expressions when lowering to the Body.

levi (Jun 27 2019 at 02:08, on Zulip):

i know someone has already taken this on github - but i was giving this a stab on sunday and got stuck at resolve_obligations_as_possible on the line let (solution, canonicalized) = match &obligation where the compiler keeps on not allowing me to have a generic over Canonicalized<T>. if i could get past that (or if zbelial solves it) - imight be able to work on the ? inference

matklad (Jun 27 2019 at 11:55, on Zulip):

@levi could you push your in-progress branch somewhere? It would be easier to see the problem that way.

levi (Jun 27 2019 at 12:09, on Zulip):

https://github.com/urbandove/rust-analyzer/tree/for-loops currently - i think im supposed to add a trait - but i couldnt get that wokring

matklad (Jun 27 2019 at 12:16, on Zulip):

So, that's the limitation of Rust: you have match arms of different types, and in Rust, unlike something Java, you can't unify those to a super-type

matklad (Jun 27 2019 at 12:17, on Zulip):

The simplest fix would be to just pull the code after the match branch inside:

    fn resolve_obligations_as_possible(&mut self) {
        let obligations = mem::replace(&mut self.obligations, Vec::new());
        for obligation in obligations {
            match &obligation {
                Obligation::Trait(tr) => {
                    let canonicalized = self.canonicalizer().canonicalize_trait_ref(tr.clone());
                    let (solution, canonicalized) = (
                        self.db.implements(
                            self.resolver.krate().unwrap(),
                            canonicalized.value.clone(),
                        ),
                        canonicalized,
                    );
                    match solution {
                        Some(Solution::Unique(substs)) => {
                            canonicalized.apply_solution(self, substs.0);
                        }
                        Some(Solution::Ambig(Guidance::Definite(substs))) => {
                            canonicalized.apply_solution(self, substs.0);
                            self.obligations.push(obligation);
                        }
                        Some(_) => {
                            // FIXME use this when trying to resolve everything at the end
                            self.obligations.push(obligation);
                        }
                        None => {
                            // FIXME obligation cannot be fulfilled => diagnostic
                        }
                    }
                }
                Obligation::Projection(pr) => {
                    let canonicalized = self.canonicalizer().canonicalize_projection(pr.clone());
                    let (solution, canonicalized) = (
                        self.db
                            .normalize(self.resolver.krate().unwrap(), canonicalized.value.clone()),
                        canonicalized,
                    );
                    match solution {
                        Some(Solution::Unique(substs)) => {
                            canonicalized.apply_solution(self, substs.0);
                        }
                        Some(Solution::Ambig(Guidance::Definite(substs))) => {
                            canonicalized.apply_solution(self, substs.0);
                            self.obligations.push(obligation);
                        }
                        Some(_) => {
                            // FIXME use this when trying to resolve everything at the end
                            self.obligations.push(obligation);
                        }
                        None => {
                            // FIXME obligation cannot be fulfilled => diagnostic
                        }
                    }
                }
            };
        }
    }
matklad (Jun 27 2019 at 12:17, on Zulip):

The duplicated part can be extracted into a generic function to make this nicer

matklad (Jun 27 2019 at 12:18, on Zulip):

I am not sure if that is the right code to begin with, I am not really proficient with chalk, but that at lest fixes the compilation error :D

matklad (Jun 27 2019 at 12:18, on Zulip):

@levi does that help?

Florian Diebold (Jun 27 2019 at 14:03, on Zulip):

another possibility might be canonicalizing the whole Obligation :thinking: in addition to canonicalize_trait_ref and canonicalize_projection, you'd have canonicalize_obligation, and you'd call that before the match and then do the match on the canonicalized obligation, and the rest could be generic again (I think)

levi (Jun 27 2019 at 14:52, on Zulip):

i was thinking about that - it just looked overly verbose to me - and though there was an easier way.
ill try that later today and see how it goes. and maybe after if i get that working i can have a look at trying what @Florian Diebold suggested

Last update: Nov 12 2019 at 16:45UTC