Join GitHub today
GitHub is home to over 31 million developers working together to host and review code, manage projects, and build software together.
Sign upType inference breakage on beta #41677
Comments
sfackler
added
the
regression-from-stable-to-beta
label
May 1, 2017
This comment has been minimized.
This comment has been minimized.
|
minified: #![allow(unused_variables, dead_code)]
use std::marker::PhantomData;
trait Handle {
type Inner;
}
struct ResizingHandle<H>(PhantomData<H>);
impl<H> Handle for ResizingHandle<H> {
type Inner = H;
}
struct Receiver<T, H: Handle<Inner=T>>(PhantomData<H>);
fn channel<T>(size: usize) -> Receiver<T, ResizingHandle<T>> {
let rx = Receiver(PhantomData);
rx
}
fn main() {
} |
nikomatsakis
added
the
T-compiler
label
May 1, 2017
This comment has been minimized.
This comment has been minimized.
|
triage: P-high |
rust-highfive
added
the
P-high
label
May 1, 2017
nikomatsakis
self-assigned this
May 1, 2017
This comment has been minimized.
This comment has been minimized.
|
So, I have a branch which fixes this by adding /// Result from a generalization operation. This includes
/// not only the generalized type, but also a bool flag
/// indicating whether further WF checks are needed.q
struct Generalization<'tcx> {
ty: Ty<'tcx>,
/// If true, then the generalized type may not be well-formed,
/// even if the source type is well-formed, so we should add an
/// additional check to enforce that it is. This arises in
/// particular around 'bivariant' type parameters that are only
/// constrained by a where-clause. As an example, imagine a type:
///
/// struct Foo<A, B> where A: Iterator<Item=B> {
/// data: A
/// }
///
/// here, `A` will be covariant, but `B` is
/// unconstrained. However, whatever it is, for `Foo` to be WF, it
/// must be equal to `A::Item`. If we have an input `Foo<?A, ?B>`,
/// then after generalization we will wind up with a type like
/// `Foo<?C, ?D>`. When we enforce that `Foo<?A, ?B> <: Foo<?C,
/// ?D>` (or `>:`), we will wind up with the requirement that `?A
/// <: ?C`, but no particular relationship between `?B` and `?D`
/// (after all, we do not know the variance of the normalized form
/// of `A::Item` with respect to `A`). If we do nothing else, this
/// may mean that `?D` goes unconstrained (as in #41677). So, in
/// this scenario where we create a new type variable in a
/// bivariant context, we set the `needs_wf` flag to true. This
/// will force the calling code to check that `WF(Foo<?C, ?D>)`
/// holds, which in turn implies that `?C::Item == ?D`. So once
/// `?C` is constrained, that should suffice to restrict `?D`.
needs_wf: bool,
}@arielb1 I opted for this strategy instead of adding explicit WF requirements to local variables because I was concerned about "intermediate" types that might wind up unconstrained. It seems like the code should be able to expect that, whenever we create a type variable, that type variable will be inferred to something WF as long as it is only related to WF types. However, as I write this comment, I suppose that I can't think of a place where some intermediate type might appear that would be unconstrained. e.g., I could imagine types that get "autoderef'd" away before they hit a local variable, but those would have to be custom deref impls, and I suppose that we would place WF requirements at the point where we call deref anyway. So I could also try adding WF constraints to locals. Still, this approach seems maybe a mite more targeted? (I'm not really sure how often we generalize types that have type variables in bivariant positions, but it seems like it would likely be less often than we declare local variables.) |
Diggsey commentedMay 1, 2017
This code compiles on stable, but fails on beta (playground link):
Error message: