-
-
Notifications
You must be signed in to change notification settings - Fork 357
Generics overhaul & improvements #2324
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
Merged
Merged
Changes from all commits
Commits
Show all changes
47 commits
Select commit
Hold shift + click to select a range
28844a5
Overhaul analysis code for generics
FnControlOption 3471b8f
Determine whether a container is generic at type resolution
FnControlOption 6f4085b
Small cleanup
FnControlOption 8e55d1f
Avoid infinite recursion
FnControlOption 2bc26fd
Fix completions and semantic tokens for generic methods
FnControlOption f47667e
Add a few more tests
FnControlOption 8061b80
Resolve bound type parameters in decl literals
FnControlOption 4820d2e
Add some more tests
FnControlOption 034d387
Resolve bound type parameters in generic union declarations
FnControlOption 80b24ba
.
FnControlOption ff7471f
Call resolveGenericType inside resolveTypeWithContainer
FnControlOption b541bbc
Improve completions for function taking a generic struct arg
FnControlOption ab65325
Improve completions of decl literal for generic type
FnControlOption 942dae9
Improve completions of decl literal in generic decl
FnControlOption cdbb9c0
Resolve bound type params of recursive generic
FnControlOption 8034781
Replace `from` field with `container_type` in `DeclWithHandle`
FnControlOption ff9c458
Fix resolved type for decl literal on alias in generic type
FnControlOption 46b244e
.
FnControlOption b54e0c6
Avoid copying more type parameters than necessary
FnControlOption c79004f
.
FnControlOption 89e0b12
Revert hack that is no longer needed
FnControlOption 4994eef
Cleanup
FnControlOption 9568992
.
FnControlOption 09bf7e0
Fix infinite recursiion
FnControlOption 37a42d4
Merge branch 'master' into wip-generics
FnControlOption 3010924
.
FnControlOption e87047a
Don't return null from resolveGenericType
FnControlOption 48e59c5
.
FnControlOption ca5da86
Merge branch 'master' into wip-generics
FnControlOption 4068497
Todo: Fix infinite recursion with pointer to nested generic anytype
FnControlOption a14b69e
Fix infinite indirect recursion with pointer to generic anytype
FnControlOption 78468dd
.
FnControlOption f9501fb
.
FnControlOption 3d46090
Use a hash map for preventing infinite recursion
FnControlOption 6335ca5
Cleanup
FnControlOption 7436067
.
FnControlOption f9b21ce
Add helper functions to TokenWithHandle
FnControlOption f374869
.
FnControlOption 8152b81
Merge branch 'master' into wip-generics
FnControlOption 5fb5a8b
Apply requested changes from review
FnControlOption 7dbbfd8
Rename .generic to .type_parameter
FnControlOption eb12d6a
Rename `Function.return_type` to `return_value`
FnControlOption fa4c57a
Fix eql for array type (bug introduced in 0a28fce)
FnControlOption a4b183f
Merge branch 'master' into wip-generics
FnControlOption 3781645
Update todo's
FnControlOption 2a21b45
resolveReturnTypeOfFuncNode -> resolveValueTypeOfFuncNode
FnControlOption b8ac160
resolveValueTypeOfFuncNode -> resolveReturnValueOfFuncNode
FnControlOption File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Large diffs are not rendered by default.
Oops, something went wrong.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Large diffs are not rendered by default.
Oops, something went wrong.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,228 @@ | ||
fn Foo(T: type) type { | ||
return struct { | ||
fn bar(U: type, t: ?T, u: ?U) void { | ||
_ = .{ t, u }; | ||
} | ||
|
||
fn baz(U: type, t: T, u: U) T { | ||
return t + u; | ||
} | ||
|
||
fn qux(U: type, t: T, u: U) @TypeOf(t, u) { | ||
return t + u; | ||
} | ||
}; | ||
} | ||
|
||
const foo = Foo(u8){}; | ||
// ^^^ (Foo(u8))() | ||
|
||
// TODO this should be `fn (U: type, ?u8, ?U) void` | ||
const bar_fn = Foo(u8).bar; | ||
// ^^^^^^ (fn (type, ?u8, ?U) void)() | ||
|
||
const bar_call = Foo(u8).bar(i32, null, null); | ||
// ^^^^^^^^ (void)() | ||
|
||
// TODO this should be `fn (U: type, i32, U) i32` | ||
const baz_fn = Foo(i32).baz; | ||
// ^^^^^^ (fn (type, i32, U) i32)() | ||
|
||
const baz_call = Foo(i32).baz(u8, -42, 42); | ||
// ^^^^^^^^ (i32)() | ||
|
||
// TODO this should be `fn (U: type, u8, U) anytype` | ||
const qux_fn = Foo(u8).qux; | ||
// ^^^^^^ (fn (type, u8, U) u8)() | ||
|
||
// TODO this should be `i32` | ||
const qux_call = Foo(u8).qux(i32, 42, -42); | ||
// ^^^^^^^^ (u8)() | ||
|
||
fn fizz(T: type) ?fn () error{}!struct { ??T } { | ||
return null; | ||
} | ||
|
||
// TODO this should be `fn (T: type) ?fn () error{}!struct { ??T })()` | ||
const fizz_fn = fizz; | ||
// ^^^^^^^ (fn (type) ?fn () error{}!struct { ??T })() | ||
|
||
const fizz_call = fizz(u8); | ||
// ^^^^^^^^^ (?fn () error{}!struct { ??u8 })() | ||
|
||
comptime { | ||
// Use @compileLog to verify the expected type with the compiler: | ||
// @compileLog(foo); | ||
} | ||
|
||
fn Point1(comptime T: type) type { | ||
return struct { | ||
x: T, | ||
y: T, | ||
fn normSquared(self: Point1(T)) T { | ||
_ = self; | ||
// ^^^^ (Point1(T))() | ||
} | ||
}; | ||
} | ||
|
||
fn parameter(comptime T: type, in: T) void { | ||
_ = in; | ||
// ^^ (T)() | ||
} | ||
|
||
fn taggedUnion(comptime T: type, in: union(enum) { a: T, b: T }) void { | ||
switch (in) { | ||
.a => |a| { | ||
_ = a; | ||
// ^ (T)() | ||
}, | ||
.b => |b| { | ||
_ = b; | ||
// ^ (T)() | ||
}, | ||
} | ||
} | ||
|
||
fn Option(comptime T: type) type { | ||
return struct { | ||
item: ?T, | ||
const none: @This() = undefined; | ||
const alias = none; | ||
const default = init(); | ||
fn init() @This() {} | ||
}; | ||
} | ||
|
||
const option_none: Option(u8) = .none; | ||
// ^^^^^ (Option(u8))() | ||
|
||
const option_alias: Option(u8) = .alias; | ||
// ^^^^^^ (Option(u8))() | ||
|
||
const option_default: Option(u8) = .default; | ||
// ^^^^^^^^ (Option(u8))() | ||
|
||
const option_init: Option(u8) = .init(); | ||
// ^^^^^ (fn () Option(u8))() | ||
|
||
fn GenericUnion(T: type) type { | ||
return union { | ||
field: T, | ||
const decl: T = undefined; | ||
}; | ||
} | ||
|
||
const generic_union_decl = GenericUnion(u8).decl; | ||
// ^^^^^^^^^^^^^^^^^^ (u8)() | ||
|
||
const generic_union: GenericUnion(u8) = .{ .field = 1 }; | ||
// ^^^^^^^^^^^^^ (GenericUnion(u8))() | ||
|
||
const generic_union_field = generic_union.field; | ||
// ^^^^^^^^^^^^^^^^^^^ (u8)() | ||
|
||
const generic_union_tag = GenericUnion(u8).field; | ||
// ^^^^^^^^^^^^^^^^^ (unknown)() | ||
|
||
fn GenericTaggedUnion(T: type) type { | ||
return union(enum) { | ||
field: T, | ||
const decl: T = undefined; | ||
}; | ||
} | ||
|
||
const generic_tagged_union_decl = GenericTaggedUnion(u8).decl; | ||
// ^^^^^^^^^^^^^^^^^^^^^^^^^ (u8)() | ||
|
||
const generic_tagged_union: GenericTaggedUnion(u8) = .{ .field = 1 }; | ||
// ^^^^^^^^^^^^^^^^^^^^ (GenericTaggedUnion(u8))() | ||
|
||
const generic_tagged_union_field = generic_tagged_union.field; | ||
// ^^^^^^^^^^^^^^^^^^^^^^^^^^ (u8)() | ||
|
||
const generic_tagged_union_tag = GenericTaggedUnion(u8).field; | ||
// ^^^^^^^^^^^^^^^^^^^^^^^^ (@typeInfo(GenericTaggedUnion(u8)).@"union".tag_type.?)() | ||
|
||
fn GenericEnum(T: type) type { | ||
return enum { | ||
field, | ||
const decl: T = undefined; | ||
}; | ||
} | ||
|
||
const generic_enum_decl = GenericEnum(u8).decl; | ||
// ^^^^^^^^^^^^^^^^^ (u8)() | ||
|
||
const generic_enum: GenericEnum(u8) = .field; | ||
// ^^^^^^^^^^^^ (GenericEnum(u8))() | ||
|
||
const generic_enum_field = generic_enum.field; | ||
// ^^^^^^^^^^^^^^^^^^ (unknown)() | ||
|
||
const generic_enum_tag = GenericEnum(u8).field; | ||
// ^^^^^^^^^^^^^^^^ (GenericEnum(u8))() | ||
|
||
fn GenericStruct(T: type) type { | ||
return struct { | ||
field: T, | ||
const decl: T = undefined; | ||
}; | ||
} | ||
|
||
const generic_struct_decl = GenericStruct(u8).decl; | ||
// ^^^^^^^^^^^^^^^^^^^ (u8)() | ||
|
||
const generic_struct: GenericStruct(u8) = .{ .field = 1 }; | ||
// ^^^^^^^^^^^^^^ (GenericStruct(u8))() | ||
|
||
const generic_struct_field = generic_struct.field; | ||
// ^^^^^^^^^^^^^^^^^^^^ (u8)() | ||
|
||
const generic_struct_tag = GenericStruct(u8).field; | ||
// ^^^^^^^^^^^^^^^^^^ (unknown)() | ||
|
||
fn Map(Context: type) type { | ||
return struct { | ||
unmanaged: MapUnmanaged(Context), | ||
ctx: Context, | ||
const Self = @This(); | ||
fn clone(self: Self) Self { | ||
const unmanaged = self.unmanaged.cloneContext(self.ctx); | ||
// ^^^^^^^^^ (MapUnmanaged(either type))() | ||
return .{ .unmanaged = unmanaged, .ctx = self.ctx }; | ||
} | ||
fn clone2(self: Self) Self { | ||
const unmanaged = self.unmanaged.cloneContext2(self.ctx); | ||
// ^^^^^^^^^ (MapUnmanaged(*either type))() | ||
return .{ .unmanaged = unmanaged, .ctx = self.ctx }; | ||
} | ||
}; | ||
} | ||
|
||
fn MapUnmanaged(Context: type) type { | ||
return struct { | ||
size: u32, | ||
const Self = @This(); | ||
fn clone(self: Self) Self { | ||
return self.cloneContext(@as(Context, undefined)); | ||
} | ||
fn cloneContext(self: Self, new_ctx: anytype) MapUnmanaged(@TypeOf(new_ctx)) { | ||
_ = self; | ||
} | ||
fn clone2(self: Self) Self { | ||
return self.cloneContext2(@as(Context, undefined)); | ||
} | ||
fn cloneContext2(self: Self, new_ctx: anytype) MapUnmanaged(*@TypeOf(new_ctx)) { | ||
_ = self; | ||
} | ||
}; | ||
} | ||
|
||
const some_list: std.ArrayListUnmanaged(u8) = .empty; | ||
// ^^^^^^^^^ (ArrayListAlignedUnmanaged(u8))() | ||
|
||
const some_list_items = some_list.items; | ||
// ^^^^^^^^^^^^^^^ ([]u8)() | ||
|
||
const std = @import("std"); |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.