-
Notifications
You must be signed in to change notification settings - Fork 13.1k
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
New inference scheme #15955
New inference scheme #15955
Conversation
There are some FIXMEs still in place concerning better tracking of "expected vs required" types for error messages. I'm not sure how important that is, shouldn't be too hard to fix properly. cmr did a graph of performance: http://i.imgur.com/JKFv3oX.png despite the labels, this PR is the red line. |
expr: &ast::Expr, | ||
freevars: &[freevars::freevar_entry]) { | ||
/*! | ||
* There is currently a rule that procs that they can only |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: "for procs"
@nikomatsakis Does this close any P-backcompat-lang issues (part of #5527)? |
After re-reading your blog post, this scheme right now assumes that lifetimes are the only way to get subtyping right now (your post says it can be extended to e.g. struct subtyping if necessary). What about trait objects, does that not count as subtyping? You can't say trait Foo {
fn foo(&self);
}
impl Foo for uint {
fn foo(&self) {
println!("foo: {}", *self);
}
}
pub fn main() {
let x: Box<Foo+Send> = box 42u;
let y: &Box<Foo+Send> = &x;
let z: &Box<Foo> = y;
z.foo();
} How does your new scheme handle this? |
Trait object "subtyping" has to be handled via coercions. You will see why if you try to sketch out how it must be handled at runtime. |
@pcwalton Not that I want true trait object subtyping as a feature, but why can't you handle it with standard single inheritance vtables? Or were you referring to the general case with multiple trait bounds? |
The general case with multiple trait bounds. Trait inheritance isn't single inheritance. The only solution would be something like C++'s virtual inheritance with multiple trees of vtables, which is… not a road I want to go down. :) |
I have never looked at the implementation of trait objects in Rust. I can definitely think of schemes that would allow trait object subtyping to work without coercion, but I assume the current scheme uses a fixed index into a table of function pointers, and that's going to be faster than any subtyping-compatible solution. |
On Thu, Jul 24, 2014 at 12:29:16PM -0700, Kevin Ballard wrote:
Good point. I had overlooked that source of subtyping. That said, it |
I should mention that this PR appears to fix issue #15244 for me. |
@pcwalton @kballard Supporting upcasting in trait objects, given multiple inheritance, is absolutely trivial. |
To elaborate on what @eddyb said: Today, if you have a trait hierachy that looks somewhat like this: trait A { ... }
trait B { ... }
trait AB: A + B { ... } Then for the usage of a trait object the compiler emits these vtables for a given type:
If we instead change the compiler to emit this vtable instead:
Then upcasting becomes a simple slicing operation of the vtable with statically known indices at the point of the upcast. |
@kballard: I actually explored such situations a bit today (raw notes are at https://gist.github.com/Kimundi/e3e292188221ee8afdf2) While its certainly true that there is duplication, it actually often ends up as a win because you can (in theory) make all vtables of a supertrait point into vtables of a subtrait. Besides, is a few pointer more here and there such a big deal? Or are there other considerations than just binary size? |
Regarding the object type relation, it is somewhat off topic, I am preparing an RFC. I see no reason that the new inference scheme can accommodate whatever subtyping relation we ultimately elect to have, though for various reasons I am inclined to have subtyping only on the object lifetime bound and prefer coercion for the rest. I will describe those reasons in the RFC. |
Regarding this branch in general, I am rebasing it on top of PR #16453, because that branch cleans up how we propagate constraints for 'static, making some of the more invasive refactoring on this branch unnecessary. It may still be worth reviewing the "main commit" here (which is the final one) independently just so speed things up. Will discuss with @pcwalton offline. |
Rebased. All tests pass locally. Note that the history includes commits that are part of PR #16453. |
Looks good to me modulo a couple of trivial nits. |
…cro rather than if_ok!
0ced472
to
3ed4a42
Compare
61a3f43
to
8b710cf
Compare
Rebased and updated. Also added a new test showing clearly where the older algorithm could fall down on perfectly reasonable code. (That example was from actual code that was failing to compile; took me a while to trace down the root cause. Imagine my delight to discover that the new inference algorithm would have fixed it.) |
…t most one type, and region variables are introduced as needed
9d72a8d
to
6e27c2f
Compare
…eme, r=pcwalton The inference scheme proposed in <http://smallcultfollowing.com/babysteps/blog/2014/07/09/an-experimental-new-type-inference-scheme-for-rust/>. This is theoretically a [breaking-change]. It is possible that you may encounter type checking errors, particularly related to closures or functions with higher-ranked lifetimes or object types. Adding more explicit type annotations should help the problem. However, I have not been able to make an example that *actually* successfully compiles with the older scheme and fails with the newer scheme. f? @pcwalton, @pnkfelix
Lifetime inference in some parts of racer appears to have been broken by rust-lang/rust#15955. Adding explicit lifetime parameters resolves racer-rust#46.
The inference scheme proposed in http://smallcultfollowing.com/babysteps/blog/2014/07/09/an-experimental-new-type-inference-scheme-for-rust/.
This is theoretically a [breaking-change]. It is possible that you may encounter type checking errors, particularly related to closures or functions with higher-ranked lifetimes or object types. Adding more explicit type annotations should help the problem. However, I have not been able to make an example that actually successfully compiles with the older scheme and fails with the newer scheme.
f? @pcwalton, @pnkfelix