about summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2022-02-11 23:01:50 +0000
committerbors <bors@rust-lang.org>2022-02-11 23:01:50 +0000
commitf19851069efd6ee1fe899a469f08ad2d66e76050 (patch)
tree82ccc32c3615e9fcbcf040e3c867b0cc527ce739 /src
parente789f3a3a3d96ebf99b7bbd95011527e5be32a11 (diff)
parentde0feb30bd54fe26e1bb2a0a75ea519708ab8f76 (diff)
downloadrust-f19851069efd6ee1fe899a469f08ad2d66e76050.tar.gz
rust-f19851069efd6ee1fe899a469f08ad2d66e76050.zip
Auto merge of #93921 - matthiaskrgr:rollup-wn3jlxj, r=matthiaskrgr
Rollup of 10 pull requests

Successful merges:

 - #90955 (Rename `FilenameTooLong` to `InvalidFilename` and also use it for Windows' `ERROR_INVALID_NAME`)
 - #91607 (Make `span_extend_to_prev_str()` more robust)
 - #92895 (Remove some unused functionality)
 - #93635 (Add missing platform-specific information on current_dir and set_current_dir)
 - #93660 (rustdoc-json: Add some tests for typealias item)
 - #93782 (Split `pauth` target feature)
 - #93868 (Fix incorrect register conflict detection in asm!)
 - #93888 (Implement `AsFd` for `&T` and `&mut T`.)
 - #93909 (Fix typo: explicitely -> explicitly)
 - #93910 (fix mention of moved function in `rustc_hir` docs)

Failed merges:

r? `@ghost`
`@rustbot` modify labels: rollup
Diffstat (limited to 'src')
-rw-r--r--src/test/rustdoc-json/type/dyn.rs21
-rw-r--r--src/test/rustdoc-json/type/fn_lifetime.rs28
-rw-r--r--src/test/rustdoc-json/type/generic_default.rs33
-rw-r--r--src/test/ui/asm/aarch64/parse-error.stderr14
-rw-r--r--src/test/ui/asm/reg-conflict.rs20
-rw-r--r--src/test/ui/asm/reg-conflict.stderr10
-rw-r--r--src/test/ui/asm/x86_64/parse-error.stderr14
-rw-r--r--src/test/ui/consts/issue-91560.fixed21
-rw-r--r--src/test/ui/consts/issue-91560.rs21
-rw-r--r--src/test/ui/consts/issue-91560.stderr21
-rw-r--r--src/test/ui/target-feature/tied-features-cli.one.stderr4
-rw-r--r--src/test/ui/target-feature/tied-features-cli.rs9
-rw-r--r--src/test/ui/target-feature/tied-features-cli.three.stderr4
-rw-r--r--src/test/ui/target-feature/tied-features-cli.two.stderr4
-rw-r--r--src/test/ui/target-feature/tied-features.rs29
-rw-r--r--src/test/ui/target-feature/tied-features.stderr18
-rw-r--r--src/test/ui/traits/negative-impls/explicitly-unimplemented-error-message.rs8
-rw-r--r--src/test/ui/traits/negative-impls/explicitly-unimplemented-error-message.stderr8
-rw-r--r--src/tools/jsondocck/src/main.rs18
19 files changed, 281 insertions, 24 deletions
diff --git a/src/test/rustdoc-json/type/dyn.rs b/src/test/rustdoc-json/type/dyn.rs
new file mode 100644
index 00000000000..f53dc03f4b4
--- /dev/null
+++ b/src/test/rustdoc-json/type/dyn.rs
@@ -0,0 +1,21 @@
+// ignore-tidy-linelength
+
+// @count dyn.json "$.index[*][?(@.name=='dyn')].inner.items" 1
+// @set sync_int_gen = - "$.index[*][?(@.name=='SyncIntGen')].id"
+// @is - "$.index[*][?(@.name=='dyn')].inner.items[0]" $sync_int_gen
+
+// @is    - "$.index[*][?(@.name=='SyncIntGen')].kind" \"typedef\"
+// @is    - "$.index[*][?(@.name=='SyncIntGen')].inner.generics" '{"params": [], "where_predicates": []}'
+// @is    - "$.index[*][?(@.name=='SyncIntGen')].inner.type.kind" \"resolved_path\"
+// @is    - "$.index[*][?(@.name=='SyncIntGen')].inner.type.inner.name" \"Box\"
+// @is    - "$.index[*][?(@.name=='SyncIntGen')].inner.type.inner.args.angle_bracketed.bindings" []
+// @count - "$.index[*][?(@.name=='SyncIntGen')].inner.type.inner.args.angle_bracketed.args" 1
+// @is    - "$.index[*][?(@.name=='SyncIntGen')].inner.type.inner.args.angle_bracketed.args[0].type.kind" \"resolved_path\"
+// @is    - "$.index[*][?(@.name=='SyncIntGen')].inner.type.inner.args.angle_bracketed.args[0].type.kind" \"resolved_path\"
+// @is    - "$.index[*][?(@.name=='SyncIntGen')].inner.type.inner.args.angle_bracketed.args[0].type.inner.name" \"Fn\"
+// @count - "$.index[*][?(@.name=='SyncIntGen')].inner.type.inner.args.angle_bracketed.args[0].type.inner.param_names[*]" 3
+// @is    - "$.index[*][?(@.name=='SyncIntGen')].inner.type.inner.args.angle_bracketed.args[0].type.inner.param_names[0].trait_bound.trait.inner.name" \"Send\"
+// @is    - "$.index[*][?(@.name=='SyncIntGen')].inner.type.inner.args.angle_bracketed.args[0].type.inner.param_names[1].trait_bound.trait.inner.name" \"Sync\"
+// @is    - "$.index[*][?(@.name=='SyncIntGen')].inner.type.inner.args.angle_bracketed.args[0].type.inner.param_names[2]" "{\"outlives\": \"'static\"}"
+// @is    - "$.index[*][?(@.name=='SyncIntGen')].inner.type.inner.args.angle_bracketed.args[0].type.inner.args" '{"parenthesized": {"inputs": [],"output": {"inner": "i32","kind": "primitive"}}}'
+pub type SyncIntGen = Box<dyn Fn() -> i32 + Send + Sync + 'static>;
diff --git a/src/test/rustdoc-json/type/fn_lifetime.rs b/src/test/rustdoc-json/type/fn_lifetime.rs
new file mode 100644
index 00000000000..e0d1e9649a0
--- /dev/null
+++ b/src/test/rustdoc-json/type/fn_lifetime.rs
@@ -0,0 +1,28 @@
+// ignore-tidy-linelength
+
+// @is fn_lifetime.json "$.index[*][?(@.name=='GenericFn')].kind" \"typedef\"
+
+// @count - "$.index[*][?(@.name=='GenericFn')].inner.generics.params[*]" 1
+// @is    - "$.index[*][?(@.name=='GenericFn')].inner.generics.params[*].name" \"\'a\"
+// @has   - "$.index[*][?(@.name=='GenericFn')].inner.generics.params[*].kind.lifetime"
+// @count - "$.index[*][?(@.name=='GenericFn')].inner.generics.params[*].kind.lifetime.outlives[*]" 0
+// @count - "$.index[*][?(@.name=='GenericFn')].inner.generics.where_predicates[*]" 0
+// @is    - "$.index[*][?(@.name=='GenericFn')].inner.type.kind" \"function_pointer\"
+// @count - "$.index[*][?(@.name=='GenericFn')].inner.type.inner.generic_params[*]" 0
+// @count - "$.index[*][?(@.name=='GenericFn')].inner.type.inner.decl.inputs[*]" 1
+// @is    - "$.index[*][?(@.name=='GenericFn')].inner.type.inner.decl.inputs[*][1].inner.lifetime" \"\'a\"
+// @is    - "$.index[*][?(@.name=='GenericFn')].inner.type.inner.decl.output.inner.lifetime" \"\'a\"
+
+pub type GenericFn<'a> = fn(&'a i32) -> &'a i32;
+
+// @is fn_lifetime.json "$.index[*][?(@.name=='ForAll')].kind" \"typedef\"
+// @count - "$.index[*][?(@.name=='ForAll')].inner.generics.params[*]" 0
+// @count - "$.index[*][?(@.name=='ForAll')].inner.generics.where_predicates[*]" 0
+// @count - "$.index[*][?(@.name=='ForAll')].inner.type.inner.generic_params[*]" 1
+// @is    - "$.index[*][?(@.name=='ForAll')].inner.type.inner.generic_params[*].name" \"\'a\"
+// @has   - "$.index[*][?(@.name=='ForAll')].inner.type.inner.generic_params[*].kind.lifetime"
+// @count - "$.index[*][?(@.name=='ForAll')].inner.type.inner.generic_params[*].kind.lifetime.outlives[*]" 0
+// @count - "$.index[*][?(@.name=='ForAll')].inner.type.inner.decl.inputs[*]" 1
+// @is    - "$.index[*][?(@.name=='ForAll')].inner.type.inner.decl.inputs[*][1].inner.lifetime" \"\'a\"
+// @is    - "$.index[*][?(@.name=='ForAll')].inner.type.inner.decl.output.inner.lifetime" \"\'a\"
+pub type ForAll = for<'a> fn(&'a i32) -> &'a i32;
diff --git a/src/test/rustdoc-json/type/generic_default.rs b/src/test/rustdoc-json/type/generic_default.rs
new file mode 100644
index 00000000000..b6bb6dcc5fe
--- /dev/null
+++ b/src/test/rustdoc-json/type/generic_default.rs
@@ -0,0 +1,33 @@
+// ignore-tidy-linelength
+
+// @set result = generic_default.json "$.index[*][?(@.name=='Result')].id"
+pub enum Result<T, E> {
+    Ok(T),
+    Err(E),
+}
+
+// @set my_error = - "$.index[*][?(@.name=='MyError')].id"
+pub struct MyError {}
+
+// @is    - "$.index[*][?(@.name=='MyResult')].kind" \"typedef\"
+// @count - "$.index[*][?(@.name=='MyResult')].inner.generics.where_predicates[*]" 0
+// @count - "$.index[*][?(@.name=='MyResult')].inner.generics.params[*]" 2
+// @is    - "$.index[*][?(@.name=='MyResult')].inner.generics.params[0].name" \"T\"
+// @is    - "$.index[*][?(@.name=='MyResult')].inner.generics.params[1].name" \"E\"
+// @has   - "$.index[*][?(@.name=='MyResult')].inner.generics.params[0].kind.type"
+// @has   - "$.index[*][?(@.name=='MyResult')].inner.generics.params[1].kind.type"
+// @count - "$.index[*][?(@.name=='MyResult')].inner.generics.params[0].kind.type.bounds[*]" 0
+// @count - "$.index[*][?(@.name=='MyResult')].inner.generics.params[1].kind.type.bounds[*]" 0
+// @is    - "$.index[*][?(@.name=='MyResult')].inner.generics.params[0].kind.type.default" null
+// @is    - "$.index[*][?(@.name=='MyResult')].inner.generics.params[1].kind.type.default.kind" \"resolved_path\"
+// @is    - "$.index[*][?(@.name=='MyResult')].inner.generics.params[1].kind.type.default.inner.id" $my_error
+// @is    - "$.index[*][?(@.name=='MyResult')].inner.generics.params[1].kind.type.default.inner.name" \"MyError\"
+// @is    - "$.index[*][?(@.name=='MyResult')].inner.type.kind" \"resolved_path\"
+// @is    - "$.index[*][?(@.name=='MyResult')].inner.type.inner.id" $result
+// @is    - "$.index[*][?(@.name=='MyResult')].inner.type.inner.name" \"Result\"
+// @is    - "$.index[*][?(@.name=='MyResult')].inner.type.inner.args.angle_bracketed.bindings" []
+// @is    - "$.index[*][?(@.name=='MyResult')].inner.type.inner.args.angle_bracketed.args[0].type.kind" \"generic\"
+// @is    - "$.index[*][?(@.name=='MyResult')].inner.type.inner.args.angle_bracketed.args[1].type.kind" \"generic\"
+// @is    - "$.index[*][?(@.name=='MyResult')].inner.type.inner.args.angle_bracketed.args[0].type.inner" \"T\"
+// @is    - "$.index[*][?(@.name=='MyResult')].inner.type.inner.args.angle_bracketed.args[1].type.inner" \"E\"
+pub type MyResult<T, E = MyError> = Result<T, E>;
diff --git a/src/test/ui/asm/aarch64/parse-error.stderr b/src/test/ui/asm/aarch64/parse-error.stderr
index d80ab921fb8..3f705ba5b64 100644
--- a/src/test/ui/asm/aarch64/parse-error.stderr
+++ b/src/test/ui/asm/aarch64/parse-error.stderr
@@ -382,7 +382,7 @@ error[E0435]: attempt to use a non-constant value in a constant
   --> $DIR/parse-error.rs:39:37
    |
 LL |     let mut foo = 0;
-   |      ---------- help: consider using `const` instead of `let`: `const foo`
+   |     ----------- help: consider using `const` instead of `let`: `const foo`
 ...
 LL |         asm!("{}", options(), const foo);
    |                                     ^^^ non-constant value
@@ -391,7 +391,7 @@ error[E0435]: attempt to use a non-constant value in a constant
   --> $DIR/parse-error.rs:48:44
    |
 LL |     let mut foo = 0;
-   |      ---------- help: consider using `const` instead of `let`: `const foo`
+   |     ----------- help: consider using `const` instead of `let`: `const foo`
 ...
 LL |         asm!("{}", clobber_abi("C"), const foo);
    |                                            ^^^ non-constant value
@@ -400,7 +400,7 @@ error[E0435]: attempt to use a non-constant value in a constant
   --> $DIR/parse-error.rs:55:31
    |
 LL |     let mut foo = 0;
-   |      ---------- help: consider using `const` instead of `let`: `const foo`
+   |     ----------- help: consider using `const` instead of `let`: `const foo`
 ...
 LL |         asm!("{a}", a = const foo, a = const bar);
    |                               ^^^ non-constant value
@@ -409,7 +409,7 @@ error[E0435]: attempt to use a non-constant value in a constant
   --> $DIR/parse-error.rs:55:46
    |
 LL |     let mut bar = 0;
-   |      ---------- help: consider using `const` instead of `let`: `const bar`
+   |     ----------- help: consider using `const` instead of `let`: `const bar`
 ...
 LL |         asm!("{a}", a = const foo, a = const bar);
    |                                              ^^^ non-constant value
@@ -418,7 +418,7 @@ error[E0435]: attempt to use a non-constant value in a constant
   --> $DIR/parse-error.rs:62:45
    |
 LL |     let mut bar = 0;
-   |      ---------- help: consider using `const` instead of `let`: `const bar`
+   |     ----------- help: consider using `const` instead of `let`: `const bar`
 ...
 LL |         asm!("{a}", in("x0") foo, a = const bar);
    |                                             ^^^ non-constant value
@@ -427,7 +427,7 @@ error[E0435]: attempt to use a non-constant value in a constant
   --> $DIR/parse-error.rs:65:45
    |
 LL |     let mut bar = 0;
-   |      ---------- help: consider using `const` instead of `let`: `const bar`
+   |     ----------- help: consider using `const` instead of `let`: `const bar`
 ...
 LL |         asm!("{a}", in("x0") foo, a = const bar);
    |                                             ^^^ non-constant value
@@ -436,7 +436,7 @@ error[E0435]: attempt to use a non-constant value in a constant
   --> $DIR/parse-error.rs:68:41
    |
 LL |     let mut bar = 0;
-   |      ---------- help: consider using `const` instead of `let`: `const bar`
+   |     ----------- help: consider using `const` instead of `let`: `const bar`
 ...
 LL |         asm!("{1}", in("x0") foo, const bar);
    |                                         ^^^ non-constant value
diff --git a/src/test/ui/asm/reg-conflict.rs b/src/test/ui/asm/reg-conflict.rs
new file mode 100644
index 00000000000..983788a93cc
--- /dev/null
+++ b/src/test/ui/asm/reg-conflict.rs
@@ -0,0 +1,20 @@
+// compile-flags: --target armv7-unknown-linux-gnueabihf
+// needs-llvm-components: arm
+
+#![feature(no_core, lang_items, rustc_attrs)]
+#![no_core]
+
+#[rustc_builtin_macro]
+macro_rules! asm {
+    () => {};
+}
+#[lang = "sized"]
+trait Sized {}
+
+fn main() {
+    unsafe {
+        asm!("", out("d0") _, out("d1") _);
+        asm!("", out("d0") _, out("s1") _);
+        //~^ ERROR register `s1` conflicts with register `d0`
+    }
+}
diff --git a/src/test/ui/asm/reg-conflict.stderr b/src/test/ui/asm/reg-conflict.stderr
new file mode 100644
index 00000000000..2395566de39
--- /dev/null
+++ b/src/test/ui/asm/reg-conflict.stderr
@@ -0,0 +1,10 @@
+error: register `s1` conflicts with register `d0`
+  --> $DIR/reg-conflict.rs:17:31
+   |
+LL |         asm!("", out("d0") _, out("s1") _);
+   |                  -----------  ^^^^^^^^^^^ register `s1`
+   |                  |
+   |                  register `d0`
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/asm/x86_64/parse-error.stderr b/src/test/ui/asm/x86_64/parse-error.stderr
index 2d0a7a94d56..194cd66a66e 100644
--- a/src/test/ui/asm/x86_64/parse-error.stderr
+++ b/src/test/ui/asm/x86_64/parse-error.stderr
@@ -394,7 +394,7 @@ error[E0435]: attempt to use a non-constant value in a constant
   --> $DIR/parse-error.rs:39:37
    |
 LL |     let mut foo = 0;
-   |      ---------- help: consider using `const` instead of `let`: `const foo`
+   |     ----------- help: consider using `const` instead of `let`: `const foo`
 ...
 LL |         asm!("{}", options(), const foo);
    |                                     ^^^ non-constant value
@@ -403,7 +403,7 @@ error[E0435]: attempt to use a non-constant value in a constant
   --> $DIR/parse-error.rs:50:44
    |
 LL |     let mut foo = 0;
-   |      ---------- help: consider using `const` instead of `let`: `const foo`
+   |     ----------- help: consider using `const` instead of `let`: `const foo`
 ...
 LL |         asm!("{}", clobber_abi("C"), const foo);
    |                                            ^^^ non-constant value
@@ -412,7 +412,7 @@ error[E0435]: attempt to use a non-constant value in a constant
   --> $DIR/parse-error.rs:57:31
    |
 LL |     let mut foo = 0;
-   |      ---------- help: consider using `const` instead of `let`: `const foo`
+   |     ----------- help: consider using `const` instead of `let`: `const foo`
 ...
 LL |         asm!("{a}", a = const foo, a = const bar);
    |                               ^^^ non-constant value
@@ -421,7 +421,7 @@ error[E0435]: attempt to use a non-constant value in a constant
   --> $DIR/parse-error.rs:57:46
    |
 LL |     let mut bar = 0;
-   |      ---------- help: consider using `const` instead of `let`: `const bar`
+   |     ----------- help: consider using `const` instead of `let`: `const bar`
 ...
 LL |         asm!("{a}", a = const foo, a = const bar);
    |                                              ^^^ non-constant value
@@ -430,7 +430,7 @@ error[E0435]: attempt to use a non-constant value in a constant
   --> $DIR/parse-error.rs:64:46
    |
 LL |     let mut bar = 0;
-   |      ---------- help: consider using `const` instead of `let`: `const bar`
+   |     ----------- help: consider using `const` instead of `let`: `const bar`
 ...
 LL |         asm!("{a}", in("eax") foo, a = const bar);
    |                                              ^^^ non-constant value
@@ -439,7 +439,7 @@ error[E0435]: attempt to use a non-constant value in a constant
   --> $DIR/parse-error.rs:67:46
    |
 LL |     let mut bar = 0;
-   |      ---------- help: consider using `const` instead of `let`: `const bar`
+   |     ----------- help: consider using `const` instead of `let`: `const bar`
 ...
 LL |         asm!("{a}", in("eax") foo, a = const bar);
    |                                              ^^^ non-constant value
@@ -448,7 +448,7 @@ error[E0435]: attempt to use a non-constant value in a constant
   --> $DIR/parse-error.rs:70:42
    |
 LL |     let mut bar = 0;
-   |      ---------- help: consider using `const` instead of `let`: `const bar`
+   |     ----------- help: consider using `const` instead of `let`: `const bar`
 ...
 LL |         asm!("{1}", in("eax") foo, const bar);
    |                                          ^^^ non-constant value
diff --git a/src/test/ui/consts/issue-91560.fixed b/src/test/ui/consts/issue-91560.fixed
new file mode 100644
index 00000000000..41b9d95734a
--- /dev/null
+++ b/src/test/ui/consts/issue-91560.fixed
@@ -0,0 +1,21 @@
+// Regression test for issue #91560.
+
+// run-rustfix
+
+#![allow(unused,non_upper_case_globals)]
+
+fn foo() {
+    const length: usize = 2;
+    //~^ HELP: consider using `const`
+    let arr = [0; length];
+    //~^ ERROR: attempt to use a non-constant value in a constant [E0435]
+}
+
+fn bar() {
+    const length: usize = 2;
+    //~^ HELP: consider using `const`
+    let arr = [0; length];
+    //~^ ERROR: attempt to use a non-constant value in a constant [E0435]
+}
+
+fn main() {}
diff --git a/src/test/ui/consts/issue-91560.rs b/src/test/ui/consts/issue-91560.rs
new file mode 100644
index 00000000000..04592feb505
--- /dev/null
+++ b/src/test/ui/consts/issue-91560.rs
@@ -0,0 +1,21 @@
+// Regression test for issue #91560.
+
+// run-rustfix
+
+#![allow(unused,non_upper_case_globals)]
+
+fn foo() {
+    let mut length: usize = 2;
+    //~^ HELP: consider using `const`
+    let arr = [0; length];
+    //~^ ERROR: attempt to use a non-constant value in a constant [E0435]
+}
+
+fn bar() {
+    let   length: usize = 2;
+    //~^ HELP: consider using `const`
+    let arr = [0; length];
+    //~^ ERROR: attempt to use a non-constant value in a constant [E0435]
+}
+
+fn main() {}
diff --git a/src/test/ui/consts/issue-91560.stderr b/src/test/ui/consts/issue-91560.stderr
new file mode 100644
index 00000000000..e1b5d4cacf8
--- /dev/null
+++ b/src/test/ui/consts/issue-91560.stderr
@@ -0,0 +1,21 @@
+error[E0435]: attempt to use a non-constant value in a constant
+  --> $DIR/issue-91560.rs:10:19
+   |
+LL |     let mut length: usize = 2;
+   |     -------------- help: consider using `const` instead of `let`: `const length`
+LL |
+LL |     let arr = [0; length];
+   |                   ^^^^^^ non-constant value
+
+error[E0435]: attempt to use a non-constant value in a constant
+  --> $DIR/issue-91560.rs:17:19
+   |
+LL |     let   length: usize = 2;
+   |     ------------ help: consider using `const` instead of `let`: `const length`
+LL |
+LL |     let arr = [0; length];
+   |                   ^^^^^^ non-constant value
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0435`.
diff --git a/src/test/ui/target-feature/tied-features-cli.one.stderr b/src/test/ui/target-feature/tied-features-cli.one.stderr
new file mode 100644
index 00000000000..2bc64a76aae
--- /dev/null
+++ b/src/test/ui/target-feature/tied-features-cli.one.stderr
@@ -0,0 +1,4 @@
+error: Target features paca, pacg must all be enabled or disabled together
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/target-feature/tied-features-cli.rs b/src/test/ui/target-feature/tied-features-cli.rs
new file mode 100644
index 00000000000..ea09d4fc460
--- /dev/null
+++ b/src/test/ui/target-feature/tied-features-cli.rs
@@ -0,0 +1,9 @@
+// only-aarch64
+// revisions: one two three four
+//[one] compile-flags: -C target-feature=+paca
+//[two] compile-flags: -C target-feature=-pacg,+pacg
+//[three] compile-flags: -C target-feature=+paca,+pacg,-paca
+//[four] check-pass
+//[four] compile-flags: -C target-feature=-paca,+pacg -C target-feature=+paca
+
+fn main() {}
diff --git a/src/test/ui/target-feature/tied-features-cli.three.stderr b/src/test/ui/target-feature/tied-features-cli.three.stderr
new file mode 100644
index 00000000000..2bc64a76aae
--- /dev/null
+++ b/src/test/ui/target-feature/tied-features-cli.three.stderr
@@ -0,0 +1,4 @@
+error: Target features paca, pacg must all be enabled or disabled together
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/target-feature/tied-features-cli.two.stderr b/src/test/ui/target-feature/tied-features-cli.two.stderr
new file mode 100644
index 00000000000..2bc64a76aae
--- /dev/null
+++ b/src/test/ui/target-feature/tied-features-cli.two.stderr
@@ -0,0 +1,4 @@
+error: Target features paca, pacg must all be enabled or disabled together
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/target-feature/tied-features.rs b/src/test/ui/target-feature/tied-features.rs
new file mode 100644
index 00000000000..86400361db3
--- /dev/null
+++ b/src/test/ui/target-feature/tied-features.rs
@@ -0,0 +1,29 @@
+// only-aarch64
+// build-fail
+
+#![feature(aarch64_target_feature, target_feature_11)]
+
+fn main() {
+    #[target_feature(enable = "pacg")]
+    //~^ ERROR must all be either enabled or disabled together
+    unsafe fn inner() {}
+
+    unsafe {
+        foo();
+        bar();
+        baz();
+        inner();
+    }
+}
+
+#[target_feature(enable = "paca")]
+//~^ ERROR must all be either enabled or disabled together
+unsafe fn foo() {}
+
+
+#[target_feature(enable = "paca,pacg")]
+unsafe fn bar() {}
+
+#[target_feature(enable = "paca")]
+#[target_feature(enable = "pacg")]
+unsafe fn baz() {}
diff --git a/src/test/ui/target-feature/tied-features.stderr b/src/test/ui/target-feature/tied-features.stderr
new file mode 100644
index 00000000000..0b1460e0b75
--- /dev/null
+++ b/src/test/ui/target-feature/tied-features.stderr
@@ -0,0 +1,18 @@
+error: the target features paca, pacg must all be either enabled or disabled together
+  --> $DIR/tied-features.rs:7:5
+   |
+LL |     #[target_feature(enable = "pacg")]
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: add the missing features in a `target_feature` attribute
+
+error: the target features paca, pacg must all be either enabled or disabled together
+  --> $DIR/tied-features.rs:19:1
+   |
+LL | #[target_feature(enable = "paca")]
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: add the missing features in a `target_feature` attribute
+
+error: aborting due to 2 previous errors
+
diff --git a/src/test/ui/traits/negative-impls/explicitly-unimplemented-error-message.rs b/src/test/ui/traits/negative-impls/explicitly-unimplemented-error-message.rs
index 3e336933937..1314f9cb093 100644
--- a/src/test/ui/traits/negative-impls/explicitly-unimplemented-error-message.rs
+++ b/src/test/ui/traits/negative-impls/explicitly-unimplemented-error-message.rs
@@ -34,20 +34,20 @@ fn main() {
     Qux.clone();
     //~^ ERROR no method named `clone` found for struct `Qux`
     //~| NOTE method not found in `Qux`
-    //~| NOTE `Clone` defines an item `clone`, but is explicitely unimplemented
+    //~| NOTE `Clone` defines an item `clone`, but is explicitly unimplemented
 
     0_u32.bar();
     //~^ ERROR no method named `bar` found for type `u32`
     //~| NOTE method not found in `u32`
-    //~| NOTE `Bar` defines an item `bar`, but is explicitely unimplemented
+    //~| NOTE `Bar` defines an item `bar`, but is explicitly unimplemented
 
     Qux.foo();
     //~^ ERROR no method named `foo` found for struct `Qux`
     //~| NOTE method not found in `Qux`
-    //~| NOTE the following traits define an item `foo`, but are explicitely unimplemented
+    //~| NOTE the following traits define an item `foo`, but are explicitly unimplemented
 
     0_u32.foo();
     //~^ ERROR no method named `foo` found for type `u32`
     //~| NOTE method not found in `u32`
-    //~| NOTE `FooBar` defines an item `foo`, but is explicitely unimplemented
+    //~| NOTE `FooBar` defines an item `foo`, but is explicitly unimplemented
 }
diff --git a/src/test/ui/traits/negative-impls/explicitly-unimplemented-error-message.stderr b/src/test/ui/traits/negative-impls/explicitly-unimplemented-error-message.stderr
index 01e36a4a62a..c18abf95083 100644
--- a/src/test/ui/traits/negative-impls/explicitly-unimplemented-error-message.stderr
+++ b/src/test/ui/traits/negative-impls/explicitly-unimplemented-error-message.stderr
@@ -8,7 +8,7 @@ LL |     Qux.clone();
    |         ^^^^^ method not found in `Qux`
    |
    = help: items from traits can only be used if the trait is implemented and in scope
-   = note: the trait `Clone` defines an item `clone`, but is explicitely unimplemented
+   = note: the trait `Clone` defines an item `clone`, but is explicitly unimplemented
 
 error[E0599]: no method named `bar` found for type `u32` in the current scope
   --> $DIR/explicitly-unimplemented-error-message.rs:39:11
@@ -17,7 +17,7 @@ LL |     0_u32.bar();
    |           ^^^ method not found in `u32`
    |
    = help: items from traits can only be used if the trait is implemented and in scope
-   = note: the trait `Bar` defines an item `bar`, but is explicitely unimplemented
+   = note: the trait `Bar` defines an item `bar`, but is explicitly unimplemented
 
 error[E0599]: no method named `foo` found for struct `Qux` in the current scope
   --> $DIR/explicitly-unimplemented-error-message.rs:44:9
@@ -29,7 +29,7 @@ LL |     Qux.foo();
    |         ^^^ method not found in `Qux`
    |
    = help: items from traits can only be used if the trait is implemented and in scope
-   = note: the following traits define an item `foo`, but are explicitely unimplemented:
+   = note: the following traits define an item `foo`, but are explicitly unimplemented:
            Foo
            FooBar
 
@@ -45,7 +45,7 @@ note: `Foo` defines an item `foo`, perhaps you need to implement it
    |
 LL | trait Foo {
    | ^^^^^^^^^
-   = note: the trait `FooBar` defines an item `foo`, but is explicitely unimplemented
+   = note: the trait `FooBar` defines an item `foo`, but is explicitly unimplemented
 
 error: aborting due to 4 previous errors
 
diff --git a/src/tools/jsondocck/src/main.rs b/src/tools/jsondocck/src/main.rs
index b8ea10f3d22..d0f476955e1 100644
--- a/src/tools/jsondocck/src/main.rs
+++ b/src/tools/jsondocck/src/main.rs
@@ -231,7 +231,21 @@ fn check_command(command: Command, cache: &mut Cache) -> Result<(), CkError> {
 
             let val = cache.get_value(&command.args[0])?;
             let results = select(&val, &command.args[1]).unwrap();
-            results.len() == expected
+            let eq = results.len() == expected;
+            if !command.negated && !eq {
+                return Err(CkError::FailedCheck(
+                    format!(
+                        "`{}` matched to `{:?}` with length {}, but expected length {}",
+                        &command.args[1],
+                        results,
+                        results.len(),
+                        expected
+                    ),
+                    command,
+                ));
+            } else {
+                eq
+            }
         }
         CommandKind::Is => {
             // @has <path> <jsonpath> <value> = check *exactly one* item matched by path, and it equals value
@@ -317,6 +331,6 @@ fn string_to_value<'a>(s: &str, cache: &'a Cache) -> Cow<'a, Value> {
             panic!("No variable: `{}`. Current state: `{:?}`", &s[1..], cache.variables)
         }))
     } else {
-        Cow::Owned(serde_json::from_str(s).unwrap())
+        Cow::Owned(serde_json::from_str(s).expect(&format!("Cannot convert `{}` to json", s)))
     }
 }