about summary refs log tree commit diff
path: root/src/test
diff options
context:
space:
mode:
authorManish Goregaokar <manishsmail@gmail.com>2020-07-03 17:16:52 -0700
committerGitHub <noreply@github.com>2020-07-03 17:16:52 -0700
commit4a8d9ea80ff8d7ec4dcc6da7d36fe60ecaa55539 (patch)
tree95dcbc65f6c216af2314d646227859c0573d4522 /src/test
parentdf8f551e796e3dd86a1ea8fb23b96cefbc7cdf85 (diff)
parent93d662fd9d0e39145ac45fc08f35a619e0cb3f8c (diff)
downloadrust-4a8d9ea80ff8d7ec4dcc6da7d36fe60ecaa55539.tar.gz
rust-4a8d9ea80ff8d7ec4dcc6da7d36fe60ecaa55539.zip
Rollup merge of #73670 - davidhewitt:format-args-capture, r=varkor
Add `format_args_capture` feature

This is the initial implementation PR for [RFC 2795](https://github.com/rust-lang/rfcs/pull/2795).

Note that, as dicussed in the tracking issue (#67984), the feature gate has been called `format_args_capture`.

Next up I guess I need to add documentation for this feature. I've not written any docs before for rustc / std so I would appreciate suggestions on where I should add docs.
Diffstat (limited to 'src/test')
-rw-r--r--src/test/ui/fmt/feature-gate-format-args-capture.rs6
-rw-r--r--src/test/ui/fmt/feature-gate-format-args-capture.stderr18
-rw-r--r--src/test/ui/fmt/format-args-capture-macro-hygiene.rs6
-rw-r--r--src/test/ui/fmt/format-args-capture-macro-hygiene.stderr22
-rw-r--r--src/test/ui/fmt/format-args-capture-missing-variables.rs22
-rw-r--r--src/test/ui/fmt/format-args-capture-missing-variables.stderr52
-rw-r--r--src/test/ui/fmt/format-args-capture.rs64
-rw-r--r--src/test/ui/if/ifmt-bad-arg.stderr10
8 files changed, 200 insertions, 0 deletions
diff --git a/src/test/ui/fmt/feature-gate-format-args-capture.rs b/src/test/ui/fmt/feature-gate-format-args-capture.rs
new file mode 100644
index 00000000000..21af9161091
--- /dev/null
+++ b/src/test/ui/fmt/feature-gate-format-args-capture.rs
@@ -0,0 +1,6 @@
+fn main() {
+    format!("{foo}");                //~ ERROR: there is no argument named `foo`
+
+    // panic! doesn't hit format_args! unless there are two or more arguments.
+    panic!("{foo} {bar}", bar=1);    //~ ERROR: there is no argument named `foo`
+}
diff --git a/src/test/ui/fmt/feature-gate-format-args-capture.stderr b/src/test/ui/fmt/feature-gate-format-args-capture.stderr
new file mode 100644
index 00000000000..f08f1651cb6
--- /dev/null
+++ b/src/test/ui/fmt/feature-gate-format-args-capture.stderr
@@ -0,0 +1,18 @@
+error: there is no argument named `foo`
+  --> $DIR/feature-gate-format-args-capture.rs:2:14
+   |
+LL |     format!("{foo}");
+   |              ^^^^^
+   |
+   = help: if you intended to capture `foo` from the surrounding scope, add `#![feature(format_args_capture)]` to the crate attributes
+
+error: there is no argument named `foo`
+  --> $DIR/feature-gate-format-args-capture.rs:5:13
+   |
+LL |     panic!("{foo} {bar}", bar=1);
+   |             ^^^^^
+   |
+   = help: if you intended to capture `foo` from the surrounding scope, add `#![feature(format_args_capture)]` to the crate attributes
+
+error: aborting due to 2 previous errors
+
diff --git a/src/test/ui/fmt/format-args-capture-macro-hygiene.rs b/src/test/ui/fmt/format-args-capture-macro-hygiene.rs
new file mode 100644
index 00000000000..6ca7dcc216f
--- /dev/null
+++ b/src/test/ui/fmt/format-args-capture-macro-hygiene.rs
@@ -0,0 +1,6 @@
+#![feature(format_args_capture)]
+
+fn main() {
+    format!(concat!("{foo}"));         //~ ERROR: there is no argument named `foo`
+    format!(concat!("{ba", "r} {}"), 1);     //~ ERROR: there is no argument named `bar`
+}
diff --git a/src/test/ui/fmt/format-args-capture-macro-hygiene.stderr b/src/test/ui/fmt/format-args-capture-macro-hygiene.stderr
new file mode 100644
index 00000000000..0c5915149cd
--- /dev/null
+++ b/src/test/ui/fmt/format-args-capture-macro-hygiene.stderr
@@ -0,0 +1,22 @@
+error: there is no argument named `foo`
+  --> $DIR/format-args-capture-macro-hygiene.rs:4:13
+   |
+LL |     format!(concat!("{foo}"));
+   |             ^^^^^^^^^^^^^^^^
+   |
+   = note: did you intend to capture a variable `foo` from the surrounding scope?
+   = note: to avoid ambiguity, `format_args!` cannot capture variables when the format string is expanded from a macro
+   = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: there is no argument named `bar`
+  --> $DIR/format-args-capture-macro-hygiene.rs:5:13
+   |
+LL |     format!(concat!("{ba", "r} {}"), 1);
+   |             ^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: did you intend to capture a variable `bar` from the surrounding scope?
+   = note: to avoid ambiguity, `format_args!` cannot capture variables when the format string is expanded from a macro
+   = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: aborting due to 2 previous errors
+
diff --git a/src/test/ui/fmt/format-args-capture-missing-variables.rs b/src/test/ui/fmt/format-args-capture-missing-variables.rs
new file mode 100644
index 00000000000..3c596ae3bb8
--- /dev/null
+++ b/src/test/ui/fmt/format-args-capture-missing-variables.rs
@@ -0,0 +1,22 @@
+#![feature(format_args_capture)]
+
+fn main() {
+    format!("{} {foo} {} {bar} {}", 1, 2, 3);
+    //~^ ERROR: cannot find value `foo` in this scope
+    //~^^ ERROR: cannot find value `bar` in this scope
+
+    format!("{foo}");                //~ ERROR: cannot find value `foo` in this scope
+
+    format!("{valuea} {valueb}", valuea=5, valuec=7);
+    //~^ ERROR cannot find value `valueb` in this scope
+    //~^^ ERROR named argument never used
+
+    format!(r##"
+
+        {foo}
+
+    "##);
+    //~^^^^^ ERROR: cannot find value `foo` in this scope
+
+    panic!("{foo} {bar}", bar=1);    //~ ERROR: cannot find value `foo` in this scope
+}
diff --git a/src/test/ui/fmt/format-args-capture-missing-variables.stderr b/src/test/ui/fmt/format-args-capture-missing-variables.stderr
new file mode 100644
index 00000000000..c3d740eef9d
--- /dev/null
+++ b/src/test/ui/fmt/format-args-capture-missing-variables.stderr
@@ -0,0 +1,52 @@
+error: named argument never used
+  --> $DIR/format-args-capture-missing-variables.rs:10:51
+   |
+LL |     format!("{valuea} {valueb}", valuea=5, valuec=7);
+   |             -------------------                   ^ named argument never used
+   |             |
+   |             formatting specifier missing
+
+error[E0425]: cannot find value `foo` in this scope
+  --> $DIR/format-args-capture-missing-variables.rs:4:13
+   |
+LL |     format!("{} {foo} {} {bar} {}", 1, 2, 3);
+   |             ^^^^^^^^^^^^^^^^^^^^^^ not found in this scope
+
+error[E0425]: cannot find value `bar` in this scope
+  --> $DIR/format-args-capture-missing-variables.rs:4:13
+   |
+LL |     format!("{} {foo} {} {bar} {}", 1, 2, 3);
+   |             ^^^^^^^^^^^^^^^^^^^^^^ not found in this scope
+
+error[E0425]: cannot find value `foo` in this scope
+  --> $DIR/format-args-capture-missing-variables.rs:8:13
+   |
+LL |     format!("{foo}");
+   |             ^^^^^^^ not found in this scope
+
+error[E0425]: cannot find value `valueb` in this scope
+  --> $DIR/format-args-capture-missing-variables.rs:10:13
+   |
+LL |     format!("{valuea} {valueb}", valuea=5, valuec=7);
+   |             ^^^^^^^^^^^^^^^^^^^ not found in this scope
+
+error[E0425]: cannot find value `foo` in this scope
+  --> $DIR/format-args-capture-missing-variables.rs:14:13
+   |
+LL |       format!(r##"
+   |  _____________^
+LL | |
+LL | |         {foo}
+LL | |
+LL | |     "##);
+   | |_______^ not found in this scope
+
+error[E0425]: cannot find value `foo` in this scope
+  --> $DIR/format-args-capture-missing-variables.rs:21:12
+   |
+LL |     panic!("{foo} {bar}", bar=1);
+   |            ^^^^^^^^^^^^^ not found in this scope
+
+error: aborting due to 7 previous errors
+
+For more information about this error, try `rustc --explain E0425`.
diff --git a/src/test/ui/fmt/format-args-capture.rs b/src/test/ui/fmt/format-args-capture.rs
new file mode 100644
index 00000000000..7490632110c
--- /dev/null
+++ b/src/test/ui/fmt/format-args-capture.rs
@@ -0,0 +1,64 @@
+// run-pass
+// ignore-wasm32
+// ignore-wasm64
+#![feature(format_args_capture)]
+
+fn main() {
+    named_argument_takes_precedence_to_captured();
+    panic_with_single_argument_does_not_get_formatted();
+    panic_with_multiple_arguments_is_formatted();
+    formatting_parameters_can_be_captured();
+}
+
+fn named_argument_takes_precedence_to_captured() {
+    let foo = "captured";
+    let s = format!("{foo}", foo="named");
+    assert_eq!(&s, "named");
+
+    let s = format!("{foo}-{foo}-{foo}", foo="named");
+    assert_eq!(&s, "named-named-named");
+
+    let s = format!("{}-{bar}-{foo}", "positional", bar="named");
+    assert_eq!(&s, "positional-named-captured");
+}
+
+fn panic_with_single_argument_does_not_get_formatted() {
+    // panic! with a single argument does not perform string formatting.
+    // RFC #2795 suggests that this may need to change so that captured arguments are formatted.
+    // For stability reasons this will need to part of an edition change.
+
+    let msg = std::panic::catch_unwind(|| {
+        panic!("{foo}");
+    }).unwrap_err();
+
+    assert_eq!(msg.downcast_ref::<&str>(), Some(&"{foo}"))
+}
+
+fn panic_with_multiple_arguments_is_formatted() {
+    let foo = "captured";
+
+    let msg = std::panic::catch_unwind(|| {
+        panic!("{}-{bar}-{foo}", "positional", bar="named");
+    }).unwrap_err();
+
+    assert_eq!(msg.downcast_ref::<String>(), Some(&"positional-named-captured".to_string()))
+}
+
+fn formatting_parameters_can_be_captured() {
+    let width = 9;
+    let precision = 3;
+
+    let x = 7.0;
+
+    let s = format!("{x:width$}");
+    assert_eq!(&s, "        7");
+
+    let s = format!("{x:<width$}");
+    assert_eq!(&s, "7        ");
+
+    let s = format!("{x:-^width$}");
+    assert_eq!(&s, "----7----");
+
+    let s = format!("{x:-^width$.precision$}");
+    assert_eq!(&s, "--7.000--");
+}
diff --git a/src/test/ui/if/ifmt-bad-arg.stderr b/src/test/ui/if/ifmt-bad-arg.stderr
index 3e5f5a63742..0ff478826f7 100644
--- a/src/test/ui/if/ifmt-bad-arg.stderr
+++ b/src/test/ui/if/ifmt-bad-arg.stderr
@@ -63,18 +63,24 @@ error: there is no argument named `foo`
    |
 LL |     format!("{} {foo} {} {bar} {}", 1, 2, 3);
    |                 ^^^^^
+   |
+   = help: if you intended to capture `foo` from the surrounding scope, add `#![feature(format_args_capture)]` to the crate attributes
 
 error: there is no argument named `bar`
   --> $DIR/ifmt-bad-arg.rs:27:26
    |
 LL |     format!("{} {foo} {} {bar} {}", 1, 2, 3);
    |                          ^^^^^
+   |
+   = help: if you intended to capture `bar` from the surrounding scope, add `#![feature(format_args_capture)]` to the crate attributes
 
 error: there is no argument named `foo`
   --> $DIR/ifmt-bad-arg.rs:31:14
    |
 LL |     format!("{foo}");
    |              ^^^^^
+   |
+   = help: if you intended to capture `foo` from the surrounding scope, add `#![feature(format_args_capture)]` to the crate attributes
 
 error: multiple unused formatting arguments
   --> $DIR/ifmt-bad-arg.rs:32:17
@@ -155,6 +161,8 @@ error: there is no argument named `valueb`
    |
 LL |     format!("{valuea} {valueb}", valuea=5, valuec=7);
    |                       ^^^^^^^^
+   |
+   = help: if you intended to capture `valueb` from the surrounding scope, add `#![feature(format_args_capture)]` to the crate attributes
 
 error: named argument never used
   --> $DIR/ifmt-bad-arg.rs:45:51
@@ -205,6 +213,8 @@ error: there is no argument named `foo`
    |
 LL |         {foo}
    |         ^^^^^
+   |
+   = help: if you intended to capture `foo` from the surrounding scope, add `#![feature(format_args_capture)]` to the crate attributes
 
 error: invalid format string: expected `'}'`, found `'t'`
   --> $DIR/ifmt-bad-arg.rs:75:1