about summary refs log tree commit diff
path: root/tests/ui/explain
diff options
context:
space:
mode:
authorKivooeo <Kivooeo123@gmail.com>2025-05-06 15:06:45 +0500
committerKivooeo <Kivooeo123@gmail.com>2025-05-06 23:02:47 +0500
commit3c1c0726ad18dc07f3ef9b9465d5997ca13e332c (patch)
tree26a7975d1de350e6328ad3e05f73c2fbd1d250a0 /tests/ui/explain
parent651e9cf327358b28db7e37a2ae61727f4a2ef232 (diff)
downloadrust-3c1c0726ad18dc07f3ef9b9465d5997ca13e332c.tar.gz
rust-3c1c0726ad18dc07f3ef9b9465d5997ca13e332c.zip
added error handle for error code > 9999
Diffstat (limited to 'tests/ui/explain')
-rw-r--r--tests/ui/explain/basic.rs2
-rw-r--r--tests/ui/explain/basic.stdout71
-rw-r--r--tests/ui/explain/error-with-no-explanation.rs3
-rw-r--r--tests/ui/explain/error-with-no-explanation.stderr2
-rw-r--r--tests/ui/explain/invalid-error-code.rs2
-rw-r--r--tests/ui/explain/invalid-error-code.stderr2
-rw-r--r--tests/ui/explain/no-E-prefix.rs2
-rw-r--r--tests/ui/explain/no-E-prefix.stdout57
-rw-r--r--tests/ui/explain/overflow-error-code.rs4
-rw-r--r--tests/ui/explain/overflow-error-code.stderr2
10 files changed, 147 insertions, 0 deletions
diff --git a/tests/ui/explain/basic.rs b/tests/ui/explain/basic.rs
new file mode 100644
index 00000000000..1206c4f95eb
--- /dev/null
+++ b/tests/ui/explain/basic.rs
@@ -0,0 +1,2 @@
+//@ compile-flags: --explain E0591
+//@ check-pass
diff --git a/tests/ui/explain/basic.stdout b/tests/ui/explain/basic.stdout
new file mode 100644
index 00000000000..ef1d866c3ff
--- /dev/null
+++ b/tests/ui/explain/basic.stdout
@@ -0,0 +1,71 @@
+Per [RFC 401][rfc401], if you have a function declaration `foo`:
+
+```
+struct S;
+
+// For the purposes of this explanation, all of these
+// different kinds of `fn` declarations are equivalent:
+
+fn foo(x: S) { /* ... */ }
+extern "C" {
+    fn foo(x: S);
+}
+impl S {
+    fn foo(self) { /* ... */ }
+}
+```
+
+the type of `foo` is **not** `fn(S)`, as one might expect.
+Rather, it is a unique, zero-sized marker type written here as `typeof(foo)`.
+However, `typeof(foo)` can be _coerced_ to a function pointer `fn(S)`,
+so you rarely notice this:
+
+```
+let x: fn(S) = foo; // OK, coerces
+```
+
+The reason that this matter is that the type `fn(S)` is not specific to
+any particular function: it's a function _pointer_. So calling `x()` results
+in a virtual call, whereas `foo()` is statically dispatched, because the type
+of `foo` tells us precisely what function is being called.
+
+As noted above, coercions mean that most code doesn't have to be
+concerned with this distinction. However, you can tell the difference
+when using **transmute** to convert a fn item into a fn pointer.
+
+This is sometimes done as part of an FFI:
+
+```
+extern "C" fn foo(userdata: Box<i32>) {
+    /* ... */
+}
+
+unsafe {
+    let f: extern "C" fn(*mut i32) = transmute(foo);
+    callback(f);
+}
+```
+
+Here, transmute is being used to convert the types of the fn arguments.
+This pattern is incorrect because the type of `foo` is a function **item**
+(`typeof(foo)`), which is zero-sized, and the target type (`fn()`)
+is a function pointer, which is not zero-sized.
+This pattern should be rewritten. There are a few possible ways to do this:
+
+- change the original fn declaration to match the expected signature,
+  and do the cast in the fn body (the preferred option)
+- cast the fn item of a fn pointer before calling transmute, as shown here:
+
+    ```
+    let f: extern "C" fn(*mut i32) = transmute(foo as extern "C" fn(_));
+    let f: extern "C" fn(*mut i32) = transmute(foo as usize); // works too
+    ```
+
+The same applies to transmutes to `*mut fn()`, which were observed in practice.
+Note though that use of this type is generally incorrect.
+The intention is typically to describe a function pointer, but just `fn()`
+alone suffices for that. `*mut fn()` is a pointer to a fn pointer.
+(Since these values are typically just passed to C code, however, this rarely
+makes a difference in practice.)
+
+[rfc401]: https://github.com/rust-lang/rfcs/blob/master/text/0401-coercions.md
diff --git a/tests/ui/explain/error-with-no-explanation.rs b/tests/ui/explain/error-with-no-explanation.rs
new file mode 100644
index 00000000000..383820eb458
--- /dev/null
+++ b/tests/ui/explain/error-with-no-explanation.rs
@@ -0,0 +1,3 @@
+// It's a valid error with no added explanation
+//@ compile-flags: --explain E9999
+//~? ERROR: E9999 is not a valid error code
diff --git a/tests/ui/explain/error-with-no-explanation.stderr b/tests/ui/explain/error-with-no-explanation.stderr
new file mode 100644
index 00000000000..afb738cfecb
--- /dev/null
+++ b/tests/ui/explain/error-with-no-explanation.stderr
@@ -0,0 +1,2 @@
+error: E9999 is not a valid error code
+
diff --git a/tests/ui/explain/invalid-error-code.rs b/tests/ui/explain/invalid-error-code.rs
new file mode 100644
index 00000000000..114118d5196
--- /dev/null
+++ b/tests/ui/explain/invalid-error-code.rs
@@ -0,0 +1,2 @@
+//@ compile-flags: --explain error_code
+//~? ERROR: error_code is not a valid error code
diff --git a/tests/ui/explain/invalid-error-code.stderr b/tests/ui/explain/invalid-error-code.stderr
new file mode 100644
index 00000000000..c33122ea88c
--- /dev/null
+++ b/tests/ui/explain/invalid-error-code.stderr
@@ -0,0 +1,2 @@
+error: error_code is not a valid error code
+
diff --git a/tests/ui/explain/no-E-prefix.rs b/tests/ui/explain/no-E-prefix.rs
new file mode 100644
index 00000000000..39c9122bfe1
--- /dev/null
+++ b/tests/ui/explain/no-E-prefix.rs
@@ -0,0 +1,2 @@
+//@ compile-flags: --explain 425
+//@ check-pass
diff --git a/tests/ui/explain/no-E-prefix.stdout b/tests/ui/explain/no-E-prefix.stdout
new file mode 100644
index 00000000000..756b970aa7e
--- /dev/null
+++ b/tests/ui/explain/no-E-prefix.stdout
@@ -0,0 +1,57 @@
+An unresolved name was used.
+
+Erroneous code examples:
+
+```
+something_that_doesnt_exist::foo;
+// error: unresolved name `something_that_doesnt_exist::foo`
+
+// or:
+
+trait Foo {
+    fn bar() {
+        Self; // error: unresolved name `Self`
+    }
+}
+
+// or:
+
+let x = unknown_variable;  // error: unresolved name `unknown_variable`
+```
+
+Please verify that the name wasn't misspelled and ensure that the
+identifier being referred to is valid for the given situation. Example:
+
+```
+enum something_that_does_exist {
+    Foo,
+}
+```
+
+Or:
+
+```
+mod something_that_does_exist {
+    pub static foo : i32 = 0i32;
+}
+
+something_that_does_exist::foo; // ok!
+```
+
+Or:
+
+```
+let unknown_variable = 12u32;
+let x = unknown_variable; // ok!
+```
+
+If the item is not defined in the current module, it must be imported using a
+`use` statement, like so:
+
+```
+use foo::bar;
+bar();
+```
+
+If the item you are importing is not defined in some super-module of the
+current module, then it must also be declared as public (e.g., `pub fn`).
diff --git a/tests/ui/explain/overflow-error-code.rs b/tests/ui/explain/overflow-error-code.rs
new file mode 100644
index 00000000000..284d5cddb35
--- /dev/null
+++ b/tests/ui/explain/overflow-error-code.rs
@@ -0,0 +1,4 @@
+// Check that we don't crash on error codes exceeding our internal limit.
+// issue: <https://github.com/rust-lang/rust/issues/140647>
+//@ compile-flags: --explain E10000
+//~? ERROR: E10000 is not a valid error code
diff --git a/tests/ui/explain/overflow-error-code.stderr b/tests/ui/explain/overflow-error-code.stderr
new file mode 100644
index 00000000000..67e584ea32e
--- /dev/null
+++ b/tests/ui/explain/overflow-error-code.stderr
@@ -0,0 +1,2 @@
+error: E10000 is not a valid error code
+