From 766e6a2cc00de47dff33fb17fba8bdc49e4d8ff2 Mon Sep 17 00:00:00 2001 From: dobkeratops Date: Tue, 1 Jul 2014 21:44:37 +0100 Subject: [PATCH 01/39] added relative use mod import rfc --- active/0000-relative-use-mod-imports.md | 60 +++++++++++++++++++++++++ 1 file changed, 60 insertions(+) create mode 100644 active/0000-relative-use-mod-imports.md diff --git a/active/0000-relative-use-mod-imports.md b/active/0000-relative-use-mod-imports.md new file mode 100644 index 00000000000..a91adf6a101 --- /dev/null +++ b/active/0000-relative-use-mod-imports.md @@ -0,0 +1,60 @@ +- Start Date: 2014-06-01 +- RFC PR #: (leave this empty) +- Rust Issue #: (leave this empty) + +# Summary + +introduce ```use mod ...``` as a fused relative module import and namespace 'use' + +# Motivation + +## versatility for compile units +consider moving between the extremes of one compilation unit per file, and an entire project as one compilation unit - with the existing use/mod behaviour, you must refactor how modules are brought in and how components are referenced when moving between these extremes. + +Relative paths would allow greater flexibility when wanting to treat project subtrees as seperate libraries. + +A build system would be at liberty to cache any appropriate subtree equivalently to a crate under the current system. + +## learning curve +The seperate absolute and relative paths, and mod / use statements are a tripping point for new users + +## tooling +with a project setup this way, a tool can locate definitions starting at the 'current' file and spidering outward. While working on a project, one may have code in different component libraries open,needing changes; Under the current system, each of which would have different absolute paths. + +## simpler imports +eliminate the need for seperate ```mod.rs``` files within directories + +# Detailed design + +use mod would look for a file relative to the current locatoin + +given some source files in +foo.rs +bar.rs +baz/qux.rs +../qaz.rs + +from foo.rs, +```use mod bar``` +```use mod baz::qux``` +```use mod super::qaz``` + +would add these files to the project, and make bar,baz,quz available as qualifiers to reference symbols in these files. ```use``` statements would bring more individual symbols in, or longer paths could be written to access subtrees of these modules. + +Each file referenced would in turn be able to bring more files in. + +from qux.rs, +```use mod super::super::qaz``` +would make ```qaz``` available. + +item paths would still reflect the directory-structure: - when a series of siblings reference eachother, one would not be able to follow this graph to reach symbols. + +# Drawbacks + +heirachical 'use' paths have their own problems. When moving sources up or down the directory tree, refactoring would still be needed; + +one might need references to a long string of ```super::super::..``` statements to refer to symbols in the project root. + +The behaviour of the standard prelude would not seem as consistent with this scheme. + + From d805fd0fd13655556ebc7c3a1fafbc5531e5eea7 Mon Sep 17 00:00:00 2001 From: dobkeratops Date: Tue, 1 Jul 2014 21:48:08 +0100 Subject: [PATCH 02/39] Update 0000-relative-use-mod-imports.md --- active/0000-relative-use-mod-imports.md | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/active/0000-relative-use-mod-imports.md b/active/0000-relative-use-mod-imports.md index a91adf6a101..f19a74d6b2b 100644 --- a/active/0000-relative-use-mod-imports.md +++ b/active/0000-relative-use-mod-imports.md @@ -4,16 +4,16 @@ # Summary -introduce ```use mod ...``` as a fused relative module import and namespace 'use' +introduce ```use mod ...;``` as a fused relative module import and namespace 'use' # Motivation ## versatility for compile units -consider moving between the extremes of one compilation unit per file, and an entire project as one compilation unit - with the existing use/mod behaviour, you must refactor how modules are brought in and how components are referenced when moving between these extremes. +consider moving between the extremes of one compilation unit per file, and an entire project as a single compilation unit - with the existing use/mod behaviour, you would have to refactor how modules are brought in and how components are referenced when moving between these extremes. Relative paths would allow greater flexibility when wanting to treat project subtrees as seperate libraries. -A build system would be at liberty to cache any appropriate subtree equivalently to a crate under the current system. +A build system would be at liberty to cache any appropriate subtree equivalently to a library crate. ## learning curve The seperate absolute and relative paths, and mod / use statements are a tripping point for new users @@ -51,6 +51,8 @@ item paths would still reflect the directory-structure: - when a series of sibli # Drawbacks +Replicates functionality available with use, mod and #[path=...] directives, and is a slightly different mentality to the existing system. + heirachical 'use' paths have their own problems. When moving sources up or down the directory tree, refactoring would still be needed; one might need references to a long string of ```super::super::..``` statements to refer to symbols in the project root. From 1c9287f9185033ecf0dfea6b08819267d2869b55 Mon Sep 17 00:00:00 2001 From: dobkeratops Date: Tue, 1 Jul 2014 21:53:50 +0100 Subject: [PATCH 03/39] Update 0000-relative-use-mod-imports.md --- active/0000-relative-use-mod-imports.md | 21 ++++++++++----------- 1 file changed, 10 insertions(+), 11 deletions(-) diff --git a/active/0000-relative-use-mod-imports.md b/active/0000-relative-use-mod-imports.md index f19a74d6b2b..dd40beaa902 100644 --- a/active/0000-relative-use-mod-imports.md +++ b/active/0000-relative-use-mod-imports.md @@ -9,9 +9,10 @@ introduce ```use mod ...;``` as a fused relative module import and namespace 'us # Motivation ## versatility for compile units -consider moving between the extremes of one compilation unit per file, and an entire project as a single compilation unit - with the existing use/mod behaviour, you would have to refactor how modules are brought in and how components are referenced when moving between these extremes. -Relative paths would allow greater flexibility when wanting to treat project subtrees as seperate libraries. +Consider moving between the extremes of one compilation unit per file, and an entire project as a single compilation unit - with the existing use/mod behaviour, you would have to refactor how modules are brought in and how components are referenced when moving between these extremes. + +Relative paths would allow greater flexibility when wanting to treat project subtrees as seperate libraries, or vica versa. A build system would be at liberty to cache any appropriate subtree equivalently to a library crate. @@ -34,18 +35,16 @@ bar.rs baz/qux.rs ../qaz.rs -from foo.rs, -```use mod bar``` -```use mod baz::qux``` -```use mod super::qaz``` +from foo.rs, the following statements +```use mod bar;``` +```use mod baz::qux;``` +```use mod super::qaz;``` -would add these files to the project, and make bar,baz,quz available as qualifiers to reference symbols in these files. ```use``` statements would bring more individual symbols in, or longer paths could be written to access subtrees of these modules. +would add these files to the project, and make bar,baz,quz available as qualifiers to reference symbols of those files within foo.rs . ```use``` statements would bring more individual symbols in, or longer paths could be written to access subtrees of these modules. -Each file referenced would in turn be able to bring more files in. +Each individual file would in turn be able to bring in its own relative files. -from qux.rs, -```use mod super::super::qaz``` -would make ```qaz``` available. +eg if qux.rs contained the statement ```use mod super::super::qaz;``` , ```../qaz.rs``` would be brought into the project, although 'foo.rs' would still need an additional ```use super::qaz``` to reference it's symbols. item paths would still reflect the directory-structure: - when a series of siblings reference eachother, one would not be able to follow this graph to reach symbols. From 62533203c332325598f2ff912cffe88d899b693b Mon Sep 17 00:00:00 2001 From: dobkeratops Date: Tue, 1 Jul 2014 22:00:01 +0100 Subject: [PATCH 04/39] Update 0000-relative-use-mod-imports.md --- active/0000-relative-use-mod-imports.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/active/0000-relative-use-mod-imports.md b/active/0000-relative-use-mod-imports.md index dd40beaa902..b351fe11d62 100644 --- a/active/0000-relative-use-mod-imports.md +++ b/active/0000-relative-use-mod-imports.md @@ -4,7 +4,7 @@ # Summary -introduce ```use mod ...;``` as a fused relative module import and namespace 'use' +introduce ```use mod ...;``` as a fused module import and namespace 'use', using relative filename/module paths # Motivation @@ -23,7 +23,7 @@ The seperate absolute and relative paths, and mod / use statements are a trippin with a project setup this way, a tool can locate definitions starting at the 'current' file and spidering outward. While working on a project, one may have code in different component libraries open,needing changes; Under the current system, each of which would have different absolute paths. ## simpler imports -eliminate the need for seperate ```mod.rs``` files within directories +eliminate the need for seperate ```mod.rs``` files within directories. Each file would do the job of mod.rs specifying further files to bring in. # Detailed design @@ -40,11 +40,11 @@ from foo.rs, the following statements ```use mod baz::qux;``` ```use mod super::qaz;``` -would add these files to the project, and make bar,baz,quz available as qualifiers to reference symbols of those files within foo.rs . ```use``` statements would bring more individual symbols in, or longer paths could be written to access subtrees of these modules. +would add these files to the project, and make ```bar::,qux::,qaz::``` available as qualifiers to reference symbols of those files within foo.rs . Further ```use``` could shortcut more individual symbols, and longer paths could be written to access subtrees of these modules. Each individual file would in turn be able to bring in its own relative files. -eg if qux.rs contained the statement ```use mod super::super::qaz;``` , ```../qaz.rs``` would be brought into the project, although 'foo.rs' would still need an additional ```use super::qaz``` to reference it's symbols. +eg if qux.rs contained the statement ```use mod super::super::qaz;``` , ```../qaz.rs``` would be brought into the project, although 'foo.rs' would still need an additional ```use super::qaz``` to reference symbols in ```qaz.rs```. item paths would still reflect the directory-structure: - when a series of siblings reference eachother, one would not be able to follow this graph to reach symbols. From 46ca2888b29fe7654424b2ccf53d867013eb56c2 Mon Sep 17 00:00:00 2001 From: dobkeratops Date: Tue, 1 Jul 2014 22:09:05 +0100 Subject: [PATCH 05/39] Update 0000-relative-use-mod-imports.md --- active/0000-relative-use-mod-imports.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/active/0000-relative-use-mod-imports.md b/active/0000-relative-use-mod-imports.md index b351fe11d62..4fe4ae01b9e 100644 --- a/active/0000-relative-use-mod-imports.md +++ b/active/0000-relative-use-mod-imports.md @@ -40,7 +40,7 @@ from foo.rs, the following statements ```use mod baz::qux;``` ```use mod super::qaz;``` -would add these files to the project, and make ```bar::,qux::,qaz::``` available as qualifiers to reference symbols of those files within foo.rs . Further ```use``` could shortcut more individual symbols, and longer paths could be written to access subtrees of these modules. +would add these files to the project, and make ```bar::,qux::,qaz::``` available as qualifiers to reference symbols of those files within foo.rs . Further ```use``` statements could shortcut more individual symbols, and longer paths could be written to access subtrees of these modules. Each individual file would in turn be able to bring in its own relative files. @@ -54,7 +54,7 @@ Replicates functionality available with use, mod and #[path=...] directives, and heirachical 'use' paths have their own problems. When moving sources up or down the directory tree, refactoring would still be needed; -one might need references to a long string of ```super::super::..``` statements to refer to symbols in the project root. +If this was to replace the existing use/mod behaviour, one might need references to a long string of ```use mod super::super::..::main``` statements to refer to symbols relative to the project root. The behaviour of the standard prelude would not seem as consistent with this scheme. From 0c180029eae526d02b3ebbc42f4eba073470f19c Mon Sep 17 00:00:00 2001 From: dobkeratops Date: Tue, 1 Jul 2014 22:09:27 +0100 Subject: [PATCH 06/39] Update 0000-relative-use-mod-imports.md --- active/0000-relative-use-mod-imports.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/active/0000-relative-use-mod-imports.md b/active/0000-relative-use-mod-imports.md index 4fe4ae01b9e..96a8832385b 100644 --- a/active/0000-relative-use-mod-imports.md +++ b/active/0000-relative-use-mod-imports.md @@ -56,6 +56,6 @@ heirachical 'use' paths have their own problems. When moving sources up or down If this was to replace the existing use/mod behaviour, one might need references to a long string of ```use mod super::super::..::main``` statements to refer to symbols relative to the project root. -The behaviour of the standard prelude would not seem as consistent with this scheme. +The behaviour of the standard library prelude would not seem as consistent with this scheme. From 8b38f7a2ef177673a9f5335fb9c64c6f5dbd27ed Mon Sep 17 00:00:00 2001 From: dobkeratops Date: Tue, 1 Jul 2014 22:11:13 +0100 Subject: [PATCH 07/39] Update 0000-relative-use-mod-imports.md --- active/0000-relative-use-mod-imports.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/active/0000-relative-use-mod-imports.md b/active/0000-relative-use-mod-imports.md index 96a8832385b..d294777c455 100644 --- a/active/0000-relative-use-mod-imports.md +++ b/active/0000-relative-use-mod-imports.md @@ -12,7 +12,7 @@ introduce ```use mod ...;``` as a fused module import and namespace 'use', using Consider moving between the extremes of one compilation unit per file, and an entire project as a single compilation unit - with the existing use/mod behaviour, you would have to refactor how modules are brought in and how components are referenced when moving between these extremes. -Relative paths would allow greater flexibility when wanting to treat project subtrees as seperate libraries, or vica versa. +Relative paths would allow greater flexibility when wanting to treat project subtrees as seperate libraries, or vica versa. eg. for building examples demonstrating components of an SDK, or a single source tree building a suite of tools. A build system would be at liberty to cache any appropriate subtree equivalently to a library crate. From 439b3bfe49ebaac566a32503f388acd11a8b0c92 Mon Sep 17 00:00:00 2001 From: dobkeratops Date: Wed, 2 Jul 2014 00:31:19 +0100 Subject: [PATCH 08/39] Update 0000-relative-use-mod-imports.md --- active/0000-relative-use-mod-imports.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/active/0000-relative-use-mod-imports.md b/active/0000-relative-use-mod-imports.md index d294777c455..651240f4684 100644 --- a/active/0000-relative-use-mod-imports.md +++ b/active/0000-relative-use-mod-imports.md @@ -56,6 +56,8 @@ heirachical 'use' paths have their own problems. When moving sources up or down If this was to replace the existing use/mod behaviour, one might need references to a long string of ```use mod super::super::..::main``` statements to refer to symbols relative to the project root. +perhaps the tree flattening effect of crate files is desirable + The behaviour of the standard library prelude would not seem as consistent with this scheme. From 7088105820e2229cdc148407328794d5baa1ebc3 Mon Sep 17 00:00:00 2001 From: dobkeratops Date: Wed, 2 Jul 2014 02:10:33 +0100 Subject: [PATCH 09/39] Update 0000-relative-use-mod-imports.md --- active/0000-relative-use-mod-imports.md | 36 +++++++++++++++---------- 1 file changed, 22 insertions(+), 14 deletions(-) diff --git a/active/0000-relative-use-mod-imports.md b/active/0000-relative-use-mod-imports.md index 651240f4684..5cc54db8366 100644 --- a/active/0000-relative-use-mod-imports.md +++ b/active/0000-relative-use-mod-imports.md @@ -4,7 +4,10 @@ # Summary -introduce ```use mod ...;``` as a fused module import and namespace 'use', using relative filename/module paths +introduce ```use mod ...;``` as a fused module import and namespace 'use', using relative module paths, which are also relative filename paths. +Exploit the coherence between the module heirarchy and the filesystem directory heirarchy - but *assume* this coherence, instead of manually creating it with 'mod.rs' files + + # Motivation @@ -16,33 +19,35 @@ Relative paths would allow greater flexibility when wanting to treat project sub A build system would be at liberty to cache any appropriate subtree equivalently to a library crate. -## learning curve -The seperate absolute and relative paths, and mod / use statements are a tripping point for new users +## shorter learning curve +The seperate absolute and relative paths, and mod / use statements are a tripping point for new users. Under this scheme, you only see relative paths, and you only need one statement 'use mod '. ## tooling -with a project setup this way, a tool can locate definitions starting at the 'current' file and spidering outward. While working on a project, one may have code in different component libraries open,needing changes; Under the current system, each of which would have different absolute paths. +with a project setup this way, a tool can locate definitions starting at the 'current' file and spidering outward. While working on a project, one may have code in different component libraries open,needing changes; Under the current system, each of which would have different absolute paths. So a tool needs to have seen less of the whole project structure. -## simpler imports +## simpler description of source-tree eliminate the need for seperate ```mod.rs``` files within directories. Each file would do the job of mod.rs specifying further files to bring in. # Detailed design -use mod would look for a file relative to the current locatoin +```use mod``` would look for a file relative to the current file. given some source files in -foo.rs -bar.rs -baz/qux.rs +./foo.rs +./bar.rs +./baz/qux.rs ../qaz.rs -from foo.rs, the following statements +from ```foo.rs,``` the following statements ```use mod bar;``` ```use mod baz::qux;``` ```use mod super::qaz;``` -would add these files to the project, and make ```bar::,qux::,qaz::``` available as qualifiers to reference symbols of those files within foo.rs . Further ```use``` statements could shortcut more individual symbols, and longer paths could be written to access subtrees of these modules. +would add those files to the project (eg, baz::qux is like saying 'load baz/qux.rs'), and make ```bar::,qux::,qaz::``` available as qualifiers to reference symbols of those files within foo.rs . -Each individual file would in turn be able to bring in its own relative files. +Further ```use``` statements could give shortcuts to individual symbols, and longer paths could be written to access subtrees of these modules. + +Each individual file would in turn be able to bring in its own relative files - starting from the project root, the build system would spider outward. eg if qux.rs contained the statement ```use mod super::super::qaz;``` , ```../qaz.rs``` would be brought into the project, although 'foo.rs' would still need an additional ```use super::qaz``` to reference symbols in ```qaz.rs```. @@ -52,12 +57,15 @@ item paths would still reflect the directory-structure: - when a series of sibli Replicates functionality available with use, mod and #[path=...] directives, and is a slightly different mentality to the existing system. +Might look more complicated *when used alonside the existing system* (even though its' intended as a replacement, it would require a rolling refactor) + heirachical 'use' paths have their own problems. When moving sources up or down the directory tree, refactoring would still be needed; If this was to replace the existing use/mod behaviour, one might need references to a long string of ```use mod super::super::..::main``` statements to refer to symbols relative to the project root. -perhaps the tree flattening effect of crate files is desirable +perhaps the tree flattening effect of explicit crate files which are them imported into a project root is desirable. +(under this scheme, *every* source file that wants to refer to a particular crate conveiniently would have some ```use mod super::super..some_major_module_that_would_currently_be_a_crate```) -The behaviour of the standard library prelude would not seem as consistent with this scheme. +The behaviour of the standard library prelude might not seem as consistent with this scheme. From 76ce70ad8a163c229af2d364c5c1bc7fdbd904af Mon Sep 17 00:00:00 2001 From: dobkeratops Date: Wed, 2 Jul 2014 02:18:19 +0100 Subject: [PATCH 10/39] Update 0000-relative-use-mod-imports.md --- active/0000-relative-use-mod-imports.md | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/active/0000-relative-use-mod-imports.md b/active/0000-relative-use-mod-imports.md index 5cc54db8366..a3a687b0c9a 100644 --- a/active/0000-relative-use-mod-imports.md +++ b/active/0000-relative-use-mod-imports.md @@ -5,7 +5,8 @@ # Summary introduce ```use mod ...;``` as a fused module import and namespace 'use', using relative module paths, which are also relative filename paths. -Exploit the coherence between the module heirarchy and the filesystem directory heirarchy - but *assume* this coherence, instead of manually creating it with 'mod.rs' files + +This system exploits the coherence between the module heirarchy and the filesystem directory tree - but it *assumes* this coherence, instead of relying on the user to manually create it with 'mod.rs' files. So the information of 'bringing things into scope' should be enough to specify what to load. @@ -51,7 +52,11 @@ Each individual file would in turn be able to bring in its own relative files - eg if qux.rs contained the statement ```use mod super::super::qaz;``` , ```../qaz.rs``` would be brought into the project, although 'foo.rs' would still need an additional ```use super::qaz``` to reference symbols in ```qaz.rs```. -item paths would still reflect the directory-structure: - when a series of siblings reference eachother, one would not be able to follow this graph to reach symbols. +## use mod between siblings +Symbol paths would always reflect the directory-structure: - when a series of siblings reference eachother, one would not be able to follow this graph to reach symbols. eg if there is a relationship a.rs->b.rs->c.rs but they are all in the same directory, there is no path ```a::b::c```, just seperate ```a:: b:: c::``` + +##submodules wthin files +mod {...} within a file would still be available - this is where the module heirarchy can differ from the file layout, but its assumed every file would be referenced explicityly by a ```use mod``` path. (submodules would be reached with additional ```use```'s # Drawbacks From 0e1e8ea0f310754c124195f05917c8882320aee5 Mon Sep 17 00:00:00 2001 From: dobkeratops Date: Wed, 2 Jul 2014 02:19:44 +0100 Subject: [PATCH 11/39] Update 0000-relative-use-mod-imports.md --- active/0000-relative-use-mod-imports.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/active/0000-relative-use-mod-imports.md b/active/0000-relative-use-mod-imports.md index a3a687b0c9a..59b9e0c6042 100644 --- a/active/0000-relative-use-mod-imports.md +++ b/active/0000-relative-use-mod-imports.md @@ -20,6 +20,8 @@ Relative paths would allow greater flexibility when wanting to treat project sub A build system would be at liberty to cache any appropriate subtree equivalently to a library crate. +This might be useful for compiling tests, eg it would be theoretically possible to start with any individual file and test it, in isolation from the whole-project build. + ## shorter learning curve The seperate absolute and relative paths, and mod / use statements are a tripping point for new users. Under this scheme, you only see relative paths, and you only need one statement 'use mod '. From 839ce69f10a7a8be8af517cd35dca502bd7e4322 Mon Sep 17 00:00:00 2001 From: dobkeratops Date: Wed, 2 Jul 2014 02:27:31 +0100 Subject: [PATCH 12/39] Update 0000-relative-use-mod-imports.md --- active/0000-relative-use-mod-imports.md | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/active/0000-relative-use-mod-imports.md b/active/0000-relative-use-mod-imports.md index 59b9e0c6042..46b0513c63b 100644 --- a/active/0000-relative-use-mod-imports.md +++ b/active/0000-relative-use-mod-imports.md @@ -6,8 +6,9 @@ introduce ```use mod ...;``` as a fused module import and namespace 'use', using relative module paths, which are also relative filename paths. -This system exploits the coherence between the module heirarchy and the filesystem directory tree - but it *assumes* this coherence, instead of relying on the user to manually create it with 'mod.rs' files. So the information of 'bringing things into scope' should be enough to specify what to load. +This system exploits coherence between the module heirarchy and the filesystem directory tree - but it *assumes* this coherence, instead of relying on the user to manually *create* it with 'mod.rs' files. So the information you give when 'bringing things into scope' should be enough to specify what to load. +```use mod``` would bring something into scope along with the hint: "this module is an actual file,not a submodule, so it should be loaded." # Motivation @@ -60,6 +61,9 @@ Symbol paths would always reflect the directory-structure: - when a series of si ##submodules wthin files mod {...} within a file would still be available - this is where the module heirarchy can differ from the file layout, but its assumed every file would be referenced explicityly by a ```use mod``` path. (submodules would be reached with additional ```use```'s +## use vs use mod +if it wasn't for the existence of submodules, would it be possible to infer load information entirely from relative use directives, and individual qualified symbols ? However this system relies on "use mod" as a hint, "this module is a file" + # Drawbacks Replicates functionality available with use, mod and #[path=...] directives, and is a slightly different mentality to the existing system. From fad91bc6bcce90989facbdde790c6fe8e1f4fbed Mon Sep 17 00:00:00 2001 From: dobkeratops Date: Wed, 2 Jul 2014 02:29:44 +0100 Subject: [PATCH 13/39] Update 0000-relative-use-mod-imports.md --- active/0000-relative-use-mod-imports.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/active/0000-relative-use-mod-imports.md b/active/0000-relative-use-mod-imports.md index 46b0513c63b..0d64c4f93cd 100644 --- a/active/0000-relative-use-mod-imports.md +++ b/active/0000-relative-use-mod-imports.md @@ -6,9 +6,10 @@ introduce ```use mod ...;``` as a fused module import and namespace 'use', using relative module paths, which are also relative filename paths. +```use mod``` brings a module into scope along with the hint: "this module is an actual file" + This system exploits coherence between the module heirarchy and the filesystem directory tree - but it *assumes* this coherence, instead of relying on the user to manually *create* it with 'mod.rs' files. So the information you give when 'bringing things into scope' should be enough to specify what to load. -```use mod``` would bring something into scope along with the hint: "this module is an actual file,not a submodule, so it should be loaded." # Motivation From c8a1a184cc189a821e25369762f76467d1778794 Mon Sep 17 00:00:00 2001 From: dobkeratops Date: Wed, 2 Jul 2014 02:31:57 +0100 Subject: [PATCH 14/39] Update 0000-relative-use-mod-imports.md --- active/0000-relative-use-mod-imports.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/active/0000-relative-use-mod-imports.md b/active/0000-relative-use-mod-imports.md index 0d64c4f93cd..5119cdb03f5 100644 --- a/active/0000-relative-use-mod-imports.md +++ b/active/0000-relative-use-mod-imports.md @@ -71,7 +71,7 @@ Replicates functionality available with use, mod and #[path=...] directives, and Might look more complicated *when used alonside the existing system* (even though its' intended as a replacement, it would require a rolling refactor) -heirachical 'use' paths have their own problems. When moving sources up or down the directory tree, refactoring would still be needed; +heirachical 'use' paths have their own problems. When moving sources up or down the directory tree, refactoring would still be needed; Rust supposedly already moved from relative to absolute. If this was to replace the existing use/mod behaviour, one might need references to a long string of ```use mod super::super::..::main``` statements to refer to symbols relative to the project root. From ebc35a9fb6b328b6f3f2a9ab55f51bfda5042369 Mon Sep 17 00:00:00 2001 From: dobkeratops Date: Wed, 2 Jul 2014 08:35:41 +0100 Subject: [PATCH 15/39] Update 0000-relative-use-mod-imports.md --- active/0000-relative-use-mod-imports.md | 44 +++++++++++++++---------- 1 file changed, 26 insertions(+), 18 deletions(-) diff --git a/active/0000-relative-use-mod-imports.md b/active/0000-relative-use-mod-imports.md index 5119cdb03f5..e7d1716a068 100644 --- a/active/0000-relative-use-mod-imports.md +++ b/active/0000-relative-use-mod-imports.md @@ -4,7 +4,9 @@ # Summary -introduce ```use mod ...;``` as a fused module import and namespace 'use', using relative module paths, which are also relative filename paths. +introduce ```use mod ...;``` as a simultaneous module import and namespace 'use', with relative module paths, which are also relative filename paths. + +Creates a graph of imports between files as in other module systems, but still mounts modules heriarchically. ```use mod``` brings a module into scope along with the hint: "this module is an actual file" @@ -16,41 +18,47 @@ This system exploits coherence between the module heirarchy and the filesystem d ## versatility for compile units -Consider moving between the extremes of one compilation unit per file, and an entire project as a single compilation unit - with the existing use/mod behaviour, you would have to refactor how modules are brought in and how components are referenced when moving between these extremes. +Consider moving between the extremes of one compilation unit per file, vs an entire project as a single compilation unit - with the existing use/mod behaviour, you would have to refactor how modules are brought in and how components are referenced. Relative paths would allow greater flexibility when wanting to treat project subtrees as seperate libraries, or vica versa. eg. for building examples demonstrating components of an SDK, or a single source tree building a suite of tools. -A build system would be at liberty to cache any appropriate subtree equivalently to a library crate. +A build system would be at liberty to cache any appropriate subtree equivalently to a library crate with no pre-planning on the users' part. -This might be useful for compiling tests, eg it would be theoretically possible to start with any individual file and test it, in isolation from the whole-project build. +a faster debug build with less inlining might be possible with smaller translation units; or you want to switch to a single translation unit (like C++ unity builds) for the maximum optimization possible. ## shorter learning curve The seperate absolute and relative paths, and mod / use statements are a tripping point for new users. Under this scheme, you only see relative paths, and you only need one statement 'use mod '. -## tooling -with a project setup this way, a tool can locate definitions starting at the 'current' file and spidering outward. While working on a project, one may have code in different component libraries open,needing changes; Under the current system, each of which would have different absolute paths. So a tool needs to have seen less of the whole project structure. +eliminates the need to create seperate ```mod.rs``` files within directories. Each file would do the job of mod.rs specifying further files to bring in. -## simpler description of source-tree -eliminate the need for seperate ```mod.rs``` files within directories. Each file would do the job of mod.rs specifying further files to bring in. +## parallelize --test +This might be useful for compiling tests, eg it would be theoretically possible to start at any individual file and test it, in isolation from the whole-project build. So building for test could be done across more cores. + +## tooling +with a project setup this way, a tool can locate definitions starting at any 'current' file and spidering outward. While working on a project, one may have source from different component libraries open; Under the current system, each of which would have different addressing scheme, relative to its own crate root. Under this scheme, a tools needs to know less about the whole project to give consistent help to the user. # Detailed design ```use mod``` would look for a file relative to the current file. given some source files in -./foo.rs -./bar.rs -./baz/qux.rs -../qaz.rs + + ./foo.rs + ./bar.rs + ./baz/qux.rs + ../qaz.rs from ```foo.rs,``` the following statements -```use mod bar;``` -```use mod baz::qux;``` -```use mod super::qaz;``` -would add those files to the project (eg, baz::qux is like saying 'load baz/qux.rs'), and make ```bar::,qux::,qaz::``` available as qualifiers to reference symbols of those files within foo.rs . + use mod bar; + use mod baz::qux; + use mod super::qaz; + +would add ```foo.rs,bar.rs,qux.rs,qaz.rs ``` to the project (eg, baz::qux is like saying 'load baz/qux.rs'), and make ```bar::,qux::,qaz::``` available as qualifiers to reference symbols of those files, within foo.rs . + +This would work regardless whether ```foo.rs``` was the crate root or further down the tree. -Further ```use``` statements could give shortcuts to individual symbols, and longer paths could be written to access subtrees of these modules. +Further ```use``` statements could give shortcuts to individual symbols within foo.rs, and longer paths could be written to access subtrees of these modules. Each individual file would in turn be able to bring in its own relative files - starting from the project root, the build system would spider outward. @@ -73,7 +81,7 @@ Might look more complicated *when used alonside the existing system* (even thoug heirachical 'use' paths have their own problems. When moving sources up or down the directory tree, refactoring would still be needed; Rust supposedly already moved from relative to absolute. -If this was to replace the existing use/mod behaviour, one might need references to a long string of ```use mod super::super::..::main``` statements to refer to symbols relative to the project root. +If this was to replace the existing use/mod behaviour, one might need references to a long string of ```use mod super::super::super::...::main``` statements to refer to symbols relative to the project root. perhaps the tree flattening effect of explicit crate files which are them imported into a project root is desirable. (under this scheme, *every* source file that wants to refer to a particular crate conveiniently would have some ```use mod super::super..some_major_module_that_would_currently_be_a_crate```) From ea49d5015cae1a84b1ad9e9daae01d7e32755567 Mon Sep 17 00:00:00 2001 From: dobkeratops Date: Wed, 2 Jul 2014 08:41:08 +0100 Subject: [PATCH 16/39] Update 0000-relative-use-mod-imports.md --- active/0000-relative-use-mod-imports.md | 24 ++++++++++++++---------- 1 file changed, 14 insertions(+), 10 deletions(-) diff --git a/active/0000-relative-use-mod-imports.md b/active/0000-relative-use-mod-imports.md index e7d1716a068..fc6f7ca2098 100644 --- a/active/0000-relative-use-mod-imports.md +++ b/active/0000-relative-use-mod-imports.md @@ -4,7 +4,7 @@ # Summary -introduce ```use mod ...;``` as a simultaneous module import and namespace 'use', with relative module paths, which are also relative filename paths. +introduce ```use mod ...;``` or ```import ...;``` as a simultaneous module import and namespace 'use', with relative module paths, which are also relative filename paths. Creates a graph of imports between files as in other module systems, but still mounts modules heriarchically. @@ -20,11 +20,12 @@ This system exploits coherence between the module heirarchy and the filesystem d Consider moving between the extremes of one compilation unit per file, vs an entire project as a single compilation unit - with the existing use/mod behaviour, you would have to refactor how modules are brought in and how components are referenced. +a faster debug build with less inlining might be possible with smaller translation units; or you want to switch to a single translation unit (like C++ unity builds) for the maximum optimization possible. + Relative paths would allow greater flexibility when wanting to treat project subtrees as seperate libraries, or vica versa. eg. for building examples demonstrating components of an SDK, or a single source tree building a suite of tools. A build system would be at liberty to cache any appropriate subtree equivalently to a library crate with no pre-planning on the users' part. -a faster debug build with less inlining might be possible with smaller translation units; or you want to switch to a single translation unit (like C++ unity builds) for the maximum optimization possible. ## shorter learning curve The seperate absolute and relative paths, and mod / use statements are a tripping point for new users. Under this scheme, you only see relative paths, and you only need one statement 'use mod '. @@ -41,18 +42,18 @@ with a project setup this way, a tool can locate definitions starting at any 'cu ```use mod``` would look for a file relative to the current file. -given some source files in +given some source files: - ./foo.rs - ./bar.rs - ./baz/qux.rs + foo.rs + bar.rs + baz/qux.rs ../qaz.rs from ```foo.rs,``` the following statements - use mod bar; - use mod baz::qux; - use mod super::qaz; + use mod bar; + use mod baz::qux; + use mod super::qaz; would add ```foo.rs,bar.rs,qux.rs,qaz.rs ``` to the project (eg, baz::qux is like saying 'load baz/qux.rs'), and make ```bar::,qux::,qaz::``` available as qualifiers to reference symbols of those files, within foo.rs . @@ -75,6 +76,8 @@ if it wasn't for the existence of submodules, would it be possible to infer loa # Drawbacks +The behaviour of the standard library prelude might not seem as consistent with this scheme. + Replicates functionality available with use, mod and #[path=...] directives, and is a slightly different mentality to the existing system. Might look more complicated *when used alonside the existing system* (even though its' intended as a replacement, it would require a rolling refactor) @@ -86,6 +89,7 @@ If this was to replace the existing use/mod behaviour, one might need references perhaps the tree flattening effect of explicit crate files which are them imported into a project root is desirable. (under this scheme, *every* source file that wants to refer to a particular crate conveiniently would have some ```use mod super::super..some_major_module_that_would_currently_be_a_crate```) -The behaviour of the standard library prelude might not seem as consistent with this scheme. +if modules down the graph did import files earlier in the tree, the tool would have to warn you about this and possibly dissalow when you compile a subtree as a library crate. + From aef7749f81c10d5ecb6e59014e16078db9a12951 Mon Sep 17 00:00:00 2001 From: dobkeratops Date: Wed, 2 Jul 2014 19:59:26 +0100 Subject: [PATCH 17/39] Update 0000-relative-use-mod-imports.md --- active/0000-relative-use-mod-imports.md | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/active/0000-relative-use-mod-imports.md b/active/0000-relative-use-mod-imports.md index fc6f7ca2098..d872866ea53 100644 --- a/active/0000-relative-use-mod-imports.md +++ b/active/0000-relative-use-mod-imports.md @@ -4,18 +4,22 @@ # Summary -introduce ```use mod ...;``` or ```import ...;``` as a simultaneous module import and namespace 'use', with relative module paths, which are also relative filename paths. +introduce ```use mod ...;``` or ```import ...;``` as a simultaneous module import and namespace 'use', with relative module paths, which have a 1:1 mapping to relative filename paths. Creates a graph of imports between files as in other module systems, but still mounts modules heriarchically. ```use mod``` brings a module into scope along with the hint: "this module is an actual file" -This system exploits coherence between the module heirarchy and the filesystem directory tree - but it *assumes* this coherence, instead of relying on the user to manually *create* it with 'mod.rs' files. So the information you give when 'bringing things into scope' should be enough to specify what to load. # Motivation +## avoids repeating information + +This idea exploits coherence between the module heirarchy and the filesystem directory tree - but it *assumes* this coherence, instead of relying on the user to manually *create* it with 'mod.rs' files. So the information you give when 'bringing things into scope' should be enough to specify what to load. + + ## versatility for compile units Consider moving between the extremes of one compilation unit per file, vs an entire project as a single compilation unit - with the existing use/mod behaviour, you would have to refactor how modules are brought in and how components are referenced. From d32161d7f09d1ad72cf00aacbf343a4d688d5d3a Mon Sep 17 00:00:00 2001 From: dobkeratops Date: Tue, 8 Jul 2014 15:07:52 +0100 Subject: [PATCH 18/39] Update 0000-relative-use-mod-imports.md --- active/0000-relative-use-mod-imports.md | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/active/0000-relative-use-mod-imports.md b/active/0000-relative-use-mod-imports.md index d872866ea53..dcf25dadcdf 100644 --- a/active/0000-relative-use-mod-imports.md +++ b/active/0000-relative-use-mod-imports.md @@ -4,7 +4,9 @@ # Summary -introduce ```use mod ...;``` or ```import ...;``` as a simultaneous module import and namespace 'use', with relative module paths, which have a 1:1 mapping to relative filename paths. +introduce ```use mod ...;``` (or ```import ...;``` ) as a simultaneous import and 'use', with relative module paths, which have a 1:1 mapping to relative filename paths. + +``` use mod foo::bar::baz``` brings in module foo/bar/baz.rs & uses' bar. Creates a graph of imports between files as in other module systems, but still mounts modules heriarchically. @@ -59,11 +61,11 @@ from ```foo.rs,``` the following statements use mod baz::qux; use mod super::qaz; -would add ```foo.rs,bar.rs,qux.rs,qaz.rs ``` to the project (eg, baz::qux is like saying 'load baz/qux.rs'), and make ```bar::,qux::,qaz::``` available as qualifiers to reference symbols of those files, within foo.rs . +would add ```foo.rs, bar.rs, baz/qux.rs, ../qaz.rs ``` to the project (eg, baz::qux is like saying 'load baz/qux.rs'), and make ```bar::,qux::,qaz::``` available as qualifiers within foo.rs . This would work regardless whether ```foo.rs``` was the crate root or further down the tree. -Further ```use``` statements could give shortcuts to individual symbols within foo.rs, and longer paths could be written to access subtrees of these modules. +Further ```use``` statements could give shortcuts to individual symbols, and longer paths could be written to access subtrees of these modules. Each individual file would in turn be able to bring in its own relative files - starting from the project root, the build system would spider outward. @@ -73,7 +75,7 @@ eg if qux.rs contained the statement ```use mod super::super::qaz;``` , ```../qa Symbol paths would always reflect the directory-structure: - when a series of siblings reference eachother, one would not be able to follow this graph to reach symbols. eg if there is a relationship a.rs->b.rs->c.rs but they are all in the same directory, there is no path ```a::b::c```, just seperate ```a:: b:: c::``` ##submodules wthin files -mod {...} within a file would still be available - this is where the module heirarchy can differ from the file layout, but its assumed every file would be referenced explicityly by a ```use mod``` path. (submodules would be reached with additional ```use```'s +mod {...} within a file would still be available - this is where the module heirarchy can differ from the file layout, but its assumed every file must be referenced explicitely by a ```use mod``` statement. (submodules would be reached with additional ```use```'s ## use vs use mod if it wasn't for the existence of submodules, would it be possible to infer load information entirely from relative use directives, and individual qualified symbols ? However this system relies on "use mod" as a hint, "this module is a file" From 155437bb6554b4dd31727ac1506c2b8355aa3b75 Mon Sep 17 00:00:00 2001 From: dobkeratops Date: Sat, 12 Jul 2014 17:43:50 +0100 Subject: [PATCH 19/39] Update 0000-relative-use-mod-imports.md --- active/0000-relative-use-mod-imports.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/active/0000-relative-use-mod-imports.md b/active/0000-relative-use-mod-imports.md index dcf25dadcdf..5e7438cab5f 100644 --- a/active/0000-relative-use-mod-imports.md +++ b/active/0000-relative-use-mod-imports.md @@ -8,7 +8,7 @@ introduce ```use mod ...;``` (or ```import ...;``` ) as a simultaneous import an ``` use mod foo::bar::baz``` brings in module foo/bar/baz.rs & uses' bar. -Creates a graph of imports between files as in other module systems, but still mounts modules heriarchically. +Creates a graph of imports between files as in other module systems, but still mounts modules heriarchically, mirroring the directory tree. ```use mod``` brings a module into scope along with the hint: "this module is an actual file" From e4ebfa728016b14fbb4f61723166e65b26ad3db8 Mon Sep 17 00:00:00 2001 From: dobkeratops Date: Mon, 3 Jul 2017 04:18:19 +0100 Subject: [PATCH 20/39] Update and rename 0000-template.md to text/0000-ask_the_compiler_placeholder_ident.md --- 0000-template.md | 29 --------- ...0000-ask_the_compiler_placeholder_ident.md | 59 +++++++++++++++++++ 2 files changed, 59 insertions(+), 29 deletions(-) delete mode 100644 0000-template.md create mode 100644 text/0000-ask_the_compiler_placeholder_ident.md diff --git a/0000-template.md b/0000-template.md deleted file mode 100644 index 629e4e4a37e..00000000000 --- a/0000-template.md +++ /dev/null @@ -1,29 +0,0 @@ -- Start Date: (fill me in with today's date, YYYY-MM-DD) -- RFC PR #: (leave this empty) -- Rust Issue #: (leave this empty) - -# Summary - -One para explanation of the feature. - -# Motivation - -Why are we doing this? What use cases does it support? What is the expected outcome? - -# Detailed design - -This is the bulk of the RFC. Explain the design in enough detail for somebody familiar -with the language to understand, and for somebody familiar with the compiler to implement. -This should get into specifics and corner-cases, and include examples of how the feature is used. - -# Drawbacks - -Why should we *not* do this? - -# Alternatives - -What other designs have been considered? What is the impact of not doing this? - -# Unresolved questions - -What parts of the design are still TBD? diff --git a/text/0000-ask_the_compiler_placeholder_ident.md b/text/0000-ask_the_compiler_placeholder_ident.md new file mode 100644 index 00000000000..4cb3dad7b70 --- /dev/null +++ b/text/0000-ask_the_compiler_placeholder_ident.md @@ -0,0 +1,59 @@ +- Start Date: (fill me in with today's date, YYYY-MM-DD) +- RFC PR #: (leave this empty) +- Rust Issue #: (leave this empty) + +# Summary + +Imageine a tool for making compile time queries (inspired by haskell holes): Add a 'placeholder ident' to the AST; this passes through type inference; it does not resolve to an actual symbol, but instead assumes it is 'whatever needed' to fit the demands around it, and allows the rest of the program to contiue compiling (resolving/typechecking). + +Compiling a program with placeholders will fail, but gives extra informative error messages reporting (a) the types at that point, and (b) potential symbols that fit. + +# Motivation + +This is to assist navigation and discovery whilst programming, doing a similar job to IDE 'dot-autocomplete', but leveraging Rust's more advanced 2-way type inference. Already people use the trick of 'let _:()=expr_' to query the type as an error, but these 'deliberate' queries would allow the inference engine to work harder. + +Improving compile time feedback pushes the community forward whilst we wait for IDE tools (with more complex integration) to stabilize and refine. + +# Detailed design + +see earlier forum post, +https://internals.rust-lang.org/t/ask-the-compiler-syntax-e-g--/700 + +The placeholder could be configurable (by commandline option or lang item?) to avoid clash, but a sane default would be a single underscore in a function,trait,or variable spot, because no one would use that for a real symbol. By making it a configurable legal ident, it will not take any syntax space. This is distinct to the underscore character in the type context (where it already performs a different function). + +The query could be used in the following ways (I note that as of 2017, the rust compiler already gives a bit of assistance in some of these cases) + +fn foo( a:T) { a.do_something() } // ask what traits have a method 'do_something()' + +fn foo(a:&X)->Y { _(a) } // ask for functions close to fitting the signature ( &X)->Y +fn foo(a:&X)->Z { a._()._()} // ask for any functions X->Y , Y->Z and possible 'Y' + +_::bar(x,y,z) // ask for full paths of any functions bar(..) + +foo._.bar - ... what member has a sub-member .bar (maybe make it also show, + +foo._._.bar foo._._._.bar, i.e. search the object graph.. this is a big deal with complex data structures. ) + +fn foo(a,b,c)->_ {... do stuff...} .. Do full inference from calls to 'foo', and report what signature this function needs to fit it's uses.. the scenario when you factor code out. + +{ ... foo(_) ... } report the arguments 'foo' should take + + +If the compiler output was formatted nicely (I dont know the full plan with the RLS) perhaps this could be used directly for IDE/editor integration; imagine if output of underscore queries could be collected by an IDE and placed in dropbox menus under the text; this could yield a unique editing experience beyond existing autocomplete IDEs?. + + + + +# Drawbacks + + + +# Alternatives + +Putting all similar effort into IDE integration. +it might be possible to treat *all* unresolved symbols this way - the compiler already does make a lot of suggestions - but the idea is for a deliberate query that can invoke heavier work. +I note that since I made this suggestion a while back significant progress has been made the with "RLS", but perhaps there is synergy with the other peices IDE support needs. + +# Unresolved questions + +What parts of the design are still TBD? From 9ca7feb5ea504781d9ca38dbcd6fbecfc080e0c1 Mon Sep 17 00:00:00 2001 From: dobkeratops Date: Mon, 3 Jul 2017 04:30:15 +0100 Subject: [PATCH 21/39] Update 0000-ask_the_compiler_placeholder_ident.md --- ...0000-ask_the_compiler_placeholder_ident.md | 31 ++++++++++++------- 1 file changed, 19 insertions(+), 12 deletions(-) diff --git a/text/0000-ask_the_compiler_placeholder_ident.md b/text/0000-ask_the_compiler_placeholder_ident.md index 4cb3dad7b70..8ff128b02e3 100644 --- a/text/0000-ask_the_compiler_placeholder_ident.md +++ b/text/0000-ask_the_compiler_placeholder_ident.md @@ -4,13 +4,15 @@ # Summary -Imageine a tool for making compile time queries (inspired by haskell holes): Add a 'placeholder ident' to the AST; this passes through type inference; it does not resolve to an actual symbol, but instead assumes it is 'whatever needed' to fit the demands around it, and allows the rest of the program to contiue compiling (resolving/typechecking). +This is inspired by haskell holes: Add a 'placeholder identifier' to the AST; when encountered passes through type inference; it does not resolve to an actual definition, but instead assumes it is 'whatever needed' to fit the demands around it, and allows the rest of the program to contiue compiling (resolving/typechecking). Compiling a program with placeholders will fail, but gives extra informative error messages reporting (a) the types at that point, and (b) potential symbols that fit. # Motivation -This is to assist navigation and discovery whilst programming, doing a similar job to IDE 'dot-autocomplete', but leveraging Rust's more advanced 2-way type inference. Already people use the trick of 'let _:()=expr_' to query the type as an error, but these 'deliberate' queries would allow the inference engine to work harder. +This is to assist navigation and discovery during the compile-edit cycle, doing a similar job to IDE 'dot-autocomplete', but leveraging Rust's more advanced 2-way type inference by making deliberate queries with more information. + +Already people use the trick of 'let _:()=expr_' to query the type as an error, but these queries would allow the inference engine to work harder. Improving compile time feedback pushes the community forward whilst we wait for IDE tools (with more complex integration) to stabilize and refine. @@ -19,24 +21,29 @@ Improving compile time feedback pushes the community forward whilst we wait for see earlier forum post, https://internals.rust-lang.org/t/ask-the-compiler-syntax-e-g--/700 -The placeholder could be configurable (by commandline option or lang item?) to avoid clash, but a sane default would be a single underscore in a function,trait,or variable spot, because no one would use that for a real symbol. By making it a configurable legal ident, it will not take any syntax space. This is distinct to the underscore character in the type context (where it already performs a different function). +The placeholder would be configurable (by commandline option) to avoid any clash, but a sane default would be a single underscore. +The placeholder is relevant to function,trait,or variable identifiers. + +By making it a configurable legal ident, it will not take any syntax space. + +This is distinct to the underscore character in the type context (which performs a different function, it leaves a gap where the surrounding context is enough to infer *exactly* what is going on). -The query could be used in the following ways (I note that as of 2017, the rust compiler already gives a bit of assistance in some of these cases) +The query could be used in the following ways -fn foo( a:T) { a.do_something() } // ask what traits have a method 'do_something()' +```fn foo( a:T) { a.do_something() } // ask what traits have a method 'do_something()'``` -fn foo(a:&X)->Y { _(a) } // ask for functions close to fitting the signature ( &X)->Y -fn foo(a:&X)->Z { a._()._()} // ask for any functions X->Y , Y->Z and possible 'Y' +```fn foo(a:&X)->Y { _(a) } // ask for functions close to fitting the signature ( &X)->Y ``` +```fn foo(a:&X)->Z { a._()._()} // ask for any functions X->Y , Y->Z and possible 'Y'``` -_::bar(x,y,z) // ask for full paths of any functions bar(..) +```_::bar(x,y,z) // ask for full paths of any functions bar(..)``` -foo._.bar - ... what member has a sub-member .bar (maybe make it also show, +```foo._.bar - ... what member has a sub-member .bar (maybe make it also show,``` -foo._._.bar foo._._._.bar, i.e. search the object graph.. this is a big deal with complex data structures. ) +```foo._._.bar foo._._._.bar, i.e. search the object graph.. this is a big deal with complex data structures. )``` -fn foo(a,b,c)->_ {... do stuff...} .. Do full inference from calls to 'foo', and report what signature this function needs to fit it's uses.. the scenario when you factor code out. +```fn foo(a,b,c)->_ {... do stuff...} .. Do full whole-program inference from any calls TO 'foo', and report what signature this function needs to fit it's uses.. the scenario appears when you factor code out.``` -{ ... foo(_) ... } report the arguments 'foo' should take +```{ ... foo(_) ... } report the arguments 'foo' should take``` If the compiler output was formatted nicely (I dont know the full plan with the RLS) perhaps this could be used directly for IDE/editor integration; imagine if output of underscore queries could be collected by an IDE and placed in dropbox menus under the text; this could yield a unique editing experience beyond existing autocomplete IDEs?. From cba3f5d65de60d7f0bb70a7cf5f205450058c887 Mon Sep 17 00:00:00 2001 From: dobkeratops Date: Mon, 3 Jul 2017 04:39:10 +0100 Subject: [PATCH 22/39] Update 0000-ask_the_compiler_placeholder_ident.md --- ...0000-ask_the_compiler_placeholder_ident.md | 24 +++++++++++++++---- 1 file changed, 19 insertions(+), 5 deletions(-) diff --git a/text/0000-ask_the_compiler_placeholder_ident.md b/text/0000-ask_the_compiler_placeholder_ident.md index 8ff128b02e3..e64aaa52223 100644 --- a/text/0000-ask_the_compiler_placeholder_ident.md +++ b/text/0000-ask_the_compiler_placeholder_ident.md @@ -4,7 +4,7 @@ # Summary -This is inspired by haskell holes: Add a 'placeholder identifier' to the AST; when encountered passes through type inference; it does not resolve to an actual definition, but instead assumes it is 'whatever needed' to fit the demands around it, and allows the rest of the program to contiue compiling (resolving/typechecking). +This is inspired by haskell holes: Add a 'placeholder identifier' to the AST; when encountered, it passes through type inference; it does not resolve to an actual definition, but instead assumes it is 'whatever needed' to fit the demands around it, and allows the rest of the program to contiue compiling (resolving/typechecking). Compiling a program with placeholders will fail, but gives extra informative error messages reporting (a) the types at that point, and (b) potential symbols that fit. @@ -18,32 +18,46 @@ Improving compile time feedback pushes the community forward whilst we wait for # Detailed design +It requires the AST to contain the concept of a query in an ident slot, even though the presence of a query signifies that this program cannot compile. + see earlier forum post, https://internals.rust-lang.org/t/ask-the-compiler-syntax-e-g--/700 The placeholder would be configurable (by commandline option) to avoid any clash, but a sane default would be a single underscore. -The placeholder is relevant to function,trait,or variable identifiers. +The placeholder parses as any other ident from a syntacital structure POV; it could be found in the location of any function, variable, argument, field, literal struct-name or trait identifier. By making it a configurable legal ident, it will not take any syntax space. This is distinct to the underscore character in the type context (which performs a different function, it leaves a gap where the surrounding context is enough to infer *exactly* what is going on). -The query could be used in the following ways +The query would be used in the following ways:- -```fn foo( a:T) { a.do_something() } // ask what traits have a method 'do_something()'``` +- querying functions, based on parameters/return values:- + +```{ a._() } // ask for available member functions of a, similar to classic 'dot-autocomplete'``` +```{ a._(b) } // ask for available member functions of a, taking 'b' - beyond classic autocomplete, it can be guided by more parameters (not just the first)``` + +```{ a._(b,_) } // ask for available member functions of a, taking 'b' - beyond classic autocomplete, it can be guided by more parameters (not just the first)``` ```fn foo(a:&X)->Y { _(a) } // ask for functions close to fitting the signature ( &X)->Y ``` + +```{ ... foo(_) ... } report the arguments 'foo' should take``` + ```fn foo(a:&X)->Z { a._()._()} // ask for any functions X->Y , Y->Z and possible 'Y'``` ```_::bar(x,y,z) // ask for full paths of any functions bar(..)``` +```fn foo( a:T) { a.do_something() } // ask what traits have a method 'do_something()'``` + +- querying struct fields:- ```foo._.bar - ... what member has a sub-member .bar (maybe make it also show,``` ```foo._._.bar foo._._._.bar, i.e. search the object graph.. this is a big deal with complex data structures. )``` + +- Querying whole program inference:- ```fn foo(a,b,c)->_ {... do stuff...} .. Do full whole-program inference from any calls TO 'foo', and report what signature this function needs to fit it's uses.. the scenario appears when you factor code out.``` -```{ ... foo(_) ... } report the arguments 'foo' should take``` If the compiler output was formatted nicely (I dont know the full plan with the RLS) perhaps this could be used directly for IDE/editor integration; imagine if output of underscore queries could be collected by an IDE and placed in dropbox menus under the text; this could yield a unique editing experience beyond existing autocomplete IDEs?. From 82f967a77b400306448e3609d83bcc913038bb2d Mon Sep 17 00:00:00 2001 From: dobkeratops Date: Thu, 13 Jul 2017 15:24:40 +0100 Subject: [PATCH 23/39] Update 0000-ask_the_compiler_placeholder_ident.md --- ...0000-ask_the_compiler_placeholder_ident.md | 87 +++++++++---------- 1 file changed, 40 insertions(+), 47 deletions(-) diff --git a/text/0000-ask_the_compiler_placeholder_ident.md b/text/0000-ask_the_compiler_placeholder_ident.md index e64aaa52223..06e2d07d362 100644 --- a/text/0000-ask_the_compiler_placeholder_ident.md +++ b/text/0000-ask_the_compiler_placeholder_ident.md @@ -4,76 +4,69 @@ # Summary -This is inspired by haskell holes: Add a 'placeholder identifier' to the AST; when encountered, it passes through type inference; it does not resolve to an actual definition, but instead assumes it is 'whatever needed' to fit the demands around it, and allows the rest of the program to contiue compiling (resolving/typechecking). - -Compiling a program with placeholders will fail, but gives extra informative error messages reporting (a) the types at that point, and (b) potential symbols that fit. +allow the ommision of function parameter types and the return type in the implementaiton of a trait for a type. # Motivation -This is to assist navigation and discovery during the compile-edit cycle, doing a similar job to IDE 'dot-autocomplete', but leveraging Rust's more advanced 2-way type inference by making deliberate queries with more information. - -Already people use the trick of 'let _:()=expr_' to query the type as an error, but these queries would allow the inference engine to work harder. - -Improving compile time feedback pushes the community forward whilst we wait for IDE tools (with more complex integration) to stabilize and refine. - -# Detailed design - -It requires the AST to contain the concept of a query in an ident slot, even though the presence of a query signifies that this program cannot compile. - -see earlier forum post, -https://internals.rust-lang.org/t/ask-the-compiler-syntax-e-g--/700 - -The placeholder would be configurable (by commandline option) to avoid any clash, but a sane default would be a single underscore. -The placeholder parses as any other ident from a syntacital structure POV; it could be found in the location of any function, variable, argument, field, literal struct-name or trait identifier. - -By making it a configurable legal ident, it will not take any syntax space. +Rust signatures can become quite heavy with nested angle-bracketed types, lifetimes etc. -This is distinct to the underscore character in the type context (which performs a different function, it leaves a gap where the surrounding context is enough to infer *exactly* what is going on). +Conversely, rust has a very powerful inference engine. -The query would be used in the following ways:- +Also,coming from C++, the need to write traits before you can 'overload' comes as a shock. +If however the informtion in the trait declaration was used to avoid repeating detailed information, they would come across as more of a virtue: writing them would more directly *save* future repition when writing many functions following a similar pattern. -- querying functions, based on parameters/return values:- +Note that this would not make writing the implementation any harder: Unlike with general purpose inference , the constraining informtion has already been supplied in the trait itself; the compiler already knows that one must match the other, and when it doesn't it reports an error. Compared to C++, Rusts syntax allows the ommision of types whilst still parsing in a straightforward manner, creating this opportunity. -```{ a._() } // ask for available member functions of a, similar to classic 'dot-autocomplete'``` -```{ a._(b) } // ask for available member functions of a, taking 'b' - beyond classic autocomplete, it can be guided by more parameters (not just the first)``` +Behaviour of this type can be seen in the Haskell language, e.g -```{ a._(b,_) } // ask for available member functions of a, taking 'b' - beyond classic autocomplete, it can be guided by more parameters (not just the first)``` +class FooBar f where -- typeclass definition (roughly = Rust trait) + foo::f->i32->[i32]->String -- only write function names and type signatures + bar::f->[String]->String->Maybe String + +instance FooBar Apple where -- typeclass instance (roughly = Rust impl) + foo s x y = ..1.. -- only write the variables names and function definition + bar s z w = ..2.. + +instance FooBar Banana where + foo s x y = ..3.. -- only write the variables names and function definition + bar s z w = ..4.. -```fn foo(a:&X)->Y { _(a) } // ask for functions close to fitting the signature ( &X)->Y ``` - -```{ ... foo(_) ... } report the arguments 'foo' should take``` - -```fn foo(a:&X)->Z { a._()._()} // ask for any functions X->Y , Y->Z and possible 'Y'``` - -```_::bar(x,y,z) // ask for full paths of any functions bar(..)``` - -```fn foo( a:T) { a.do_something() } // ask what traits have a method 'do_something()'``` - -- querying struct fields:- -```foo._.bar - ... what member has a sub-member .bar (maybe make it also show,``` - -```foo._._.bar foo._._._.bar, i.e. search the object graph.. this is a big deal with complex data structures. )``` +(..1.. etc denote function definition bodies) +# Detailed design -- Querying whole program inference:- -```fn foo(a,b,c)->_ {... do stuff...} .. Do full whole-program inference from any calls TO 'foo', and report what signature this function needs to fit it's uses.. the scenario appears when you factor code out.``` +by example: the proposal is to allow the following (..1.. etc denote the function definition bodies roughly equivalent to the pattern above) + struct Apple(i32); struct Banana(String) + trait FooBar { + fn foo(&self, x:i32, y:Vec)->i32; + fn bar(&self, z:&Vec, w:&String)->Option; + } + impl FooBar for Apple { + fn foo(&self, x,y){ ..1.. } // no need to repeat i32 Vec ->i32 + fn bar(&self, z,w){ ..2.. } // no need to repeat Vec , String -> Option + } + + impl FooBar for Banana { + fn foo(&self, x,y){ ..3.. } // no need to repeat i32 ->i32 + fn bar(&self, z,w){ ..4.. } // no need to repeat Vec , String -> Option + } + -If the compiler output was formatted nicely (I dont know the full plan with the RLS) perhaps this could be used directly for IDE/editor integration; imagine if output of underscore queries could be collected by an IDE and placed in dropbox menus under the text; this could yield a unique editing experience beyond existing autocomplete IDEs?. +# Drawbacks -# Drawbacks +One potential objection is that you can no longer see the types when you read the impl. +However, whilst engaged in the compile-edit cycle, the compiler can directly report what the types should be if you make an error; also the programmer *must* have the trait documentation or original source at hand (or gain enough guidance from the error message) in order to actually write the implementation in the first place. # Alternatives -Putting all similar effort into IDE integration. -it might be possible to treat *all* unresolved symbols this way - the compiler already does make a lot of suggestions - but the idea is for a deliberate query that can invoke heavier work. -I note that since I made this suggestion a while back significant progress has been made the with "RLS", but perhaps there is synergy with the other peices IDE support needs. +allowing more general whole-program inference # Unresolved questions From 2299860f812f70a2d41ed48cac2ad03f98dc641e Mon Sep 17 00:00:00 2001 From: dobkeratops Date: Thu, 13 Jul 2017 15:27:28 +0100 Subject: [PATCH 24/39] Update 0000-ask_the_compiler_placeholder_ident.md --- text/0000-ask_the_compiler_placeholder_ident.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/text/0000-ask_the_compiler_placeholder_ident.md b/text/0000-ask_the_compiler_placeholder_ident.md index 06e2d07d362..402079c735f 100644 --- a/text/0000-ask_the_compiler_placeholder_ident.md +++ b/text/0000-ask_the_compiler_placeholder_ident.md @@ -13,9 +13,9 @@ Rust signatures can become quite heavy with nested angle-bracketed types, lifeti Conversely, rust has a very powerful inference engine. Also,coming from C++, the need to write traits before you can 'overload' comes as a shock. -If however the informtion in the trait declaration was used to avoid repeating detailed information, they would come across as more of a virtue: writing them would more directly *save* future repition when writing many functions following a similar pattern. +If however the informtion in the trait declaration was used to avoid repeating detailed information, they would come across as more of a virtue: writing them would directly *save* future repition when writing many functions following a similar pattern. -Note that this would not make writing the implementation any harder: Unlike with general purpose inference , the constraining informtion has already been supplied in the trait itself; the compiler already knows that one must match the other, and when it doesn't it reports an error. Compared to C++, Rusts syntax allows the ommision of types whilst still parsing in a straightforward manner, creating this opportunity. +Note that this would not make writing the implementation any harder: Unlike with general purpose whole-program inference , constraining is already implied by the trait itself; the compiler already knows that one must match the other, and when it doesn't it reports an error. Compared to C++, Rusts syntax allows the ommision of types whilst still parsing parameter names in a straightforward manner, creating this opportunity. Behaviour of this type can be seen in the Haskell language, e.g From 5fdffaa5a22bc1b105fdbf19222c7107bc8fabbe Mon Sep 17 00:00:00 2001 From: dobkeratops Date: Thu, 13 Jul 2017 15:38:24 +0100 Subject: [PATCH 25/39] Update 0000-ask_the_compiler_placeholder_ident.md --- ...0000-ask_the_compiler_placeholder_ident.md | 39 ++++++++++--------- 1 file changed, 20 insertions(+), 19 deletions(-) diff --git a/text/0000-ask_the_compiler_placeholder_ident.md b/text/0000-ask_the_compiler_placeholder_ident.md index 402079c735f..e8b16baafe5 100644 --- a/text/0000-ask_the_compiler_placeholder_ident.md +++ b/text/0000-ask_the_compiler_placeholder_ident.md @@ -8,31 +8,31 @@ allow the ommision of function parameter types and the return type in the implem # Motivation -Rust signatures can become quite heavy with nested angle-bracketed types, lifetimes etc. +Rust signatures can become quite heavy with nested angle-bracketed types, lifetimes etc, +Also,coming from C++, the need to write and reference traits *before* you can 'overload' functions comes as a shock. -Conversely, rust has a very powerful inference engine. - -Also,coming from C++, the need to write traits before you can 'overload' comes as a shock. -If however the informtion in the trait declaration was used to avoid repeating detailed information, they would come across as more of a virtue: writing them would directly *save* future repition when writing many functions following a similar pattern. +If,however, the informtion in the trait declaration was used to avoid repeating detailed information, they would come across as more of a virtue: writing/referenceing them would directly *save* repition when writing many functions following a similar pattern. Note that this would not make writing the implementation any harder: Unlike with general purpose whole-program inference , constraining is already implied by the trait itself; the compiler already knows that one must match the other, and when it doesn't it reports an error. Compared to C++, Rusts syntax allows the ommision of types whilst still parsing parameter names in a straightforward manner, creating this opportunity. Behaviour of this type can be seen in the Haskell language, e.g -class FooBar f where -- typeclass definition (roughly = Rust trait) - foo::f->i32->[i32]->String -- only write function names and type signatures - bar::f->[String]->String->Maybe String + class FooBar f where -- typeclass definition (roughly = Rust trait) + foo::f->i32->[i32]->String -- only write function names and function signatures + bar::f->[String]->String->Maybe String -instance FooBar Apple where -- typeclass instance (roughly = Rust impl) - foo s x y = ..1.. -- only write the variables names and function definition - bar s z w = ..2.. + instance FooBar Apple where -- typeclass instance (roughly = Rust impl) + foo s x y = ..1.. -- only write the argument names and function definition + bar s z w = ..2.. -instance FooBar Banana where - foo s x y = ..3.. -- only write the variables names and function definition - bar s z w = ..4.. + instance FooBar Banana where + foo s x y = ..3.. -- only write the argument names and function definition + bar s z w = ..4.. (..1.. etc denote function definition bodies) +In particular with the traits for operator overloads, the type information is more directly specified in the trait itself + # Detailed design by example: the proposal is to allow the following (..1.. etc denote the function definition bodies roughly equivalent to the pattern above) @@ -44,13 +44,13 @@ by example: the proposal is to allow the following (..1.. etc denote the functio } impl FooBar for Apple { - fn foo(&self, x,y){ ..1.. } // no need to repeat i32 Vec ->i32 - fn bar(&self, z,w){ ..2.. } // no need to repeat Vec , String -> Option + fn foo(&self, x,y){ ..1.. } // no need to repeat :i32 :Vec ->i32 + fn bar(&self, z,w){ ..2.. } // no need to repeat :&Vec , :String -> Option } impl FooBar for Banana { - fn foo(&self, x,y){ ..3.. } // no need to repeat i32 ->i32 - fn bar(&self, z,w){ ..4.. } // no need to repeat Vec , String -> Option + fn foo(&self, x,y){ ..3.. } // no need to repeat :i32 ->i32 + fn bar(&self, z,w){ ..4.. } // no need to repeat :Vec , :String -> Option } @@ -66,7 +66,8 @@ However, whilst engaged in the compile-edit cycle, the compiler can directly rep # Alternatives -allowing more general whole-program inference +allowing more general whole-program inference; +another way to streamline the number of mental steps when writing trait 'impls' would be to swap the trait/self-type order as this is more coherent with the function declarations themselves (no need to mentally swap them back and forth), as well as 'trait object casting' (type as trait) and disambiguation syntax ::method_name() ; this would be the subject of another RFC. It would be an alternate declaration syntax complemeting the existing one. impl type as trait {..}, or impl type:trait {} It would complement this suggestion. # Unresolved questions From 52330851519c24ed5ad3620b1ad4711baf85bf4c Mon Sep 17 00:00:00 2001 From: dobkeratops Date: Thu, 13 Jul 2017 15:41:53 +0100 Subject: [PATCH 26/39] Update 0000-ask_the_compiler_placeholder_ident.md --- text/0000-ask_the_compiler_placeholder_ident.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/text/0000-ask_the_compiler_placeholder_ident.md b/text/0000-ask_the_compiler_placeholder_ident.md index e8b16baafe5..4831ae1c64d 100644 --- a/text/0000-ask_the_compiler_placeholder_ident.md +++ b/text/0000-ask_the_compiler_placeholder_ident.md @@ -8,12 +8,12 @@ allow the ommision of function parameter types and the return type in the implem # Motivation -Rust signatures can become quite heavy with nested angle-bracketed types, lifetimes etc, +Rust signatures can become quite heavy with nested angle-bracketed types, trait-bounds, lifetimes etc, Also,coming from C++, the need to write and reference traits *before* you can 'overload' functions comes as a shock. -If,however, the informtion in the trait declaration was used to avoid repeating detailed information, they would come across as more of a virtue: writing/referenceing them would directly *save* repition when writing many functions following a similar pattern. +However, if the informtion in the trait declaration was used to avoid repeating information, they would come across as more of a virtue: writing and referenceing them would directly *save* repetition when writing many functions following a similar pattern. -Note that this would not make writing the implementation any harder: Unlike with general purpose whole-program inference , constraining is already implied by the trait itself; the compiler already knows that one must match the other, and when it doesn't it reports an error. Compared to C++, Rusts syntax allows the ommision of types whilst still parsing parameter names in a straightforward manner, creating this opportunity. +Note that this would not make writing the implementation any harder: Unlike with general purpose whole-program inference , constraining is already implied by the trait itself; the compiler already knows that one must match the other, and when it doesn't it reports an error. Compared to C++, Rusts syntax allows the ommision of types whilst still parsing parameter names in a straightforward manner, creating this opportunity. The lack of overloading *within* a trait/impl means there is no need to write the types to disambiguate the functions; you would be fully leveraging the trait name to do that. Behaviour of this type can be seen in the Haskell language, e.g From 47b67a09aecc308d1e8c9311f20f2829566bd8fe Mon Sep 17 00:00:00 2001 From: dobkeratops Date: Thu, 13 Jul 2017 15:45:55 +0100 Subject: [PATCH 27/39] Rename 0000-ask_the_compiler_placeholder_ident.md to infer function parameter and return types from the original trait declaration into impl blocks --- ...rn types from the original trait declaration into impl blocks} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename text/{0000-ask_the_compiler_placeholder_ident.md => infer function parameter and return types from the original trait declaration into impl blocks} (100%) diff --git a/text/0000-ask_the_compiler_placeholder_ident.md b/text/infer function parameter and return types from the original trait declaration into impl blocks similarity index 100% rename from text/0000-ask_the_compiler_placeholder_ident.md rename to text/infer function parameter and return types from the original trait declaration into impl blocks From 184dbd46e8c941a07e95b3732b496a96e6b5059a Mon Sep 17 00:00:00 2001 From: dobkeratops Date: Thu, 13 Jul 2017 15:46:49 +0100 Subject: [PATCH 28/39] Rename infer function parameter and return types from the original trait declaration into impl blocks to infer function signatures from trait declaration into impls --- ...> infer function signatures from trait declaration into impls} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename text/{infer function parameter and return types from the original trait declaration into impl blocks => infer function signatures from trait declaration into impls} (100%) diff --git a/text/infer function parameter and return types from the original trait declaration into impl blocks b/text/infer function signatures from trait declaration into impls similarity index 100% rename from text/infer function parameter and return types from the original trait declaration into impl blocks rename to text/infer function signatures from trait declaration into impls From a5090a638e17dd8f235e63bce136cf418f285a55 Mon Sep 17 00:00:00 2001 From: dobkeratops Date: Thu, 13 Jul 2017 15:57:04 +0100 Subject: [PATCH 29/39] Update infer function signatures from trait declaration into impls --- ...er function signatures from trait declaration into impls | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/text/infer function signatures from trait declaration into impls b/text/infer function signatures from trait declaration into impls index 4831ae1c64d..86a1eda69ae 100644 --- a/text/infer function signatures from trait declaration into impls +++ b/text/infer function signatures from trait declaration into impls @@ -4,14 +4,14 @@ # Summary -allow the ommision of function parameter types and the return type in the implementaiton of a trait for a type. +Allow the ommision of function parameters and return types, in the implementaiton of a trait for a type; infer this information directly from the trait declaration. # Motivation Rust signatures can become quite heavy with nested angle-bracketed types, trait-bounds, lifetimes etc, -Also,coming from C++, the need to write and reference traits *before* you can 'overload' functions comes as a shock. +Also,coming from C++, the need to write (and reference) traits *before* you can 'overload' functions comes as a shock. -However, if the informtion in the trait declaration was used to avoid repeating information, they would come across as more of a virtue: writing and referenceing them would directly *save* repetition when writing many functions following a similar pattern. +However, if the informtion in the trait declaration was used to avoid repeating information, they would come across as more of a virtue: they would directly *save* repetition when writing many functions following a similar pattern. You would leverage the trait name to specify many signatures. Note that this would not make writing the implementation any harder: Unlike with general purpose whole-program inference , constraining is already implied by the trait itself; the compiler already knows that one must match the other, and when it doesn't it reports an error. Compared to C++, Rusts syntax allows the ommision of types whilst still parsing parameter names in a straightforward manner, creating this opportunity. The lack of overloading *within* a trait/impl means there is no need to write the types to disambiguate the functions; you would be fully leveraging the trait name to do that. From 4ee9e16ba3fa570359ae8b2f579b58e58e8b09c8 Mon Sep 17 00:00:00 2001 From: dobkeratops Date: Fri, 14 Jul 2017 07:37:19 +0100 Subject: [PATCH 30/39] Update infer function signatures from trait declaration into impls --- ...gnatures from trait declaration into impls | 45 ++++++++++++++----- 1 file changed, 35 insertions(+), 10 deletions(-) diff --git a/text/infer function signatures from trait declaration into impls b/text/infer function signatures from trait declaration into impls index 86a1eda69ae..2b8335add72 100644 --- a/text/infer function signatures from trait declaration into impls +++ b/text/infer function signatures from trait declaration into impls @@ -4,21 +4,32 @@ # Summary -Allow the ommision of function parameters and return types, in the implementaiton of a trait for a type; infer this information directly from the trait declaration. +Allow the ommision of function parameters and return types, in the implementaiton of a trait for a type; +infer this information directly from the trait declaration. # Motivation Rust signatures can become quite heavy with nested angle-bracketed types, trait-bounds, lifetimes etc, -Also,coming from C++, the need to write (and reference) traits *before* you can 'overload' functions comes as a shock. - -However, if the informtion in the trait declaration was used to avoid repeating information, they would come across as more of a virtue: they would directly *save* repetition when writing many functions following a similar pattern. You would leverage the trait name to specify many signatures. - -Note that this would not make writing the implementation any harder: Unlike with general purpose whole-program inference , constraining is already implied by the trait itself; the compiler already knows that one must match the other, and when it doesn't it reports an error. Compared to C++, Rusts syntax allows the ommision of types whilst still parsing parameter names in a straightforward manner, creating this opportunity. The lack of overloading *within* a trait/impl means there is no need to write the types to disambiguate the functions; you would be fully leveraging the trait name to do that. +Also,coming from C++, the need to write (and reference) traits *before* you write 'overloads' functions comes as a shock, +especially for people trying to escape the repitition of 'header files'. + +However, if the trait declaration was used to avoid repeating information, +they would come across as more of a virtue: +they would directly *save* repetition when writing many functions following a similar pattern. +You would leverage the trait name to specify many signatures. + +Note that this would not make writing the implementation any harder: +Unlike with general purpose whole-program inference , constraining is already implied by the trait itself; +the compiler already knows that one must match the other, and when it doesn't it reports an error. +Compared to C++, Rusts syntax allows the ommision of types whilst still parsing parameter names in a straightforward manner, +creating this opportunity. +The lack of overloading *within* a trait/impl means there is no need to write the types to disambiguate the functions; +you would be fully leveraging the trait name to do that. Behaviour of this type can be seen in the Haskell language, e.g class FooBar f where -- typeclass definition (roughly = Rust trait) - foo::f->i32->[i32]->String -- only write function names and function signatures + foo::f->i32->[i32]->String -- only write function signatures bar::f->[String]->String->Maybe String instance FooBar Apple where -- typeclass instance (roughly = Rust impl) @@ -28,6 +39,7 @@ Behaviour of this type can be seen in the Haskell language, e.g instance FooBar Banana where foo s x y = ..3.. -- only write the argument names and function definition bar s z w = ..4.. + (..1.. etc denote function definition bodies) @@ -35,7 +47,8 @@ In particular with the traits for operator overloads, the type information is mo # Detailed design -by example: the proposal is to allow the following (..1.. etc denote the function definition bodies roughly equivalent to the pattern above) +by example: the proposal is to allow the following to compile +(..1.. etc denote the function definition bodies roughly equivalent to the pattern above) struct Apple(i32); struct Banana(String) trait FooBar { @@ -61,13 +74,25 @@ by example: the proposal is to allow the following (..1.. etc denote the functio One potential objection is that you can no longer see the types when you read the impl. -However, whilst engaged in the compile-edit cycle, the compiler can directly report what the types should be if you make an error; also the programmer *must* have the trait documentation or original source at hand (or gain enough guidance from the error message) in order to actually write the implementation in the first place. +However, whilst engaged in the compile-edit cycle, the compiler can directly report what the types should be, +if you make an error; +also the programmer *must* have the trait documentation or original source at hand +(or gain enough guidance from the error message) in order to actually write the implementation in the first place. + +As such , this should not be a problem - even for cross-module implementations # Alternatives allowing more general whole-program inference; -another way to streamline the number of mental steps when writing trait 'impls' would be to swap the trait/self-type order as this is more coherent with the function declarations themselves (no need to mentally swap them back and forth), as well as 'trait object casting' (type as trait) and disambiguation syntax ::method_name() ; this would be the subject of another RFC. It would be an alternate declaration syntax complemeting the existing one. impl type as trait {..}, or impl type:trait {} It would complement this suggestion. +another way to streamline the number of mental steps when writing trait 'impls' +would be to swap the trait/self-type order as this is more coherent with the function declarations themselves +(no need to mentally swap them back and forth), as well as 'trait object casting' (type as trait) +and disambiguation syntax ::method_name() ; +this would be the subject of another RFC (a very different request aimed at an overlapping scenario) +It would be an alternate declaration syntax complemeting the existing one. +impl type as trait {..}, or impl type:trait {} It would complement this suggestion. + # Unresolved questions From 29f7020285928d71557738d9d77c6d04445d7a83 Mon Sep 17 00:00:00 2001 From: dobkeratops Date: Fri, 14 Jul 2017 07:48:36 +0100 Subject: [PATCH 31/39] Update infer function signatures from trait declaration into impls --- ...gnatures from trait declaration into impls | 28 +++++++++---------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/text/infer function signatures from trait declaration into impls b/text/infer function signatures from trait declaration into impls index 2b8335add72..6fb79f12d78 100644 --- a/text/infer function signatures from trait declaration into impls +++ b/text/infer function signatures from trait declaration into impls @@ -4,23 +4,24 @@ # Summary -Allow the ommision of function parameters and return types, in the implementaiton of a trait for a type; -infer this information directly from the trait declaration. +Allow the ommision of function parameters and return types, in the implementation of a trait for a type; +Infer this information directly from the trait declaration. # Motivation Rust signatures can become quite heavy with nested angle-bracketed types, trait-bounds, lifetimes etc, -Also,coming from C++, the need to write (and reference) traits *before* you write 'overloads' functions comes as a shock, +Also,coming from C++, the need to write (and reference) traits *before* you can write 'overloads' comes as a shock, especially for people trying to escape the repitition of 'header files'. -However, if the trait declaration was used to avoid repeating information, +However, if the trait was used to avoid repeating information, they would come across as more of a virtue: they would directly *save* repetition when writing many functions following a similar pattern. -You would leverage the trait name to specify many signatures. +You would leverage the trait name to specify many detailed signatures. + +Note that this would not make writing the implementation any harder:- -Note that this would not make writing the implementation any harder: Unlike with general purpose whole-program inference , constraining is already implied by the trait itself; -the compiler already knows that one must match the other, and when it doesn't it reports an error. +The compiler already knows that one must match the other, and when it doesn't it reports an error. Compared to C++, Rusts syntax allows the ommision of types whilst still parsing parameter names in a straightforward manner, creating this opportunity. The lack of overloading *within* a trait/impl means there is no need to write the types to disambiguate the functions; @@ -42,13 +43,12 @@ Behaviour of this type can be seen in the Haskell language, e.g (..1.. etc denote function definition bodies) - -In particular with the traits for operator overloads, the type information is more directly specified in the trait itself + # Detailed design by example: the proposal is to allow the following to compile -(..1.. etc denote the function definition bodies roughly equivalent to the pattern above) +(/*..1..*/ etc denote the function definition bodies roughly equivalent to the pattern above) struct Apple(i32); struct Banana(String) trait FooBar { @@ -57,13 +57,13 @@ by example: the proposal is to allow the following to compile } impl FooBar for Apple { - fn foo(&self, x,y){ ..1.. } // no need to repeat :i32 :Vec ->i32 - fn bar(&self, z,w){ ..2.. } // no need to repeat :&Vec , :String -> Option + fn foo(&self, x,y){ /*..1..*/ } // no need to repeat :i32 :Vec ->i32 + fn bar(&self, z,w){ /*..2..*/ } // no need to repeat :&Vec , :String -> Option } impl FooBar for Banana { - fn foo(&self, x,y){ ..3.. } // no need to repeat :i32 ->i32 - fn bar(&self, z,w){ ..4.. } // no need to repeat :Vec , :String -> Option + fn foo(&self, x,y){ /*..3..*/ } // no need to repeat :i32 ->i32 + fn bar(&self, z,w){ /*..4..*/ } // no need to repeat :Vec , :String -> Option } From cafd5c5964022f9055635d5584e9a9816f969198 Mon Sep 17 00:00:00 2001 From: dobkeratops Date: Fri, 14 Jul 2017 08:01:58 +0100 Subject: [PATCH 32/39] Update infer function signatures from trait declaration into impls --- ...infer function signatures from trait declaration into impls | 3 +++ 1 file changed, 3 insertions(+) diff --git a/text/infer function signatures from trait declaration into impls b/text/infer function signatures from trait declaration into impls index 6fb79f12d78..0ad192abf8a 100644 --- a/text/infer function signatures from trait declaration into impls +++ b/text/infer function signatures from trait declaration into impls @@ -79,6 +79,9 @@ if you make an error; also the programmer *must* have the trait documentation or original source at hand (or gain enough guidance from the error message) in order to actually write the implementation in the first place. +as far as users go, the point is the trait should suffice; there may be example code close to the trait decl; +trait implemenations are easy to search for, thanks to rusts syntax. + As such , this should not be a problem - even for cross-module implementations From 22d2f789901f6d8ba0b6c2a3becaaa7d79d0fa7d Mon Sep 17 00:00:00 2001 From: dobkeratops Date: Sat, 22 Jul 2017 09:30:14 +0100 Subject: [PATCH 33/39] Rename infer function signatures from trait declaration into impls to infer function signatures from trait declaration into impls.md --- ...nfer function signatures from trait declaration into impls.md} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename text/{infer function signatures from trait declaration into impls => infer function signatures from trait declaration into impls.md} (100%) diff --git a/text/infer function signatures from trait declaration into impls b/text/infer function signatures from trait declaration into impls.md similarity index 100% rename from text/infer function signatures from trait declaration into impls rename to text/infer function signatures from trait declaration into impls.md From c6846a04258d51febecd686c3fc545e0c98dd584 Mon Sep 17 00:00:00 2001 From: dobkeratops Date: Sat, 22 Jul 2017 09:35:26 +0100 Subject: [PATCH 34/39] Update infer function signatures from trait declaration into impls.md --- ...function signatures from trait declaration into impls.md | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/text/infer function signatures from trait declaration into impls.md b/text/infer function signatures from trait declaration into impls.md index 0ad192abf8a..9174dc032c9 100644 --- a/text/infer function signatures from trait declaration into impls.md +++ b/text/infer function signatures from trait declaration into impls.md @@ -13,7 +13,7 @@ Rust signatures can become quite heavy with nested angle-bracketed types, trait- Also,coming from C++, the need to write (and reference) traits *before* you can write 'overloads' comes as a shock, especially for people trying to escape the repitition of 'header files'. -However, if the trait was used to avoid repeating information, +However, if the trait was used to *avoid* repeating information, they would come across as more of a virtue: they would directly *save* repetition when writing many functions following a similar pattern. You would leverage the trait name to specify many detailed signatures. @@ -44,6 +44,8 @@ Behaviour of this type can be seen in the Haskell language, e.g (..1.. etc denote function definition bodies) + +The trait is still usually very easy to find - thanks to Rusts syntax, declarations are easy to grep for. # Detailed design @@ -66,7 +68,9 @@ by example: the proposal is to allow the following to compile fn bar(&self, z,w){ /*..4..*/ } // no need to repeat :Vec , :String -> Option } +## concern about return values +A variation would be to require a trailing placeholder ```->_``` to make it clearer if there is a return value # Drawbacks From 438be12b5ada2071255570e824732c83aa4e907d Mon Sep 17 00:00:00 2001 From: dobkeratops Date: Sat, 22 Jul 2017 09:36:21 +0100 Subject: [PATCH 35/39] Update infer function signatures from trait declaration into impls.md --- ...fer function signatures from trait declaration into impls.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/text/infer function signatures from trait declaration into impls.md b/text/infer function signatures from trait declaration into impls.md index 9174dc032c9..b769ac3fb1b 100644 --- a/text/infer function signatures from trait declaration into impls.md +++ b/text/infer function signatures from trait declaration into impls.md @@ -50,7 +50,7 @@ The trait is still usually very easy to find - thanks to Rusts syntax, declarati # Detailed design by example: the proposal is to allow the following to compile -(/*..1..*/ etc denote the function definition bodies roughly equivalent to the pattern above) +(```/*..1..*/``` etc denote the function definition bodies roughly equivalent to the pattern above) struct Apple(i32); struct Banana(String) trait FooBar { From c78d53ece945a98bb00b01db4a5551239430a5cd Mon Sep 17 00:00:00 2001 From: dobkeratops Date: Sat, 29 Jul 2017 21:03:12 +0100 Subject: [PATCH 36/39] Update infer function signatures from trait declaration into impls.md --- ...unction signatures from trait declaration into impls.md | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/text/infer function signatures from trait declaration into impls.md b/text/infer function signatures from trait declaration into impls.md index b769ac3fb1b..b1b97a90bae 100644 --- a/text/infer function signatures from trait declaration into impls.md +++ b/text/infer function signatures from trait declaration into impls.md @@ -13,6 +13,8 @@ Rust signatures can become quite heavy with nested angle-bracketed types, trait- Also,coming from C++, the need to write (and reference) traits *before* you can write 'overloads' comes as a shock, especially for people trying to escape the repitition of 'header files'. +(Furthermore, the types are in a different location ```type argname``` vs ```argname:type```. ) + However, if the trait was used to *avoid* repeating information, they would come across as more of a virtue: they would directly *save* repetition when writing many functions following a similar pattern. @@ -91,8 +93,8 @@ As such , this should not be a problem - even for cross-module implementations # Alternatives -allowing more general whole-program inference; -another way to streamline the number of mental steps when writing trait 'impls' +* allowing more general whole-program inference; +* another way to streamline the number of mental steps when writing trait 'impls' would be to swap the trait/self-type order as this is more coherent with the function declarations themselves (no need to mentally swap them back and forth), as well as 'trait object casting' (type as trait) and disambiguation syntax ::method_name() ; @@ -100,6 +102,7 @@ this would be the subject of another RFC (a very different request aimed at an o It would be an alternate declaration syntax complemeting the existing one. impl type as trait {..}, or impl type:trait {} It would complement this suggestion. +* Getting back to the expectations from C++, if writing the types out, one might expect the reverse: that the language could infer which *trait* is being implemented, allowing that to be ommitted; unfortunately this goes against the idea that the trait is part of the function's namespace. # Unresolved questions From e5a740358a83db38a93c646cce2384c355a68291 Mon Sep 17 00:00:00 2001 From: dobkeratops Date: Sat, 29 Jul 2017 21:08:53 +0100 Subject: [PATCH 37/39] Update infer function signatures from trait declaration into impls.md --- ...unction signatures from trait declaration into impls.md | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/text/infer function signatures from trait declaration into impls.md b/text/infer function signatures from trait declaration into impls.md index b1b97a90bae..723634ce48e 100644 --- a/text/infer function signatures from trait declaration into impls.md +++ b/text/infer function signatures from trait declaration into impls.md @@ -23,7 +23,8 @@ You would leverage the trait name to specify many detailed signatures. Note that this would not make writing the implementation any harder:- Unlike with general purpose whole-program inference , constraining is already implied by the trait itself; -The compiler already knows that one must match the other, and when it doesn't it reports an error. +The compiler already knows that one must match the other, and when it doesn't it reports an error. + Compared to C++, Rusts syntax allows the ommision of types whilst still parsing parameter names in a straightforward manner, creating this opportunity. The lack of overloading *within* a trait/impl means there is no need to write the types to disambiguate the functions; @@ -85,8 +86,8 @@ if you make an error; also the programmer *must* have the trait documentation or original source at hand (or gain enough guidance from the error message) in order to actually write the implementation in the first place. -as far as users go, the point is the trait should suffice; there may be example code close to the trait decl; -trait implemenations are easy to search for, thanks to rusts syntax. +as far as users go, the point is refering to the trait should suffice; there may be example code close to the trait decl; +trait implemenations are easy to search for, thanks to rusts syntax. *RustDoc* already gives browseable reference; trait declarations are very easy to grep for, and future IDE tools may have other interactive assists. As such , this should not be a problem - even for cross-module implementations From def4117cc6590b7c2367e942730ef7a4491f4fda Mon Sep 17 00:00:00 2001 From: dobkeratops Date: Wed, 6 Sep 2017 20:03:10 +0100 Subject: [PATCH 38/39] Update infer function signatures from trait declaration into impls.md --- ...tures from trait declaration into impls.md | 23 ++++++++++--------- 1 file changed, 12 insertions(+), 11 deletions(-) diff --git a/text/infer function signatures from trait declaration into impls.md b/text/infer function signatures from trait declaration into impls.md index 723634ce48e..6b80264436a 100644 --- a/text/infer function signatures from trait declaration into impls.md +++ b/text/infer function signatures from trait declaration into impls.md @@ -13,16 +13,15 @@ Rust signatures can become quite heavy with nested angle-bracketed types, trait- Also,coming from C++, the need to write (and reference) traits *before* you can write 'overloads' comes as a shock, especially for people trying to escape the repitition of 'header files'. -(Furthermore, the types are in a different location ```type argname``` vs ```argname:type```. ) +(Furthermore, the types are in a different location ```type argname``` vs ```argname:type``` .. although more logical there is a cost to any convention-switch ) However, if the trait was used to *avoid* repeating information, -they would come across as more of a virtue: -they would directly *save* repetition when writing many functions following a similar pattern. +they would come across more obviously as a virtue: You would leverage the trait name to specify many detailed signatures. Note that this would not make writing the implementation any harder:- -Unlike with general purpose whole-program inference , constraining is already implied by the trait itself; +Unlike with general purpose whole-program inference , constraining is already implied (unambiguously) by the trait itself; The compiler already knows that one must match the other, and when it doesn't it reports an error. Compared to C++, Rusts syntax allows the ommision of types whilst still parsing parameter names in a straightforward manner, @@ -30,22 +29,22 @@ creating this opportunity. The lack of overloading *within* a trait/impl means there is no need to write the types to disambiguate the functions; you would be fully leveraging the trait name to do that. -Behaviour of this type can be seen in the Haskell language, e.g +Behaviour of this type can be seen in the Haskell language, i.e:- class FooBar f where -- typeclass definition (roughly = Rust trait) foo::f->i32->[i32]->String -- only write function signatures bar::f->[String]->String->Maybe String instance FooBar Apple where -- typeclass instance (roughly = Rust impl) - foo s x y = ..1.. -- only write the argument names and function definition - bar s z w = ..2.. + foo s x y = /*..1..*/ -- only write the argument names and function definition + bar s z w = /*..2..*/ instance FooBar Banana where - foo s x y = ..3.. -- only write the argument names and function definition - bar s z w = ..4.. + foo s x y = /*..3..*/ -- only write the argument names and function definition + bar s z w = /*..4..*/ -(..1.. etc denote function definition bodies) +(/*..1..*/ etc denote function definition bodies) The trait is still usually very easy to find - thanks to Rusts syntax, declarations are easy to grep for. @@ -71,6 +70,8 @@ by example: the proposal is to allow the following to compile fn bar(&self, z,w){ /*..4..*/ } // no need to repeat :Vec , :String -> Option } +Trait definitions are easy to grep, but to further streamline locating them, a "File:line: -see definition of " styl error message would tend to bring these into the text-editor as the user steps through error messages in the usual edit-compile cycle. + ## concern about return values A variation would be to require a trailing placeholder ```->_``` to make it clearer if there is a return value @@ -86,7 +87,7 @@ if you make an error; also the programmer *must* have the trait documentation or original source at hand (or gain enough guidance from the error message) in order to actually write the implementation in the first place. -as far as users go, the point is refering to the trait should suffice; there may be example code close to the trait decl; +as far as users go, refering to the trait should suffice; there may be example code close to the trait decl; trait implemenations are easy to search for, thanks to rusts syntax. *RustDoc* already gives browseable reference; trait declarations are very easy to grep for, and future IDE tools may have other interactive assists. As such , this should not be a problem - even for cross-module implementations From 8eeff4662fff45ca24821239402fd26a4d7f0454 Mon Sep 17 00:00:00 2001 From: dobkeratops Date: Wed, 6 Sep 2017 20:59:37 +0100 Subject: [PATCH 39/39] Update infer function signatures from trait declaration into impls.md --- ...r function signatures from trait declaration into impls.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/text/infer function signatures from trait declaration into impls.md b/text/infer function signatures from trait declaration into impls.md index 6b80264436a..307f74ab919 100644 --- a/text/infer function signatures from trait declaration into impls.md +++ b/text/infer function signatures from trait declaration into impls.md @@ -13,7 +13,7 @@ Rust signatures can become quite heavy with nested angle-bracketed types, trait- Also,coming from C++, the need to write (and reference) traits *before* you can write 'overloads' comes as a shock, especially for people trying to escape the repitition of 'header files'. -(Furthermore, the types are in a different location ```type argname``` vs ```argname:type``` .. although more logical there is a cost to any convention-switch ) +(Furthermore, the types are in a different location ```type argname``` vs ```argname:type``` .. although more logical there is a cost to any reading convention-switch ) However, if the trait was used to *avoid* repeating information, they would come across more obviously as a virtue: @@ -45,6 +45,8 @@ Behaviour of this type can be seen in the Haskell language, i.e:- (/*..1..*/ etc denote function definition bodies) + +Surprisingly, coming from C++ (where familiar users read ```Type argname```), a seperation into 'just types', and 'just names' is actually easier to adapt to (the absence of a detail, rather than the detail being in a different place) The trait is still usually very easy to find - thanks to Rusts syntax, declarations are easy to grep for.