Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

unnormalized projections in writeback may contain infer vars #12

Open
lcnr opened this issue Mar 23, 2023 · 6 comments
Open

unnormalized projections in writeback may contain infer vars #12

lcnr opened this issue Mar 23, 2023 · 6 comments

Comments

@lcnr
Copy link
Owner

lcnr commented Mar 23, 2023

If we have some <T as Id<?x>>::Assoc in hir typeck and the current impl normalizes that to T before writeback but is unable to infer ?x, then lazy norm would result in an inference error.

It seems like the following currently errors on stable, figure out why

trait Id<T: ?Sized> {
    type Assoc;
}

impl<T, U: ?Sized> Id<U> for T {
    type Assoc = T;
}

fn foo<T: Default>() -> T {
    <T as Id<_>>::Assoc::default()
}
@compiler-errors
Copy link

compiler-errors commented Mar 23, 2023

It seems like the following currently errors on stable, figure out why

This is expected behavior, because we resolve and encode the type of all hir::Ty nodes in the writeback results for foo, and _ is not the target of any diverging ! -> () fallback, it's not constrained to () during fallback or anything like that.

@compiler-errors
Copy link

compiler-errors commented Mar 23, 2023

I'm not sure if it's possible to come up with an example that has unconstrained infer vars in a projection in the new solver, without also having some "type annotations needed" error even on stable?

@compiler-errors
Copy link

compiler-errors commented Mar 27, 2023

Actually, nevermind! This happens with closure substs, specifically the tupled upvar subst:

fn main() {
    let mut x: Vec<_> = vec![];
    x.extend(Some(1i32).into_iter().map(|x| x));
}

@compiler-errors
Copy link

Also, pretty easy repro of the problem I guess:

trait Mk {
    type Assoc;
}
fn mk<T: Mk<Assoc = i32>>(t: T) -> T::Assoc {
    0
}

trait Bar {}
impl Bar for () {}
impl<T: Bar> Mk for T {
    type Assoc = i32;
}

fn main() {
    let mut x = Default::default();
    let y = mk(x);
    x = ();
}

@lcnr
Copy link
Owner Author

lcnr commented Mar 27, 2023

how does the second example work? don't we constrain T to () here so the type of y should be <() as Mk>::Assoc?

also confused about the first example 🤔 the projection is <<Map<std::option::IntoIter<i32>, [main::{closure#0} closure_substs=(unavailable) substs=[i16, extern "rust-call" fn((i32,)) -> i32, _#21t]]> as Iterator>::Item>, but shouldn't we infer _#21t(the closure upvars), to simply be () here?

@compiler-errors
Copy link

compiler-errors commented Mar 27, 2023

In both examples, we emit alias-relate goals instead of simply equating the projection ty to the infer-var of the let-bindings.

this is because we generalize the ty of the projection, since the let binding's infer var cannot name the projection type (it was created when the universe was still 0).

these alias-relate goals both hold trivially via the normalizes-to branch of the code, so we never end up relating the projection substs, and the infer var remains unconstrained in both examples.

that last part seems like it may be a slightly separate issue about alias-relate causing inference to be weaker... I'll file another issue when I wake up. edit: #13

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants