-
Notifications
You must be signed in to change notification settings - Fork 1.6k
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
Type annotations "look through" typedefs, which can be confusing. #1666
Comments
Yeah, I wonder what is the correct way to deal with type aliases.... Currently we eagerly normalize them, which causes the reported issue. I wonder if we should have That should make the following code possible ideally (which is currently an error in rustc):
|
I personally don't think we should treat type aliases as a separate type. That seems like too much of a change from Rust's actual type system. (Also note that type aliases can alias to any type, not just ADTs.) What I imagine is keeping track of where a type came from during type inference (either using a side table or using additional fields on the types), and then using that to represent the type in the way it was originally written (i.e. with type aliases, using the same path, leaving out default type parameters if they were left out there, etc.). Though I have to admit it's only a vague notion so far 😄 |
(Or maybe put another way, it seems a layering violation to fix a 'display' issue like this by changing the type system.) |
struct Unit;
type UnitAlias = Unit;
fn new_unit_alias() -> UnitAlias { Unit }
let a = new_unit_alias();
let b: Unit = a; Should |
I think Maybe we would need a setting or an option to show 'normalized' types though. |
@flodiebold 👍 for both. |
@flodiebold yeah, doing this for display is centrally both wrong and insufficient (there are cases where you need to guess aliases back anyway). However, fixing
seems like a good idea, if that's actually possible (don't know what it takes to unify Also, this seems like a really good question for type-inference libraryfication, and I hope we'll start on than after nikomatsakis is back. |
I completely agree that changing the type system for formatting purposes is wrong. Actually I think there are two separate issues here, one about typedefs and one about paths. To state the second one more clearly, what if we just had this: struct Foo {
inner: blah::Foo,
} then how should we display the type of |
This is a bit of a tangent, but is anyone aware of what heuristics Clang uses in its error messages? C++ std lib types can be horrible (pages and pages of template crap), but Clang diagnostics seem to usually choose a spelling that is reasonably easy to understand. |
It would be so cool if type aliases could be preserved in the user displayed types, at least to some degree. In the following example/screenshot, the function returns the type Using type aliases would help users see through the too-complex types, and help them write better code too (use the type aliases). The dimensionality information - the 3 - is not visible in the abbreviated full type. |
If I don't limit the length of inlays types ( In that project I define type aliases for vectors of uom quantities. I would like to see those type aliases used as inlays and not the full length exact type. Thanks! |
Another thread on this regard: https://rust-lang.zulipchat.com/#narrow/stream/185405-t-compiler.2Frust-analyzer/topic/Type.20aliases.20in.20inlay.20hints that makes me reconsider the labels we have on this one. |
While a hard problem, I think the win for users can be immense. Does unactionable mean that we can still work on trying to define a solvable variant of the problem? |
Unactionable doesn't mean anyone is prevented from working on it in any way, just that we don't see a direct way of making progress on it right now. |
To just give a example involving diesel where rust-analyzer shows private types as type hint: #[macro_use] extern crate diesel; // 1.4.6
use diesel::prelude::*;
table! {
users {
id -> Integer,
name -> Text,
}
}
fn test() {
let f = users::table.filter(users::name.eq("bar"));
} which shows |
Would it be possible to have like a setting |
What about generally trying to always using type alias for displaying types when they decrease complexity? We can define "complexity" as sum of generic arg counts, e.g. This doesn't solve the problem completely, but is a step forward with relatively smaller change, and it is something that we may want to keep even when we support type aliases properly. |
The type of a Particularly with FFI code where the type's width can vary by platform, the stable API is often not "you can use i32" here, it's "you can use c_int here, whatever width that is" |
Yes, that wouldn't help in the |
ah, haha, yeah |
I personally would like to have at least some notion of type aliases. I recently had Another thing I want to mention is the go extension for VSCode, which shows type aliases. I don't know to what extend, but for them it seems to work. Maybe their approach can be a solution? |
In the hover text (since there is more room there than inlay hints), I would find it very useful to actually display the full aliasing stack:
This is (kind of) a preview what successive |
Today I ran into a problem I think is related to this but in a bad way. I used a code action to implement the missing members of actix-session::storage::SessionStore for my struct and when it populated the types it ended up giving me the alias (SessionState) that crate uses internally for HashMap<String, String>. SessionState is private to the crate so I can't use it and ended up confused for a while until I figured out what it really was. |
I don't know if it's useful to point out rust analyzer currently appears inconsistent. Given: type PacketIndex = SeqIndex; Struct info shows base type ( Function signature shows alias ( Parameter info shows base type again: Is there something special about the function signature that lets it work as expected that can't be used for the other cases? (like, I dunno, it's just copy/pasting the raw text with no semantic understanding or something) I can also do stuff like "Show all references to |
The difference is where the rendering of these derive their information from, the struct hover shows things based off of the non lowered forms (so we retain aliases as we never resolved them), where as function hovers actually re-render the fully resolved things. It is unrelatd to the concrete issue being asked about here though as that only works on the fully lowered type system information. |
blah.rs:
lib.rs:
Rust-analyzer reports the type of
_x
to beFoo
, which is quite confusing -- it would be better asBlahFoo
or evenblah::Foo
The text was updated successfully, but these errors were encountered: